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