github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/containerizer/system/namespacing_execer_linux.go (about) 1 package system 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "syscall" 8 9 "github.com/cloudfoundry/gunk/command_runner" 10 ) 11 12 const UIDMappingRange = 65536 13 14 type NamespacingExecer struct { 15 CommandRunner command_runner.CommandRunner 16 ExtraFiles []*os.File 17 Privileged bool 18 19 // When User Namespaces are enabled, maps 1-MaxUID-1 UIDS, and 20 // maps container root (0) to MaxUID 21 MaxUID int 22 } 23 24 func (e *NamespacingExecer) Exec(binPath string, args ...string) (int, error) { 25 cmd := exec.Command(binPath, args...) 26 cmd.SysProcAttr = &syscall.SysProcAttr{} 27 28 flags := syscall.CLONE_NEWIPC 29 flags = flags | syscall.CLONE_NEWNET 30 flags = flags | syscall.CLONE_NEWNS 31 flags = flags | syscall.CLONE_NEWUTS 32 flags = flags | syscall.CLONE_NEWPID 33 34 if !e.Privileged { 35 flags = flags | syscall.CLONE_NEWUSER 36 37 mapping, err := makeSysProcIDMap(e.MaxUID) 38 if err != nil { 39 return 0, err 40 } 41 cmd.SysProcAttr.UidMappings = mapping 42 cmd.SysProcAttr.GidMappings = mapping 43 44 cmd.SysProcAttr.Credential = &syscall.Credential{ 45 Uid: 0, 46 Gid: 0, 47 } 48 } 49 50 cmd.SysProcAttr.Cloneflags = uintptr(flags) 51 cmd.ExtraFiles = e.ExtraFiles 52 53 if err := e.CommandRunner.Start(cmd); err != nil { 54 return 0, fmt.Errorf("system: failed to start the supplied command: %s", err) 55 } 56 57 return cmd.Process.Pid, nil 58 } 59 60 func makeSysProcIDMap(maxUid int) ([]syscall.SysProcIDMap, error) { 61 return []syscall.SysProcIDMap{ 62 syscall.SysProcIDMap{ 63 ContainerID: 0, 64 HostID: maxUid, 65 Size: 1, 66 }, 67 syscall.SysProcIDMap{ 68 ContainerID: 1, 69 HostID: 1, 70 Size: maxUid - 1, 71 }, 72 }, nil 73 }