diff options
Diffstat (limited to 'src/pkg/syscall/exec_unix.go')
-rw-r--r-- | src/pkg/syscall/exec_unix.go | 74 |
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) } |