exec_unix.go 9.34 KB
Newer Older
1 2 3 4
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

5
// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
6

7 8 9 10
// Fork, exec, wait, etc.

package syscall

11
import (
12
	"runtime"
13 14 15 16
	"sync"
	"unsafe"
)

17
//sysnb	raw_fork() (pid Pid_t, err Errno)
18 19
//fork() Pid_t

20
//sysnb	raw_getpid() (pid Pid_t)
21 22
//getpid() Pid_t

23
//sysnb	raw_getppid() (pid Pid_t)
24 25
//getppid() Pid_t

26
//sysnb raw_setsid() (err Errno)
27 28
//setsid() Pid_t

29
//sysnb raw_setpgid(pid int, pgid int) (err Errno)
30
//setpgid(pid Pid_t, pgid Pid_t) _C_int
31 32

//sysnb	raw_chroot(path *byte) (err Errno)
33
//chroot(path *byte) _C_int
34

35
//sysnb	raw_chdir(path *byte) (err Errno)
36
//chdir(path *byte) _C_int
37

38
//sysnb	raw_fcntl(fd int, cmd int, arg int) (val int, err Errno)
39
//__go_fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int
40

41
//sysnb	raw_close(fd int) (err Errno)
42
//close(fd _C_int) _C_int
43

44
//sysnb	raw_ioctl(fd int, cmd uintptr, val int) (rval int, err Errno)
45 46
//__go_ioctl(fd _C_int, cmd _C_int, val _C_int) _C_int

47
//sysnb raw_ioctl_ptr(fd int, cmd uintptr, val unsafe.Pointer) (rval int, err Errno)
48
//__go_ioctl_ptr(fd _C_int, cmd _C_int, val unsafe.Pointer) _C_int
49

50
//sysnb	raw_execve(argv0 *byte, argv **byte, envv **byte) (err Errno)
51
//execve(argv0 *byte, argv **byte, envv **byte) _C_int
52

53
//sysnb	raw_write(fd int, buf *byte, count int) (err Errno)
54
//write(fd _C_int, buf *byte, count Size_t) Ssize_t
55 56

//sysnb	raw_exit(status int)
57
//_exit(status _C_int)
58

59
//sysnb raw_dup2(oldfd int, newfd int) (err Errno)
60
//dup2(oldfd _C_int, newfd _C_int) _C_int
61

62
//sysnb raw_kill(pid Pid_t, sig Signal) (err Errno)
63 64 65 66 67
//kill(pid Pid_t, sig _C_int) _C_int

//sysnb raw_setgroups(size int, list unsafe.Pointer) (err Errno)
//setgroups(size Size_t, list *Gid_t) _C_int

68 69 70
// Lock synchronizing creation of new file descriptors with fork.
//
// We want the child in a fork/exec sequence to inherit only the
71
// file descriptors we intend. To do that, we mark all file
72 73 74
// descriptors close-on-exec and then, in the child, explicitly
// unmark the ones we want the exec'ed program to keep.
// Unix doesn't make this easy: there is, in general, no way to
75
// allocate a new file descriptor close-on-exec. Instead you
76 77 78 79 80 81
// have to allocate the descriptor and then mark it close-on-exec.
// If a fork happens between those two events, the child's exec
// will inherit an unwanted file descriptor.
//
// This lock solves that race: the create new fd/mark close-on-exec
// operation is done holding ForkLock for reading, and the fork itself
82
// is done holding ForkLock for writing. At least, that's the idea.
83 84 85 86
// There are some complications.
//
// Some system calls that create new file descriptors can block
// for arbitrarily long times: open on a hung NFS server or named
87
// pipe, accept on a socket, and so on. We can't reasonably grab
88 89 90 91
// the lock across those operations.
//
// It is worse to inherit some file descriptors than others.
// If a non-malicious child accidentally inherits an open ordinary file,
92
// that's not a big deal. On the other hand, if a long-lived child
93 94
// accidentally inherits the write end of a pipe, then the reader
// of that pipe will not see EOF until that child exits, potentially
95
// causing the parent program to hang. This is a common problem
96 97 98 99 100 101 102 103 104
// in threaded C programs that use popen.
//
// Luckily, the file descriptors that are most important not to
// inherit are not the ones that can take an arbitrarily long time
// to create: pipe returns instantly, and the net package uses
// non-blocking I/O to accept on a listening socket.
// The rules for which file descriptor-creating operations use the
// ForkLock are as follows:
//
105 106 107
// 1) Pipe. Does not block. Use the ForkLock.
// 2) Socket. Does not block. Use the ForkLock.
// 3) Accept. If using non-blocking mode, use the ForkLock.
108
//             Otherwise, live with the race.
109
// 4) Open. Can block. Use O_CLOEXEC if available (GNU/Linux).
110
//             Otherwise, live with the race.
111
// 5) Dup. Does not block. Use the ForkLock.
112
//             On GNU/Linux, could use fcntl F_DUPFD_CLOEXEC
113 114 115 116
//             instead of the ForkLock, but only for dup(fd, -1).

var ForkLock sync.RWMutex

117 118 119 120 121
// StringSlicePtr converts a slice of strings to a slice of pointers
// to NUL-terminated byte arrays. If any string contains a NUL byte
// this function panics instead of returning an error.
//
// Deprecated: Use SlicePtrFromStrings instead.
122 123 124 125 126 127 128 129 130
func StringSlicePtr(ss []string) []*byte {
	bb := make([]*byte, len(ss)+1)
	for i := 0; i < len(ss); i++ {
		bb[i] = StringBytePtr(ss[i])
	}
	bb[len(ss)] = nil
	return bb
}

131
// SlicePtrFromStrings converts a slice of strings to a slice of
132
// pointers to NUL-terminated byte arrays. If any string contains
133
// a NUL byte, it returns (nil, EINVAL).
134
func SlicePtrFromStrings(ss []string) ([]*byte, error) {
135 136 137
	var err error
	bb := make([]*byte, len(ss)+1)
	for i := 0; i < len(ss); i++ {
138
		bb[i], err = BytePtrFromString(ss[i])
139 140 141 142 143 144 145 146
		if err != nil {
			return nil, err
		}
	}
	bb[len(ss)] = nil
	return bb, nil
}

147 148
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }

149
func SetNonblock(fd int, nonblocking bool) (err error) {
150
	flag, err := fcntl(fd, F_GETFL, 0)
151
	if err != nil {
152 153 154 155 156
		return err
	}
	if nonblocking {
		flag |= O_NONBLOCK
	} else {
157
		flag &^= O_NONBLOCK
158 159 160 161
	}
	_, err = fcntl(fd, F_SETFL, flag)
	return err
}
162

163 164 165
// Credential holds user and group identities to be assumed
// by a child process started by StartProcess.
type Credential struct {
166 167 168 169
	Uid         uint32   // User ID.
	Gid         uint32   // Group ID.
	Groups      []uint32 // Supplementary group IDs.
	NoSetGroups bool     // If true, don't set supplementary groups
170
}
171

172 173
// ProcAttr holds attributes that will be applied to a new process started
// by StartProcess.
174
type ProcAttr struct {
175 176 177
	Dir   string    // Current working directory.
	Env   []string  // Environment.
	Files []uintptr // File descriptors.
178
	Sys   *SysProcAttr
179 180
}

181 182
var zeroProcAttr ProcAttr
var zeroSysProcAttr SysProcAttr
183

184
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
185
	var p [2]int
186
	var n int
187
	var err1 Errno
188
	var wstatus WaitStatus
189

190
	if attr == nil {
191 192 193 194 195
		attr = &zeroProcAttr
	}
	sys := attr.Sys
	if sys == nil {
		sys = &zeroSysProcAttr
196 197
	}

198 199
	p[0] = -1
	p[1] = -1
200 201

	// Convert args to C form.
202
	argv0p, err := BytePtrFromString(argv0)
203 204 205
	if err != nil {
		return 0, err
	}
206
	argvp, err := SlicePtrFromStrings(argv)
207 208 209
	if err != nil {
		return 0, err
	}
210
	envvp, err := SlicePtrFromStrings(attr.Env)
211 212 213
	if err != nil {
		return 0, err
	}
214

215
	if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv[0]) > len(argv0) {
216 217 218
		argvp[0] = argv0p
	}

219 220
	var chroot *byte
	if sys.Chroot != "" {
221
		chroot, err = BytePtrFromString(sys.Chroot)
222 223 224
		if err != nil {
			return 0, err
		}
225
	}
226 227
	var dir *byte
	if attr.Dir != "" {
228
		dir, err = BytePtrFromString(attr.Dir)
229 230 231
		if err != nil {
			return 0, err
		}
232 233 234 235 236
	}

	// Acquire the fork lock so that no other threads
	// create new fds that are not yet close-on-exec
	// before we fork.
237
	ForkLock.Lock()
238 239

	// Allocate child status pipe close on exec.
240
	if err = forkExecPipe(p[:]); err != nil {
241
		goto error
242 243 244
	}

	// Kick off child.
245 246
	pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
	if err1 != 0 {
247
		err = Errno(err1)
248
		goto error
249
	}
250
	ForkLock.Unlock()
251 252

	// Read child error status from pipe.
253
	Close(p[1])
254
	n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
255
	Close(p[0])
256
	if err != nil || n != 0 {
257
		if n == int(unsafe.Sizeof(err1)) {
258
			err = Errno(err1)
259
		}
260
		if err == nil {
261
			err = EPIPE
262 263 264 265
		}

		// Child failed; wait for it to exit, to make sure
		// the zombies don't accumulate.
266
		_, err1 := Wait4(pid, &wstatus, 0, nil)
267
		for err1 == EINTR {
268
			_, err1 = Wait4(pid, &wstatus, 0, nil)
269 270 271 272 273
		}
		return 0, err
	}

	// Read got EOF, so pipe closed on exec, so exec succeeded.
274
	return pid, nil
275 276 277 278 279 280 281 282

error:
	if p[0] >= 0 {
		Close(p[0])
		Close(p[1])
	}
	ForkLock.Unlock()
	return 0, err
283 284 285
}

// Combination of fork and exec, careful to be thread safe.
286
func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
287
	return forkExec(argv0, argv, attr)
288 289
}

290
// StartProcess wraps ForkExec for package os.
291
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
292 293
	pid, err = forkExec(argv0, argv, attr)
	return pid, 0, err
294 295
}

296 297 298 299
// Implemented in runtime package.
func runtime_BeforeExec()
func runtime_AfterExec()

300
// execveLibc is non-nil on OS using libc syscall, set to execve in exec_libc.go; this
301
// avoids a build dependency for other platforms.
302
var execveDarwin func(path *byte, argv **byte, envp **byte) error
303

304
// Exec invokes the execve(2) system call.
305
func Exec(argv0 string, argv []string, envv []string) (err error) {
306
	argv0p, err := BytePtrFromString(argv0)
307 308 309
	if err != nil {
		return err
	}
310
	argvp, err := SlicePtrFromStrings(argv)
311 312 313
	if err != nil {
		return err
	}
314
	envvp, err := SlicePtrFromStrings(envv)
315 316 317
	if err != nil {
		return err
	}
318 319
	runtime_BeforeExec()

320
	var err1 error
321
	if runtime.GOOS == "solaris" || runtime.GOOS == "aix" || runtime.GOOS == "hurd" {
322
		// RawSyscall should never be used on Solaris or AIX.
323
		err1 = raw_execve(argv0p, &argvp[0], &envvp[0])
324 325 326 327 328 329 330 331 332
	} else if runtime.GOOS == "darwin" {
		// Similarly on Darwin.
		err1 = execveDarwin(argv0p, &argvp[0], &envvp[0])
	} else {
		_, _, err1 = RawSyscall(SYS_EXECVE,
			uintptr(unsafe.Pointer(argv0p)),
			uintptr(unsafe.Pointer(&argvp[0])),
			uintptr(unsafe.Pointer(&envvp[0])))
	}
333
	runtime_AfterExec()
334
	return err1
335
}