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 }