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