github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/system/linux.go (about) 1 // +build linux 2 3 package system 4 5 import ( 6 "bufio" 7 "fmt" 8 "os" 9 "os/exec" 10 "syscall" 11 "unsafe" 12 ) 13 14 // If arg2 is nonzero, set the "child subreaper" attribute of the 15 // calling process; if arg2 is zero, unset the attribute. When a 16 // process is marked as a child subreaper, all of the children 17 // that it creates, and their descendants, will be marked as 18 // having a subreaper. In effect, a subreaper fulfills the role 19 // of init(1) for its descendant processes. Upon termination of 20 // a process that is orphaned (i.e., its immediate parent has 21 // already terminated) and marked as having a subreaper, the 22 // nearest still living ancestor subreaper will receive a SIGCHLD 23 // signal and be able to wait(2) on the process to discover its 24 // termination status. 25 const PR_SET_CHILD_SUBREAPER = 36 26 27 type ParentDeathSignal int 28 29 func (p ParentDeathSignal) Restore() error { 30 if p == 0 { 31 return nil 32 } 33 current, err := GetParentDeathSignal() 34 if err != nil { 35 return err 36 } 37 if p == current { 38 return nil 39 } 40 return p.Set() 41 } 42 43 func (p ParentDeathSignal) Set() error { 44 return SetParentDeathSignal(uintptr(p)) 45 } 46 47 func Execv(cmd string, args []string, env []string) error { 48 name, err := exec.LookPath(cmd) 49 if err != nil { 50 return err 51 } 52 53 return syscall.Exec(name, args, env) 54 } 55 56 func Prlimit(pid, resource int, limit syscall.Rlimit) error { 57 _, _, err := syscall.RawSyscall6(syscall.SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(&limit)), uintptr(unsafe.Pointer(&limit)), 0, 0) 58 if err != 0 { 59 return err 60 } 61 return nil 62 } 63 64 func SetParentDeathSignal(sig uintptr) error { 65 if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, sig, 0); err != 0 { 66 return err 67 } 68 return nil 69 } 70 71 func GetParentDeathSignal() (ParentDeathSignal, error) { 72 var sig int 73 _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0) 74 if err != 0 { 75 return -1, err 76 } 77 return ParentDeathSignal(sig), nil 78 } 79 80 func SetKeepCaps() error { 81 if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 1, 0); err != 0 { 82 return err 83 } 84 85 return nil 86 } 87 88 func ClearKeepCaps() error { 89 if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 0, 0); err != 0 { 90 return err 91 } 92 93 return nil 94 } 95 96 func Setctty() error { 97 if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 { 98 return err 99 } 100 return nil 101 } 102 103 // RunningInUserNS detects whether we are currently running in a user namespace. 104 // Copied from github.com/lxc/lxd/shared/util.go 105 func RunningInUserNS() bool { 106 file, err := os.Open("/proc/self/uid_map") 107 if err != nil { 108 // This kernel-provided file only exists if user namespaces are supported 109 return false 110 } 111 defer file.Close() 112 113 buf := bufio.NewReader(file) 114 l, _, err := buf.ReadLine() 115 if err != nil { 116 return false 117 } 118 119 line := string(l) 120 var a, b, c int64 121 fmt.Sscanf(line, "%d %d %d", &a, &b, &c) 122 /* 123 * We assume we are in the initial user namespace if we have a full 124 * range - 4294967295 uids starting at uid 0. 125 */ 126 if a == 0 && b == 0 && c == 4294967295 { 127 return false 128 } 129 return true 130 } 131 132 // SetSubreaper sets the value i as the subreaper setting for the calling process 133 func SetSubreaper(i int) error { 134 return Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0) 135 } 136 137 func Prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { 138 _, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) 139 if e1 != 0 { 140 err = e1 141 } 142 return 143 }