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  }