OSDN Git Service

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