| | |
| | |
| | |
| |
|
| | |
| |
|
| | |
| |
|
| | package syscall |
| |
|
| | import ( |
| | "runtime" |
| | "unsafe" |
| | ) |
| |
|
| | type SysProcAttr struct { |
| | Chroot string |
| | Credential *Credential |
| | Setsid bool |
| | |
| | |
| | Setpgid bool |
| | |
| | |
| | |
| | |
| | Setctty bool |
| | Noctty bool |
| | Ctty int |
| | |
| | |
| | |
| | |
| | |
| | Foreground bool |
| | Pgid int |
| | } |
| |
|
| | |
| | func runtime_BeforeFork() |
| | func runtime_AfterFork() |
| | func runtime_AfterForkInChild() |
| |
|
| | func chdir(path uintptr) (err Errno) |
| | func chroot1(path uintptr) (err Errno) |
| | func closeFD(fd uintptr) (err Errno) |
| | func dup2child(old uintptr, new uintptr) (val uintptr, err Errno) |
| | func execve(path uintptr, argv uintptr, envp uintptr) (err Errno) |
| | func exit(code uintptr) |
| | func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err Errno) |
| | func forkx(flags uintptr) (pid uintptr, err Errno) |
| | func getpid() (pid uintptr, err Errno) |
| | func ioctl(fd uintptr, req uintptr, arg uintptr) (err Errno) |
| | func setgid(gid uintptr) (err Errno) |
| | func setgroups1(ngid uintptr, gid uintptr) (err Errno) |
| | func setrlimit1(which uintptr, lim unsafe.Pointer) (err Errno) |
| | func setsid() (pid uintptr, err Errno) |
| | func setuid(uid uintptr) (err Errno) |
| | func setpgid(pid uintptr, pgid uintptr) (err Errno) |
| | func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno) |
| |
|
| | |
| | func init() { |
| | execveLibc = execveLibcWrapper |
| | } |
| |
|
| | func execveLibcWrapper(path *byte, argv **byte, envp **byte) error { |
| | return execve(uintptr(unsafe.Pointer(path)), |
| | uintptr(unsafe.Pointer(argv)), |
| | uintptr(unsafe.Pointer(envp))) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) { |
| | |
| | |
| | var ( |
| | r1 uintptr |
| | err1 Errno |
| | nextfd int |
| | i int |
| | pgrp _Pid_t |
| | cred *Credential |
| | ngroups, groups uintptr |
| | ) |
| |
|
| | rlim := origRlimitNofile.Load() |
| |
|
| | |
| | |
| | |
| | fd := make([]int, len(attr.Files)) |
| | nextfd = len(attr.Files) |
| | for i, ufd := range attr.Files { |
| | if nextfd < int(ufd) { |
| | nextfd = int(ufd) |
| | } |
| | fd[i] = int(ufd) |
| | } |
| | nextfd++ |
| |
|
| | |
| | |
| | runtime_BeforeFork() |
| | r1, err1 = forkx(0x1) |
| | if err1 != 0 { |
| | runtime_AfterFork() |
| | return 0, err1 |
| | } |
| |
|
| | if r1 != 0 { |
| | |
| | runtime_AfterFork() |
| | return int(r1), 0 |
| | } |
| |
|
| | |
| |
|
| | |
| | if sys.Setsid { |
| | _, err1 = setsid() |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if sys.Setpgid || sys.Foreground { |
| | |
| | err1 = setpgid(0, uintptr(sys.Pgid)) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | if sys.Foreground { |
| | pgrp = _Pid_t(sys.Pgid) |
| | if pgrp == 0 { |
| | r1, err1 = getpid() |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| |
|
| | pgrp = _Pid_t(r1) |
| | } |
| |
|
| | |
| | err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp))) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | |
| | runtime_AfterForkInChild() |
| |
|
| | |
| | if chroot != nil { |
| | err1 = chroot1(uintptr(unsafe.Pointer(chroot))) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if cred = sys.Credential; cred != nil { |
| | ngroups = uintptr(len(cred.Groups)) |
| | groups = uintptr(0) |
| | if ngroups > 0 { |
| | groups = uintptr(unsafe.Pointer(&cred.Groups[0])) |
| | } |
| | if !cred.NoSetGroups { |
| | err1 = setgroups1(ngroups, groups) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| | err1 = setgid(uintptr(cred.Gid)) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | err1 = setuid(uintptr(cred.Uid)) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if dir != nil { |
| | err1 = chdir(uintptr(unsafe.Pointer(dir))) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | |
| | if pipe < nextfd { |
| | switch runtime.GOOS { |
| | case "illumos", "solaris": |
| | _, err1 = fcntl1(uintptr(pipe), _F_DUP2FD_CLOEXEC, uintptr(nextfd)) |
| | default: |
| | _, err1 = dup2child(uintptr(pipe), uintptr(nextfd)) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) |
| | } |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | pipe = nextfd |
| | nextfd++ |
| | } |
| | for i = 0; i < len(fd); i++ { |
| | if fd[i] >= 0 && fd[i] < i { |
| | if nextfd == pipe { |
| | nextfd++ |
| | } |
| | switch runtime.GOOS { |
| | case "illumos", "solaris": |
| | _, err1 = fcntl1(uintptr(fd[i]), _F_DUP2FD_CLOEXEC, uintptr(nextfd)) |
| | default: |
| | _, err1 = dup2child(uintptr(fd[i]), uintptr(nextfd)) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) |
| | } |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | fd[i] = nextfd |
| | nextfd++ |
| | } |
| | } |
| |
|
| | |
| | for i = 0; i < len(fd); i++ { |
| | if fd[i] == -1 { |
| | closeFD(uintptr(i)) |
| | continue |
| | } |
| | if fd[i] == i { |
| | |
| | |
| | _, err1 = fcntl1(uintptr(fd[i]), F_SETFD, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | continue |
| | } |
| | |
| | |
| | _, err1 = dup2child(uintptr(fd[i]), uintptr(i)) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | for i = len(fd); i < 3; i++ { |
| | closeFD(uintptr(i)) |
| | } |
| |
|
| | |
| | if sys.Noctty { |
| | err1 = ioctl(0, uintptr(TIOCNOTTY), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if sys.Setctty { |
| | |
| | if TIOCSCTTY == 0 { |
| | err1 = ENOSYS |
| | goto childerror |
| | } |
| | err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if rlim != nil { |
| | setrlimit1(RLIMIT_NOFILE, unsafe.Pointer(rlim)) |
| | } |
| |
|
| | |
| | err1 = execve( |
| | uintptr(unsafe.Pointer(argv0)), |
| | uintptr(unsafe.Pointer(&argv[0])), |
| | uintptr(unsafe.Pointer(&envv[0]))) |
| |
|
| | childerror: |
| | |
| | write1(uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1)) |
| | for { |
| | exit(253) |
| | } |
| | } |
| |
|
| | |
| | func forkAndExecFailureCleanup(attr *ProcAttr, sys *SysProcAttr) { |
| | |
| | } |
| |
|
| | func ioctlPtr(fd, req uintptr, arg unsafe.Pointer) (err Errno) { |
| | return ioctl(fd, req, uintptr(arg)) |
| | } |
| |
|