github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/src/syscall/exec_unix.go (about) 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 dragonfly freebsd linux netbsd openbsd solaris 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 // StringSlicePtr is deprecated. Use SlicePtrFromStrings instead. 67 // If any string contains a NUL byte this function panics instead 68 // of returning an error. 69 func StringSlicePtr(ss []string) []*byte { 70 bb := make([]*byte, len(ss)+1) 71 for i := 0; i < len(ss); i++ { 72 bb[i] = StringBytePtr(ss[i]) 73 } 74 bb[len(ss)] = nil 75 return bb 76 } 77 78 // SlicePtrFromStrings converts a slice of strings to a slice of 79 // pointers to NUL-terminated byte slices. If any string contains 80 // a NUL byte, it returns (nil, EINVAL). 81 func SlicePtrFromStrings(ss []string) ([]*byte, error) { 82 var err error 83 bb := make([]*byte, len(ss)+1) 84 for i := 0; i < len(ss); i++ { 85 bb[i], err = BytePtrFromString(ss[i]) 86 if err != nil { 87 return nil, err 88 } 89 } 90 bb[len(ss)] = nil 91 return bb, nil 92 } 93 94 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } 95 96 func SetNonblock(fd int, nonblocking bool) (err error) { 97 flag, err := fcntl(fd, F_GETFL, 0) 98 if err != nil { 99 return err 100 } 101 if nonblocking { 102 flag |= O_NONBLOCK 103 } else { 104 flag &= ^O_NONBLOCK 105 } 106 _, err = fcntl(fd, F_SETFL, flag) 107 return err 108 } 109 110 // Credential holds user and group identities to be assumed 111 // by a child process started by StartProcess. 112 type Credential struct { 113 Uid uint32 // User ID. 114 Gid uint32 // Group ID. 115 Groups []uint32 // Supplementary group IDs. 116 } 117 118 // ProcAttr holds attributes that will be applied to a new process started 119 // by StartProcess. 120 type ProcAttr struct { 121 Dir string // Current working directory. 122 Env []string // Environment. 123 Files []uintptr // File descriptors. 124 Sys *SysProcAttr 125 } 126 127 var zeroProcAttr ProcAttr 128 var zeroSysProcAttr SysProcAttr 129 130 func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) { 131 var p [2]int 132 var n int 133 var err1 Errno 134 var wstatus WaitStatus 135 136 if attr == nil { 137 attr = &zeroProcAttr 138 } 139 sys := attr.Sys 140 if sys == nil { 141 sys = &zeroSysProcAttr 142 } 143 144 p[0] = -1 145 p[1] = -1 146 147 // Convert args to C form. 148 argv0p, err := BytePtrFromString(argv0) 149 if err != nil { 150 return 0, err 151 } 152 argvp, err := SlicePtrFromStrings(argv) 153 if err != nil { 154 return 0, err 155 } 156 envvp, err := SlicePtrFromStrings(attr.Env) 157 if err != nil { 158 return 0, err 159 } 160 161 if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv[0]) > len(argv0) { 162 argvp[0] = argv0p 163 } 164 165 var chroot *byte 166 if sys.Chroot != "" { 167 chroot, err = BytePtrFromString(sys.Chroot) 168 if err != nil { 169 return 0, err 170 } 171 } 172 var dir *byte 173 if attr.Dir != "" { 174 dir, err = BytePtrFromString(attr.Dir) 175 if err != nil { 176 return 0, err 177 } 178 } 179 180 // Acquire the fork lock so that no other threads 181 // create new fds that are not yet close-on-exec 182 // before we fork. 183 ForkLock.Lock() 184 185 // Allocate child status pipe close on exec. 186 if err = forkExecPipe(p[:]); err != nil { 187 goto error 188 } 189 190 // Kick off child. 191 pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1]) 192 if err1 != 0 { 193 err = Errno(err1) 194 goto error 195 } 196 ForkLock.Unlock() 197 198 // Read child error status from pipe. 199 Close(p[1]) 200 n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1))) 201 Close(p[0]) 202 if err != nil || n != 0 { 203 if n == int(unsafe.Sizeof(err1)) { 204 err = Errno(err1) 205 } 206 if err == nil { 207 err = EPIPE 208 } 209 210 // Child failed; wait for it to exit, to make sure 211 // the zombies don't accumulate. 212 _, err1 := Wait4(pid, &wstatus, 0, nil) 213 for err1 == EINTR { 214 _, err1 = Wait4(pid, &wstatus, 0, nil) 215 } 216 return 0, err 217 } 218 219 // Read got EOF, so pipe closed on exec, so exec succeeded. 220 return pid, nil 221 222 error: 223 if p[0] >= 0 { 224 Close(p[0]) 225 Close(p[1]) 226 } 227 ForkLock.Unlock() 228 return 0, err 229 } 230 231 // Combination of fork and exec, careful to be thread safe. 232 func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) { 233 return forkExec(argv0, argv, attr) 234 } 235 236 // StartProcess wraps ForkExec for package os. 237 func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) { 238 pid, err = forkExec(argv0, argv, attr) 239 return pid, 0, err 240 } 241 242 // Ordinary exec. 243 func Exec(argv0 string, argv []string, envv []string) (err error) { 244 argv0p, err := BytePtrFromString(argv0) 245 if err != nil { 246 return err 247 } 248 argvp, err := SlicePtrFromStrings(argv) 249 if err != nil { 250 return err 251 } 252 envvp, err := SlicePtrFromStrings(envv) 253 if err != nil { 254 return err 255 } 256 _, _, err1 := RawSyscall(SYS_EXECVE, 257 uintptr(unsafe.Pointer(argv0p)), 258 uintptr(unsafe.Pointer(&argvp[0])), 259 uintptr(unsafe.Pointer(&envvp[0]))) 260 return Errno(err1) 261 }