syscall: fix Exec on solaris

The test added for issue #18146 exposed a long-existing bug in the
Solaris port; notably, that syscall.Exec uses RawSyscall -- which is not
actually functional for the Solaris port (intentionally) and only exists
as a placebo to satisfy build requirements.

Call syscall.execve instead for Solaris.

Fixes #20832

Change-Id: I327d863f4bbbbbb6e5ecf66b82152c4030825d09
Reviewed-on: https://go-review.googlesource.com/47032
Run-TryBot: Shawn Walker-Salas <shawn.walker@oracle.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Shawn Walker-Salas 2017-06-28 10:58:44 -07:00 committed by Brad Fitzpatrick
parent cfb8404e76
commit 2d1bd1fe9d
2 changed files with 24 additions and 5 deletions

View file

@ -41,6 +41,11 @@ func setuid(uid uintptr) (err Errno)
func setpgid(pid uintptr, pgid uintptr) (err Errno) func setpgid(pid uintptr, pgid uintptr) (err Errno)
func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno) func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno)
// syscall defines this global on our behalf to avoid a build dependency on other platforms
func init() {
execveSolaris = execve
}
// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
// If a dup or exec fails, write the errno error to pipe. // If a dup or exec fails, write the errno error to pipe.
// (Pipe is close-on-exec so if exec succeeds, it will be closed.) // (Pipe is close-on-exec so if exec succeeds, it will be closed.)

View file

@ -246,6 +246,10 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
func runtime_BeforeExec() func runtime_BeforeExec()
func runtime_AfterExec() func runtime_AfterExec()
// execveSolaris is non-nil on Solaris, set to execve in exec_solaris.go; this
// avoids a build dependency for other platforms.
var execveSolaris func(path uintptr, argv uintptr, envp uintptr) (err Errno)
// Exec invokes the execve(2) system call. // Exec invokes the execve(2) system call.
func Exec(argv0 string, argv []string, envv []string) (err error) { func Exec(argv0 string, argv []string, envv []string) (err error) {
argv0p, err := BytePtrFromString(argv0) argv0p, err := BytePtrFromString(argv0)
@ -261,10 +265,20 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
return err return err
} }
runtime_BeforeExec() runtime_BeforeExec()
_, _, err1 := RawSyscall(SYS_EXECVE,
uintptr(unsafe.Pointer(argv0p)), var err1 Errno
uintptr(unsafe.Pointer(&argvp[0])), if runtime.GOOS == "solaris" {
uintptr(unsafe.Pointer(&envvp[0]))) // RawSyscall should never be used on Solaris.
err1 = execveSolaris(
uintptr(unsafe.Pointer(argv0p)),
uintptr(unsafe.Pointer(&argvp[0])),
uintptr(unsafe.Pointer(&envvp[0])))
} else {
_, _, err1 = RawSyscall(SYS_EXECVE,
uintptr(unsafe.Pointer(argv0p)),
uintptr(unsafe.Pointer(&argvp[0])),
uintptr(unsafe.Pointer(&envvp[0])))
}
runtime_AfterExec() runtime_AfterExec()
return Errno(err1) return err1
} }