OSDN Git Service

Solaris/Irix compatibility patches.
[pf3gnuchains/gcc-fork.git] / libgo / go / 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 openbsd
6
7 // Fork, exec, wait, etc.
8
9 package syscall
10
11 import (
12         "sync"
13         "unsafe"
14 )
15
16 //sysnb raw_fork() (pid Pid_t, errno int)
17 //fork() Pid_t
18
19 //sysnb raw_setsid() (errno int)
20 //setsid() Pid_t
21
22 //sysnb raw_chroot(path *byte) (errno int)
23 //chroot(path *byte) int
24
25 //sysnb raw_chdir(path *byte) (errno int)
26 //chdir(path *byte) int
27
28 //sysnb raw_fcntl(fd int, cmd int, arg int) (val int, errno int)
29 //fcntl(fd int, cmd int, arg int) int
30
31 //sysnb raw_close(fd int) (errno int)
32 //close(fd int) int
33
34 //sysnb raw_ioctl(fd int, cmd int, val int) (rval int, errno int)
35 //ioctl(fd int, cmd int, val int) int
36
37 //sysnb raw_execve(argv0 *byte, argv **byte, envv **byte) (errno int)
38 //execve(argv0 *byte, argv **byte, envv **byte) int
39
40 //sysnb raw_read(fd int, p *byte, np int) (n int, errno int)
41 //read(fd int, buf *byte, count Size_t) Ssize_t
42
43 //sysnb raw_write(fd int, buf *byte, count int) int
44 //write(fd int, buf *byte, count Size_t) Ssize_t
45
46 //sysnb raw_exit(status int)
47 //_exit(status int)
48
49 // Lock synchronizing creation of new file descriptors with fork.
50 //
51 // We want the child in a fork/exec sequence to inherit only the
52 // file descriptors we intend.  To do that, we mark all file
53 // descriptors close-on-exec and then, in the child, explicitly
54 // unmark the ones we want the exec'ed program to keep.
55 // Unix doesn't make this easy: there is, in general, no way to
56 // allocate a new file descriptor close-on-exec.  Instead you
57 // have to allocate the descriptor and then mark it close-on-exec.
58 // If a fork happens between those two events, the child's exec
59 // will inherit an unwanted file descriptor.
60 //
61 // This lock solves that race: the create new fd/mark close-on-exec
62 // operation is done holding ForkLock for reading, and the fork itself
63 // is done holding ForkLock for writing.  At least, that's the idea.
64 // There are some complications.
65 //
66 // Some system calls that create new file descriptors can block
67 // for arbitrarily long times: open on a hung NFS server or named
68 // pipe, accept on a socket, and so on.  We can't reasonably grab
69 // the lock across those operations.
70 //
71 // It is worse to inherit some file descriptors than others.
72 // If a non-malicious child accidentally inherits an open ordinary file,
73 // that's not a big deal.  On the other hand, if a long-lived child
74 // accidentally inherits the write end of a pipe, then the reader
75 // of that pipe will not see EOF until that child exits, potentially
76 // causing the parent program to hang.  This is a common problem
77 // in threaded C programs that use popen.
78 //
79 // Luckily, the file descriptors that are most important not to
80 // inherit are not the ones that can take an arbitrarily long time
81 // to create: pipe returns instantly, and the net package uses
82 // non-blocking I/O to accept on a listening socket.
83 // The rules for which file descriptor-creating operations use the
84 // ForkLock are as follows:
85 //
86 // 1) Pipe.    Does not block.  Use the ForkLock.
87 // 2) Socket.  Does not block.  Use the ForkLock.
88 // 3) Accept.  If using non-blocking mode, use the ForkLock.
89 //             Otherwise, live with the race.
90 // 4) Open.    Can block.  Use O_CLOEXEC if available (Linux).
91 //             Otherwise, live with the race.
92 // 5) Dup.     Does not block.  Use the ForkLock.
93 //             On Linux, could use fcntl F_DUPFD_CLOEXEC
94 //             instead of the ForkLock, but only for dup(fd, -1).
95
96 var ForkLock sync.RWMutex
97
98 // Convert array of string to array
99 // of NUL-terminated byte pointer.
100 func StringSlicePtr(ss []string) []*byte {
101         bb := make([]*byte, len(ss)+1)
102         for i := 0; i < len(ss); i++ {
103                 bb[i] = StringBytePtr(ss[i])
104         }
105         bb[len(ss)] = nil
106         return bb
107 }
108
109 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
110
111 func SetNonblock(fd int, nonblocking bool) (errno int) {
112         flag, err := fcntl(fd, F_GETFL, 0)
113         if err != 0 {
114                 return err
115         }
116         if nonblocking {
117                 flag |= O_NONBLOCK
118         } else {
119                 flag &= ^O_NONBLOCK
120         }
121         _, err = fcntl(fd, F_SETFL, flag)
122         return err
123 }
124
125 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
126 // If a dup or exec fails, write the errno int to pipe.
127 // (Pipe is close-on-exec so if exec succeeds, it will be closed.)
128 // In the child, this function must not acquire any locks, because
129 // they might have been locked at the time of the fork.  This means
130 // no rescheduling, no malloc calls, and no new stack segments.
131 // The calls to RawSyscall are okay because they are assembly
132 // functions that do not grow the stack.
133 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) {
134         // Declare all variables at top in case any
135         // declarations require heap allocation (e.g., err1).
136         var r1 Pid_t
137         var err1 int
138         var nextfd int
139         var i int
140
141         // guard against side effects of shuffling fds below.
142         fd := append([]int(nil), attr.Files...)
143
144         // About to call fork.
145         // No more allocation or calls of non-assembly functions.
146         r1, err1 = raw_fork()
147         if err1 != 0 {
148                 return 0, int(err1)
149         }
150
151         if r1 != 0 {
152                 // parent; return PID
153                 return int(r1), 0
154         }
155
156         // Fork succeeded, now in child.
157
158         // Enable tracing if requested.
159         if sys.Ptrace {
160                 err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
161                 if err1 != 0 {
162                         goto childerror
163                 }
164         }
165
166         // Session ID
167         if sys.Setsid {
168                 err1 = raw_setsid()
169                 if err1 != 0 {
170                         goto childerror
171                 }
172         }
173
174         // Set process group
175         if sys.Setpgid {
176                 err1 = Setpgid(0, 0)
177                 if err1 != 0 {
178                         goto childerror
179                 }
180         }
181
182         // Chroot
183         if chroot != nil {
184                 err1 = raw_chroot(chroot)
185                 if err1 != 0 {
186                         goto childerror
187                 }
188         }
189
190         // User and groups
191         if cred := sys.Credential; cred != nil {
192                 ngroups := len(cred.Groups)
193                 if ngroups == 0 {
194                         err1 = setgroups(0, nil)
195                 } else {
196                         groups := make([]Gid_t, ngroups)
197                         for i, v := range cred.Groups {
198                                 groups[i] = Gid_t(v)
199                         }
200                         err1 = setgroups(ngroups, &groups[0])
201                 }
202                 if err1 != 0 {
203                         goto childerror
204                 }
205                 err1 = Setgid(int(cred.Gid))
206                 if err1 != 0 {
207                         goto childerror
208                 }
209                 err1 = Setuid(int(cred.Uid))
210                 if err1 != 0 {
211                         goto childerror
212                 }
213         }
214
215         // Chdir
216         if dir != nil {
217                 err1 = raw_chdir(dir)
218                 if err1 != 0 {
219                         goto childerror
220                 }
221         }
222
223         // Pass 1: look for fd[i] < i and move those up above len(fd)
224         // so that pass 2 won't stomp on an fd it needs later.
225         nextfd = int(len(fd))
226         if pipe < nextfd {
227                 _, err1 = Dup2(pipe, nextfd)
228                 if err1 != 0 {
229                         goto childerror
230                 }
231                 raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
232                 pipe = nextfd
233                 nextfd++
234         }
235         for i = 0; i < len(fd); i++ {
236                 if fd[i] >= 0 && fd[i] < int(i) {
237                         _, err1 = Dup2(fd[i], nextfd)
238                         if err1 != 0 {
239                                 goto childerror
240                         }
241                         raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
242                         fd[i] = nextfd
243                         nextfd++
244                         if nextfd == pipe { // don't stomp on pipe
245                                 nextfd++
246                         }
247                 }
248         }
249
250         // Pass 2: dup fd[i] down onto i.
251         for i = 0; i < len(fd); i++ {
252                 if fd[i] == -1 {
253                         raw_close(i)
254                         continue
255                 }
256                 if fd[i] == int(i) {
257                         // Dup2(i, i) won't clear close-on-exec flag on Linux,
258                         // probably not elsewhere either.
259                         _, err1 = raw_fcntl(fd[i], F_SETFD, 0)
260                         if err1 != 0 {
261                                 goto childerror
262                         }
263                         continue
264                 }
265                 // The new fd is created NOT close-on-exec,
266                 // which is exactly what we want.
267                 _, err1 = Dup2(fd[i], i)
268                 if err1 != 0 {
269                         goto childerror
270                 }
271         }
272
273         // By convention, we don't close-on-exec the fds we are
274         // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
275         // Programs that know they inherit fds >= 3 will need
276         // to set them close-on-exec.
277         for i = len(fd); i < 3; i++ {
278                 raw_close(i)
279         }
280
281         // Detach fd 0 from tty
282         if sys.Noctty {
283                 _, err1 = raw_ioctl(0, TIOCNOTTY, 0)
284                 if err1 != 0 {
285                         goto childerror
286                 }
287         }
288
289         // Make fd 0 the tty
290         if sys.Setctty {
291                 _, err1 = raw_ioctl(0, TIOCSCTTY, 0)
292                 if err1 != 0 {
293                         goto childerror
294                 }
295         }
296
297         // Time to exec.
298         err1 = raw_execve(argv0, &argv[0], &envv[0])
299
300 childerror:
301         // send error code on pipe
302         raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
303         for {
304                 raw_exit(253)
305         }
306
307         // Calling panic is not actually safe,
308         // but the for loop above won't break
309         // and this shuts up the compiler.
310         panic("unreached")
311 }
312
313 // Credential holds user and group identities to be assumed
314 // by a child process started by StartProcess.
315 type Credential struct {
316         Uid    uint32   // User ID.
317         Gid    uint32   // Group ID.
318         Groups []uint32 // Supplementary group IDs.
319 }
320
321 // ProcAttr holds attributes that will be applied to a new process started
322 // by StartProcess.
323 type ProcAttr struct {
324         Dir   string   // Current working directory.
325         Env   []string // Environment.
326         Files []int    // File descriptors.
327         Sys   *SysProcAttr
328 }
329
330 type SysProcAttr struct {
331         Chroot     string      // Chroot.
332         Credential *Credential // Credential.
333         Ptrace     bool        // Enable tracing.
334         Setsid     bool        // Create session.
335         Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
336         Setctty    bool        // Set controlling terminal to fd 0
337         Noctty     bool        // Detach fd 0 from controlling terminal
338 }
339
340 var zeroProcAttr ProcAttr
341 var zeroSysProcAttr SysProcAttr
342
343 func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
344         var p [2]int
345         var n int
346         var err1 uintptr
347         var wstatus WaitStatus
348
349         if attr == nil {
350                 attr = &zeroProcAttr
351         }
352         sys := attr.Sys
353         if sys == nil {
354                 sys = &zeroSysProcAttr
355         }
356
357         p[0] = -1
358         p[1] = -1
359
360         // Convert args to C form.
361         argv0p := StringBytePtr(argv0)
362         argvp := StringSlicePtr(argv)
363         envvp := StringSlicePtr(attr.Env)
364
365         if OS == "freebsd" && len(argv[0]) > len(argv0) {
366                 argvp[0] = argv0p
367         }
368
369         var chroot *byte
370         if sys.Chroot != "" {
371                 chroot = StringBytePtr(sys.Chroot)
372         }
373         var dir *byte
374         if attr.Dir != "" {
375                 dir = StringBytePtr(attr.Dir)
376         }
377
378         // Acquire the fork lock so that no other threads
379         // create new fds that are not yet close-on-exec
380         // before we fork.
381         ForkLock.Lock()
382
383         // Allocate child status pipe close on exec.
384         if err = Pipe(p[0:]); err != 0 {
385                 goto error
386         }
387         if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
388                 goto error
389         }
390         if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
391                 goto error
392         }
393
394         // Kick off child.
395         pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
396         if err != 0 {
397                 goto error
398         }
399         ForkLock.Unlock()
400
401         // Read child error status from pipe.
402         Close(p[1])
403         n, err = raw_read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
404         Close(p[0])
405         if err != 0 || n != 0 {
406                 if n == int(unsafe.Sizeof(err1)) {
407                         err = int(err1)
408                 }
409                 if err == 0 {
410                         err = EPIPE
411                 }
412
413                 // Child failed; wait for it to exit, to make sure
414                 // the zombies don't accumulate.
415                 _, err1 := Wait4(pid, &wstatus, 0, nil)
416                 for err1 == EINTR {
417                         _, err1 = Wait4(pid, &wstatus, 0, nil)
418                 }
419                 return 0, err
420         }
421
422         // Read got EOF, so pipe closed on exec, so exec succeeded.
423         return pid, 0
424
425 error:
426         if p[0] >= 0 {
427                 Close(p[0])
428                 Close(p[1])
429         }
430         ForkLock.Unlock()
431         return 0, err
432 }
433
434 // Combination of fork and exec, careful to be thread safe.
435 func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
436         return forkExec(argv0, argv, attr)
437 }
438
439 // StartProcess wraps ForkExec for package os.
440 func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
441         pid, err = forkExec(argv0, argv, attr)
442         return pid, 0, err
443 }
444
445 // Ordinary exec.
446 func Exec(argv0 string, argv []string, envv []string) (err int) {
447         err1 := raw_execve(StringBytePtr(argv0),
448                 &StringSlicePtr(argv)[0],
449                 &StringSlicePtr(envv)[0])
450         return int(err1)
451 }