123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // +build linux
- package system
- import (
- "os"
- "os/exec"
- "syscall" // only for exec
- "unsafe"
- "github.com/opencontainers/runc/libcontainer/user"
- "golang.org/x/sys/unix"
- )
- // If arg2 is nonzero, set the "child subreaper" attribute of the
- // calling process; if arg2 is zero, unset the attribute. When a
- // process is marked as a child subreaper, all of the children
- // that it creates, and their descendants, will be marked as
- // having a subreaper. In effect, a subreaper fulfills the role
- // of init(1) for its descendant processes. Upon termination of
- // a process that is orphaned (i.e., its immediate parent has
- // already terminated) and marked as having a subreaper, the
- // nearest still living ancestor subreaper will receive a SIGCHLD
- // signal and be able to wait(2) on the process to discover its
- // termination status.
- const PR_SET_CHILD_SUBREAPER = 36
- type ParentDeathSignal int
- func (p ParentDeathSignal) Restore() error {
- if p == 0 {
- return nil
- }
- current, err := GetParentDeathSignal()
- if err != nil {
- return err
- }
- if p == current {
- return nil
- }
- return p.Set()
- }
- func (p ParentDeathSignal) Set() error {
- return SetParentDeathSignal(uintptr(p))
- }
- func Execv(cmd string, args []string, env []string) error {
- name, err := exec.LookPath(cmd)
- if err != nil {
- return err
- }
- return syscall.Exec(name, args, env)
- }
- func Prlimit(pid, resource int, limit unix.Rlimit) error {
- _, _, err := unix.RawSyscall6(unix.SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(&limit)), uintptr(unsafe.Pointer(&limit)), 0, 0)
- if err != 0 {
- return err
- }
- return nil
- }
- func SetParentDeathSignal(sig uintptr) error {
- if err := unix.Prctl(unix.PR_SET_PDEATHSIG, sig, 0, 0, 0); err != nil {
- return err
- }
- return nil
- }
- func GetParentDeathSignal() (ParentDeathSignal, error) {
- var sig int
- if err := unix.Prctl(unix.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0, 0, 0); err != nil {
- return -1, err
- }
- return ParentDeathSignal(sig), nil
- }
- func SetKeepCaps() error {
- if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 1, 0, 0, 0); err != nil {
- return err
- }
- return nil
- }
- func ClearKeepCaps() error {
- if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 0, 0, 0, 0); err != nil {
- return err
- }
- return nil
- }
- func Setctty() error {
- if err := unix.IoctlSetInt(0, unix.TIOCSCTTY, 0); err != nil {
- return err
- }
- return nil
- }
- // RunningInUserNS detects whether we are currently running in a user namespace.
- // Originally copied from github.com/lxc/lxd/shared/util.go
- func RunningInUserNS() bool {
- uidmap, err := user.CurrentProcessUIDMap()
- if err != nil {
- // This kernel-provided file only exists if user namespaces are supported
- return false
- }
- return UIDMapInUserNS(uidmap)
- }
- func UIDMapInUserNS(uidmap []user.IDMap) bool {
- /*
- * We assume we are in the initial user namespace if we have a full
- * range - 4294967295 uids starting at uid 0.
- */
- if len(uidmap) == 1 && uidmap[0].ID == 0 && uidmap[0].ParentID == 0 && uidmap[0].Count == 4294967295 {
- return false
- }
- return true
- }
- // GetParentNSeuid returns the euid within the parent user namespace
- func GetParentNSeuid() int64 {
- euid := int64(os.Geteuid())
- uidmap, err := user.CurrentProcessUIDMap()
- if err != nil {
- // This kernel-provided file only exists if user namespaces are supported
- return euid
- }
- for _, um := range uidmap {
- if um.ID <= euid && euid <= um.ID+um.Count-1 {
- return um.ParentID + euid - um.ID
- }
- }
- return euid
- }
- // SetSubreaper sets the value i as the subreaper setting for the calling process
- func SetSubreaper(i int) error {
- return unix.Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
- }
- // GetSubreaper returns the subreaper setting for the calling process
- func GetSubreaper() (int, error) {
- var i uintptr
- if err := unix.Prctl(unix.PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0, 0, 0); err != nil {
- return -1, err
- }
- return int(i), nil
- }
|