github.com/criyle/go-sandbox@v0.10.3/pkg/forkexec/userns_linux.go (about)

     1  package forkexec
     2  
     3  import (
     4  	"strconv"
     5  	"syscall"
     6  
     7  	"golang.org/x/sys/unix"
     8  )
     9  
    10  // writeUidGidMappings writes User ID and Group ID mappings for user namespaces
    11  // for a process and it is called from the parent process.
    12  func writeIDMaps(r *Runner, pid int) error {
    13  	var uidMappings, gidMappings, setGroups []byte
    14  	pidStr := strconv.Itoa(pid)
    15  
    16  	if r.UIDMappings == nil {
    17  		uidMappings = []byte("0 " + strconv.Itoa(unix.Geteuid()) + " 1")
    18  	} else {
    19  		uidMappings = formatIDMappings(r.UIDMappings)
    20  	}
    21  	if err := writeFile("/proc/"+pidStr+"/uid_map", uidMappings); err != nil {
    22  		return err
    23  	}
    24  
    25  	if r.GIDMappings == nil || !r.GIDMappingsEnableSetgroups {
    26  		setGroups = setGIDDeny
    27  	} else {
    28  		setGroups = setGIDAllow
    29  	}
    30  	if err := writeFile("/proc/"+pidStr+"/setgroups", setGroups); err != nil {
    31  		return err
    32  	}
    33  
    34  	if r.GIDMappings == nil {
    35  		gidMappings = []byte("0 " + strconv.Itoa(unix.Getegid()) + " 1")
    36  	} else {
    37  		gidMappings = formatIDMappings(r.GIDMappings)
    38  	}
    39  	if err := writeFile("/proc/"+pidStr+"/gid_map", gidMappings); err != nil {
    40  		return err
    41  	}
    42  	return nil
    43  }
    44  
    45  func formatIDMappings(idMap []syscall.SysProcIDMap) []byte {
    46  	var data []byte
    47  	for _, im := range idMap {
    48  		data = append(data, []byte(strconv.Itoa(im.ContainerID)+" "+strconv.Itoa(im.HostID)+" "+strconv.Itoa(im.Size)+"\n")...)
    49  	}
    50  	return data
    51  }
    52  
    53  // writeFile writes file
    54  func writeFile(path string, content []byte) error {
    55  	fd, err := unix.Open(path, unix.O_RDWR|unix.O_CLOEXEC, 0)
    56  	if err != nil {
    57  		return err
    58  	}
    59  	if _, err := unix.Write(fd, content); err != nil {
    60  		unix.Close(fd)
    61  		return err
    62  	}
    63  	if err := unix.Close(fd); err != nil {
    64  		return err
    65  	}
    66  	return nil
    67  }