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 }