...
Run Format

Source file src/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 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	// Exec invokes the execve(2) system call.
   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	

View as plain text