| | |
| | |
| | |
| |
|
| | 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 |
| | Pdeathsig Signal |
| | Jail int |
| | } |
| |
|
| | const ( |
| | _P_PID = 0 |
| |
|
| | _PROC_PDEATHSIG_CTL = 11 |
| | ) |
| |
|
| | |
| | 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 |
| | upid, ppid uintptr |
| | ) |
| |
|
| | rlim := origRlimitNofile.Load() |
| |
|
| | |
| | if sys.Pdeathsig != 0 { |
| | ppid, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0) |
| | } |
| |
|
| | |
| | |
| | |
| | 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.Jail > 0 { |
| | _, _, err1 = RawSyscall(SYS_JAIL_ATTACH, uintptr(sys.Jail), 0, 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| |
|
| | |
| | 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 sys.Pdeathsig != 0 { |
| | switch runtime.GOARCH { |
| | case "386", "arm": |
| | _, _, err1 = RawSyscall6(SYS_PROCCTL, _P_PID, 0, 0, _PROC_PDEATHSIG_CTL, uintptr(unsafe.Pointer(&sys.Pdeathsig)), 0) |
| | default: |
| | _, _, err1 = RawSyscall6(SYS_PROCCTL, _P_PID, 0, _PROC_PDEATHSIG_CTL, uintptr(unsafe.Pointer(&sys.Pdeathsig)), 0, 0) |
| | } |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| |
|
| | |
| | |
| | |
| | r1, _, _ = RawSyscall(SYS_GETPPID, 0, 0, 0) |
| | if r1 != ppid { |
| | upid, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0) |
| | _, _, err1 = RawSyscall(SYS_KILL, upid, uintptr(sys.Pdeathsig), 0) |
| | if err1 != 0 { |
| | goto childerror |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | if pipe < nextfd { |
| | _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(pipe), F_DUP2FD_CLOEXEC, uintptr(nextfd)) |
| | 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++ |
| | } |
| | _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_DUP2FD_CLOEXEC, uintptr(nextfd)) |
| | 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) { |
| | |
| | } |
| |
|