summaryrefslogtreecommitdiff
path: root/src/pkg/syscall/exec_unix.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/syscall/exec_unix.go')
-rw-r--r--src/pkg/syscall/exec_unix.go74
1 files changed, 56 insertions, 18 deletions
diff --git a/src/pkg/syscall/exec_unix.go b/src/pkg/syscall/exec_unix.go
index dfaa0374a..01b76c106 100644
--- a/src/pkg/syscall/exec_unix.go
+++ b/src/pkg/syscall/exec_unix.go
@@ -63,8 +63,9 @@ import (
var ForkLock sync.RWMutex
-// Convert array of string to array
-// of NUL-terminated byte pointer.
+// StringSlicePtr is deprecated. Use SlicePtrFromStrings instead.
+// If any string contains a NUL byte this function panics instead
+// of returning an error.
func StringSlicePtr(ss []string) []*byte {
bb := make([]*byte, len(ss)+1)
for i := 0; i < len(ss); i++ {
@@ -74,6 +75,22 @@ func StringSlicePtr(ss []string) []*byte {
return bb
}
+// SlicePtrFromStrings converts a slice of strings to a slice of
+// pointers to NUL-terminated byte slices. If any string contains
+// a NUL byte, it returns (nil, EINVAL).
+func SlicePtrFromStrings(ss []string) ([]*byte, error) {
+ var err error
+ bb := make([]*byte, len(ss)+1)
+ for i := 0; i < len(ss); i++ {
+ bb[i], err = BytePtrFromString(ss[i])
+ if err != nil {
+ return nil, err
+ }
+ }
+ bb[len(ss)] = nil
+ return bb, nil
+}
+
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
func SetNonblock(fd int, nonblocking bool) (err error) {
@@ -128,9 +145,18 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
p[1] = -1
// Convert args to C form.
- argv0p := StringBytePtr(argv0)
- argvp := StringSlicePtr(argv)
- envvp := StringSlicePtr(attr.Env)
+ argv0p, err := BytePtrFromString(argv0)
+ if err != nil {
+ return 0, err
+ }
+ argvp, err := SlicePtrFromStrings(argv)
+ if err != nil {
+ return 0, err
+ }
+ envvp, err := SlicePtrFromStrings(attr.Env)
+ if err != nil {
+ return 0, err
+ }
if runtime.GOOS == "freebsd" && len(argv[0]) > len(argv0) {
argvp[0] = argv0p
@@ -138,11 +164,17 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
var chroot *byte
if sys.Chroot != "" {
- chroot = StringBytePtr(sys.Chroot)
+ chroot, err = BytePtrFromString(sys.Chroot)
+ if err != nil {
+ return 0, err
+ }
}
var dir *byte
if attr.Dir != "" {
- dir = StringBytePtr(attr.Dir)
+ dir, err = BytePtrFromString(attr.Dir)
+ if err != nil {
+ return 0, err
+ }
}
// Acquire the fork lock so that no other threads
@@ -151,13 +183,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
ForkLock.Lock()
// Allocate child status pipe close on exec.
- if err = Pipe(p[0:]); err != nil {
- goto error
- }
- if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil {
- goto error
- }
- if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != nil {
+ if err = forkExecPipe(p[:]); err != nil {
goto error
}
@@ -171,7 +197,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
// Read child error status from pipe.
Close(p[1])
- n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+ n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
Close(p[0])
if err != nil || n != 0 {
if n == int(unsafe.Sizeof(err1)) {
@@ -215,9 +241,21 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
// Ordinary exec.
func Exec(argv0 string, argv []string, envv []string) (err error) {
+ argv0p, err := BytePtrFromString(argv0)
+ if err != nil {
+ return err
+ }
+ argvp, err := SlicePtrFromStrings(argv)
+ if err != nil {
+ return err
+ }
+ envvp, err := SlicePtrFromStrings(envv)
+ if err != nil {
+ return err
+ }
_, _, err1 := RawSyscall(SYS_EXECVE,
- uintptr(unsafe.Pointer(StringBytePtr(argv0))),
- uintptr(unsafe.Pointer(&StringSlicePtr(argv)[0])),
- uintptr(unsafe.Pointer(&StringSlicePtr(envv)[0])))
+ uintptr(unsafe.Pointer(argv0p)),
+ uintptr(unsafe.Pointer(&argvp[0])),
+ uintptr(unsafe.Pointer(&envvp[0])))
return Errno(err1)
}