exec_unix.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build darwin dragonfly freebsd linux netbsd openbsd solaris
  5. // Fork, exec, wait, etc.
  6. package unix
  7. import (
  8. "runtime"
  9. "sync"
  10. "syscall"
  11. "unsafe"
  12. )
  13. // Lock synchronizing creation of new file descriptors with fork.
  14. //
  15. // We want the child in a fork/exec sequence to inherit only the
  16. // file descriptors we intend. To do that, we mark all file
  17. // descriptors close-on-exec and then, in the child, explicitly
  18. // unmark the ones we want the exec'ed program to keep.
  19. // Unix doesn't make this easy: there is, in general, no way to
  20. // allocate a new file descriptor close-on-exec. Instead you
  21. // have to allocate the descriptor and then mark it close-on-exec.
  22. // If a fork happens between those two events, the child's exec
  23. // will inherit an unwanted file descriptor.
  24. //
  25. // This lock solves that race: the create new fd/mark close-on-exec
  26. // operation is done holding ForkLock for reading, and the fork itself
  27. // is done holding ForkLock for writing. At least, that's the idea.
  28. // There are some complications.
  29. //
  30. // Some system calls that create new file descriptors can block
  31. // for arbitrarily long times: open on a hung NFS server or named
  32. // pipe, accept on a socket, and so on. We can't reasonably grab
  33. // the lock across those operations.
  34. //
  35. // It is worse to inherit some file descriptors than others.
  36. // If a non-malicious child accidentally inherits an open ordinary file,
  37. // that's not a big deal. On the other hand, if a long-lived child
  38. // accidentally inherits the write end of a pipe, then the reader
  39. // of that pipe will not see EOF until that child exits, potentially
  40. // causing the parent program to hang. This is a common problem
  41. // in threaded C programs that use popen.
  42. //
  43. // Luckily, the file descriptors that are most important not to
  44. // inherit are not the ones that can take an arbitrarily long time
  45. // to create: pipe returns instantly, and the net package uses
  46. // non-blocking I/O to accept on a listening socket.
  47. // The rules for which file descriptor-creating operations use the
  48. // ForkLock are as follows:
  49. //
  50. // 1) Pipe. Does not block. Use the ForkLock.
  51. // 2) Socket. Does not block. Use the ForkLock.
  52. // 3) Accept. If using non-blocking mode, use the ForkLock.
  53. // Otherwise, live with the race.
  54. // 4) Open. Can block. Use O_CLOEXEC if available (Linux).
  55. // Otherwise, live with the race.
  56. // 5) Dup. Does not block. Use the ForkLock.
  57. // On Linux, could use fcntl F_DUPFD_CLOEXEC
  58. // instead of the ForkLock, but only for dup(fd, -1).
  59. var ForkLock sync.RWMutex
  60. // SlicePtrFromStrings converts a slice of strings to a slice of
  61. // pointers to NUL-terminated byte slices. If any string contains
  62. // a NUL byte, it returns (nil, EINVAL).
  63. func SlicePtrFromStrings(ss []string) ([]*byte, error) {
  64. var err error
  65. bb := make([]*byte, len(ss)+1)
  66. for i := 0; i < len(ss); i++ {
  67. bb[i], err = BytePtrFromString(ss[i])
  68. if err != nil {
  69. return nil, err
  70. }
  71. }
  72. bb[len(ss)] = nil
  73. return bb, nil
  74. }
  75. func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
  76. func SetNonblock(fd int, nonblocking bool) (err error) {
  77. flag, err := fcntl(fd, F_GETFL, 0)
  78. if err != nil {
  79. return err
  80. }
  81. if nonblocking {
  82. flag |= O_NONBLOCK
  83. } else {
  84. flag &= ^O_NONBLOCK
  85. }
  86. _, err = fcntl(fd, F_SETFL, flag)
  87. return err
  88. }
  89. // Credential holds user and group identities to be assumed
  90. // by a child process started by StartProcess.
  91. type Credential struct {
  92. Uid uint32 // User ID.
  93. Gid uint32 // Group ID.
  94. Groups []uint32 // Supplementary group IDs.
  95. }
  96. // ProcAttr holds attributes that will be applied to a new process started
  97. // by StartProcess.
  98. type ProcAttr struct {
  99. Dir string // Current working directory.
  100. Env []string // Environment.
  101. Files []uintptr // File descriptors.
  102. Sys *SysProcAttr
  103. }
  104. var zeroProcAttr ProcAttr
  105. var zeroSysProcAttr SysProcAttr
  106. func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
  107. var p [2]int
  108. var n int
  109. var err1 syscall.Errno
  110. var wstatus WaitStatus
  111. if attr == nil {
  112. attr = &zeroProcAttr
  113. }
  114. sys := attr.Sys
  115. if sys == nil {
  116. sys = &zeroSysProcAttr
  117. }
  118. p[0] = -1
  119. p[1] = -1
  120. // Convert args to C form.
  121. argv0p, err := BytePtrFromString(argv0)
  122. if err != nil {
  123. return 0, err
  124. }
  125. argvp, err := SlicePtrFromStrings(argv)
  126. if err != nil {
  127. return 0, err
  128. }
  129. envvp, err := SlicePtrFromStrings(attr.Env)
  130. if err != nil {
  131. return 0, err
  132. }
  133. if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv[0]) > len(argv0) {
  134. argvp[0] = argv0p
  135. }
  136. var chroot *byte
  137. if sys.Chroot != "" {
  138. chroot, err = BytePtrFromString(sys.Chroot)
  139. if err != nil {
  140. return 0, err
  141. }
  142. }
  143. var dir *byte
  144. if attr.Dir != "" {
  145. dir, err = BytePtrFromString(attr.Dir)
  146. if err != nil {
  147. return 0, err
  148. }
  149. }
  150. // Acquire the fork lock so that no other threads
  151. // create new fds that are not yet close-on-exec
  152. // before we fork.
  153. ForkLock.Lock()
  154. // Allocate child status pipe close on exec.
  155. if err = forkExecPipe(p[:]); err != nil {
  156. goto error
  157. }
  158. // Kick off child.
  159. pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
  160. if err1 != 0 {
  161. err = syscall.Errno(err1)
  162. goto error
  163. }
  164. ForkLock.Unlock()
  165. // Read child error status from pipe.
  166. Close(p[1])
  167. n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
  168. Close(p[0])
  169. if err != nil || n != 0 {
  170. if n == int(unsafe.Sizeof(err1)) {
  171. err = syscall.Errno(err1)
  172. }
  173. if err == nil {
  174. err = EPIPE
  175. }
  176. // Child failed; wait for it to exit, to make sure
  177. // the zombies don't accumulate.
  178. _, err1 := Wait4(pid, &wstatus, 0, nil)
  179. for err1 == EINTR {
  180. _, err1 = Wait4(pid, &wstatus, 0, nil)
  181. }
  182. return 0, err
  183. }
  184. // Read got EOF, so pipe closed on exec, so exec succeeded.
  185. return pid, nil
  186. error:
  187. if p[0] >= 0 {
  188. Close(p[0])
  189. Close(p[1])
  190. }
  191. ForkLock.Unlock()
  192. return 0, err
  193. }
  194. // Combination of fork and exec, careful to be thread safe.
  195. func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
  196. return forkExec(argv0, argv, attr)
  197. }
  198. // StartProcess wraps ForkExec for package os.
  199. func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
  200. pid, err = forkExec(argv0, argv, attr)
  201. return pid, 0, err
  202. }
  203. // Ordinary exec.
  204. func Exec(argv0 string, argv []string, envv []string) (err error) {
  205. argv0p, err := BytePtrFromString(argv0)
  206. if err != nil {
  207. return err
  208. }
  209. argvp, err := SlicePtrFromStrings(argv)
  210. if err != nil {
  211. return err
  212. }
  213. envvp, err := SlicePtrFromStrings(envv)
  214. if err != nil {
  215. return err
  216. }
  217. _, _, err1 := RawSyscall(SYS_EXECVE,
  218. uintptr(unsafe.Pointer(argv0p)),
  219. uintptr(unsafe.Pointer(&argvp[0])),
  220. uintptr(unsafe.Pointer(&envvp[0])))
  221. return syscall.Errno(err1)
  222. }