| | |
| | |
| | |
| |
|
| | |
| |
|
| | package syscall |
| |
|
| | import ( |
| | "runtime" |
| | "unsafe" |
| | ) |
| |
|
| | type SysProcAttr struct { |
| | Chroot string |
| | Credential *Credential |
| | Ptrace bool |
| | Setsid bool |
| | |
| | |
| | Setpgid bool |
| | |
| | |
| | |
| | |
| | Setctty bool |
| | Noctty bool |
| | Ctty int |
| | |
| | |
| | |
| | |
| | |
| | Foreground bool |
| | Pgid int |
| | } |
| |
|
| | |
| | func runtime_BeforeFork() |
| | func runtime_AfterFork() |
| | func runtime_AfterForkInChild() |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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 _C_int |
| | 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 = RawSyscall(SYS_FORK, 0, 0, 0) |
| | if err1 != 0 { |
| | runtime_AfterFork() |
| | return 0, err1 |
| | } |
| |
|
| | if r1 != 0 { |
| | |
| | runtime_AfterFork() |
| | return int(r1), 0 |
| | } |
| |
|
| | |
| |
|
| | |
| | if sys.Ptrace { |
| | _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if sys.Setsid { |
| | _, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if sys.Setpgid || sys.Foreground { |
| | |
| | _, _, err1 = RawSyscall(SYS_SETPGID, 0, uintptr(sys.Pgid), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | if sys.Foreground { |
| | |
| | |
| | pgrp = _C_int(sys.Pgid) |
| | if pgrp == 0 { |
| | r1, _, err1 = RawSyscall(SYS_GETPID, 0, 0, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| |
|
| | pgrp = _C_int(r1) |
| | } |
| |
|
| | |
| | _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp))) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | |
| | runtime_AfterForkInChild() |
| |
|
| | |
| | if chroot != nil { |
| | _, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0) |
| | 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 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| | _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if dir != nil { |
| | _, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | |
| | if pipe < nextfd { |
| | if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") { |
| | _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(pipe), uintptr(nextfd), O_CLOEXEC) |
| | } else if runtime.GOOS == "dragonfly" { |
| | _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(pipe), _F_DUP2FD_CLOEXEC, uintptr(nextfd)) |
| | } else { |
| | _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | _, _, err1 = RawSyscall(SYS_FCNTL, 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++ |
| | } |
| | if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") { |
| | _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC) |
| | } else if runtime.GOOS == "dragonfly" { |
| | _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), _F_DUP2FD_CLOEXEC, uintptr(nextfd)) |
| | } else { |
| | _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | _, _, err1 = RawSyscall(SYS_FCNTL, 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 { |
| | RawSyscall(SYS_CLOSE, uintptr(i), 0, 0) |
| | continue |
| | } |
| | if fd[i] == i { |
| | |
| | |
| | _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | continue |
| | } |
| | |
| | |
| | _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | for i = len(fd); i < 3; i++ { |
| | RawSyscall(SYS_CLOSE, uintptr(i), 0, 0) |
| | } |
| |
|
| | |
| | if sys.Noctty { |
| | _, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if sys.Setctty { |
| | _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | if rlim != nil { |
| | RawSyscall(SYS_SETRLIMIT, uintptr(RLIMIT_NOFILE), uintptr(unsafe.Pointer(rlim)), 0) |
| | } |
| |
|
| | |
| | _, _, err1 = RawSyscall(SYS_EXECVE, |
| | uintptr(unsafe.Pointer(argv0)), |
| | uintptr(unsafe.Pointer(&argv[0])), |
| | uintptr(unsafe.Pointer(&envv[0]))) |
| |
|
| | childerror: |
| | |
| | RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1)) |
| | for { |
| | RawSyscall(SYS_EXIT, 253, 0, 0) |
| | } |
| | } |
| |
|
| | |
| | func forkAndExecFailureCleanup(attr *ProcAttr, sys *SysProcAttr) { |
| | |
| | } |
| |
|