exec_linux.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. // Copyright 2011 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 linux
  5. package unix
  6. import (
  7. "syscall"
  8. "unsafe"
  9. )
  10. type SysProcAttr struct {
  11. Chroot string // Chroot.
  12. Credential *Credential // Credential.
  13. Ptrace bool // Enable tracing.
  14. Setsid bool // Create session.
  15. Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
  16. Setctty bool // Set controlling terminal to fd Ctty (only meaningful if Setsid is set)
  17. Noctty bool // Detach fd 0 from controlling terminal
  18. Ctty int // Controlling TTY fd (Linux only)
  19. Pdeathsig syscall.Signal // Signal that the process will get when its parent dies (Linux only)
  20. Cloneflags uintptr // Flags for clone calls (Linux only)
  21. }
  22. // Implemented in runtime package.
  23. func runtime_BeforeFork()
  24. func runtime_AfterFork()
  25. // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
  26. // If a dup or exec fails, write the errno error to pipe.
  27. // (Pipe is close-on-exec so if exec succeeds, it will be closed.)
  28. // In the child, this function must not acquire any locks, because
  29. // they might have been locked at the time of the fork. This means
  30. // no rescheduling, no malloc calls, and no new stack segments.
  31. // For the same reason compiler does not race instrument it.
  32. // The calls to RawSyscall are okay because they are assembly
  33. // functions that do not grow the stack.
  34. func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err syscall.Errno) {
  35. // Declare all variables at top in case any
  36. // declarations require heap allocation (e.g., err1).
  37. var (
  38. r1 uintptr
  39. err1 syscall.Errno
  40. nextfd int
  41. i int
  42. )
  43. // Guard against side effects of shuffling fds below.
  44. // Make sure that nextfd is beyond any currently open files so
  45. // that we can't run the risk of overwriting any of them.
  46. fd := make([]int, len(attr.Files))
  47. nextfd = len(attr.Files)
  48. for i, ufd := range attr.Files {
  49. if nextfd < int(ufd) {
  50. nextfd = int(ufd)
  51. }
  52. fd[i] = int(ufd)
  53. }
  54. nextfd++
  55. // About to call fork.
  56. // No more allocation or calls of non-assembly functions.
  57. runtime_BeforeFork()
  58. r1, _, err1 = RawSyscall6(SYS_CLONE, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0, 0)
  59. if err1 != 0 {
  60. runtime_AfterFork()
  61. return 0, err1
  62. }
  63. if r1 != 0 {
  64. // parent; return PID
  65. runtime_AfterFork()
  66. return int(r1), 0
  67. }
  68. // Fork succeeded, now in child.
  69. // Parent death signal
  70. if sys.Pdeathsig != 0 {
  71. _, _, err1 = RawSyscall6(SYS_PRCTL, PR_SET_PDEATHSIG, uintptr(sys.Pdeathsig), 0, 0, 0, 0)
  72. if err1 != 0 {
  73. goto childerror
  74. }
  75. // Signal self if parent is already dead. This might cause a
  76. // duplicate signal in rare cases, but it won't matter when
  77. // using SIGKILL.
  78. r1, _, _ = RawSyscall(SYS_GETPPID, 0, 0, 0)
  79. if r1 == 1 {
  80. pid, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
  81. _, _, err1 := RawSyscall(SYS_KILL, pid, uintptr(sys.Pdeathsig), 0)
  82. if err1 != 0 {
  83. goto childerror
  84. }
  85. }
  86. }
  87. // Enable tracing if requested.
  88. if sys.Ptrace {
  89. _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
  90. if err1 != 0 {
  91. goto childerror
  92. }
  93. }
  94. // Session ID
  95. if sys.Setsid {
  96. _, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
  97. if err1 != 0 {
  98. goto childerror
  99. }
  100. }
  101. // Set process group
  102. if sys.Setpgid {
  103. _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
  104. if err1 != 0 {
  105. goto childerror
  106. }
  107. }
  108. // Chroot
  109. if chroot != nil {
  110. _, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
  111. if err1 != 0 {
  112. goto childerror
  113. }
  114. }
  115. // User and groups
  116. if cred := sys.Credential; cred != nil {
  117. ngroups := uintptr(len(cred.Groups))
  118. var groups unsafe.Pointer
  119. if ngroups > 0 {
  120. groups = unsafe.Pointer(&cred.Groups[0])
  121. }
  122. _, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, uintptr(groups), 0)
  123. if err1 != 0 {
  124. goto childerror
  125. }
  126. _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
  127. if err1 != 0 {
  128. goto childerror
  129. }
  130. _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
  131. if err1 != 0 {
  132. goto childerror
  133. }
  134. }
  135. // Chdir
  136. if dir != nil {
  137. _, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
  138. if err1 != 0 {
  139. goto childerror
  140. }
  141. }
  142. // Pass 1: look for fd[i] < i and move those up above len(fd)
  143. // so that pass 2 won't stomp on an fd it needs later.
  144. if pipe < nextfd {
  145. _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
  146. if err1 != 0 {
  147. goto childerror
  148. }
  149. RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
  150. pipe = nextfd
  151. nextfd++
  152. }
  153. for i = 0; i < len(fd); i++ {
  154. if fd[i] >= 0 && fd[i] < int(i) {
  155. _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
  156. if err1 != 0 {
  157. goto childerror
  158. }
  159. RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
  160. fd[i] = nextfd
  161. nextfd++
  162. if nextfd == pipe { // don't stomp on pipe
  163. nextfd++
  164. }
  165. }
  166. }
  167. // Pass 2: dup fd[i] down onto i.
  168. for i = 0; i < len(fd); i++ {
  169. if fd[i] == -1 {
  170. RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
  171. continue
  172. }
  173. if fd[i] == int(i) {
  174. // dup2(i, i) won't clear close-on-exec flag on Linux,
  175. // probably not elsewhere either.
  176. _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
  177. if err1 != 0 {
  178. goto childerror
  179. }
  180. continue
  181. }
  182. // The new fd is created NOT close-on-exec,
  183. // which is exactly what we want.
  184. _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
  185. if err1 != 0 {
  186. goto childerror
  187. }
  188. }
  189. // By convention, we don't close-on-exec the fds we are
  190. // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
  191. // Programs that know they inherit fds >= 3 will need
  192. // to set them close-on-exec.
  193. for i = len(fd); i < 3; i++ {
  194. RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
  195. }
  196. // Detach fd 0 from tty
  197. if sys.Noctty {
  198. _, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
  199. if err1 != 0 {
  200. goto childerror
  201. }
  202. }
  203. // Set the controlling TTY to Ctty
  204. if sys.Setctty && sys.Ctty >= 0 {
  205. _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
  206. if err1 != 0 {
  207. goto childerror
  208. }
  209. }
  210. // Time to exec.
  211. _, _, err1 = RawSyscall(SYS_EXECVE,
  212. uintptr(unsafe.Pointer(argv0)),
  213. uintptr(unsafe.Pointer(&argv[0])),
  214. uintptr(unsafe.Pointer(&envv[0])))
  215. childerror:
  216. // send error code on pipe
  217. RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
  218. for {
  219. RawSyscall(SYS_EXIT, 253, 0, 0)
  220. }
  221. }
  222. // Try to open a pipe with O_CLOEXEC set on both file descriptors.
  223. func forkExecPipe(p []int) (err error) {
  224. err = Pipe2(p, O_CLOEXEC)
  225. // pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it
  226. // might not be implemented.
  227. if err == ENOSYS {
  228. if err = Pipe(p); err != nil {
  229. return
  230. }
  231. if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil {
  232. return
  233. }
  234. _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
  235. }
  236. return
  237. }