github.com/geofffranks/garden-linux@v0.0.0-20160715111146-26c893169cfa/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  		cmd.SysProcAttr.GidMappingsEnableSetgroups = true
    44  
    45  		cmd.SysProcAttr.Credential = &syscall.Credential{
    46  			Uid: 0,
    47  			Gid: 0,
    48  		}
    49  	}
    50  
    51  	cmd.SysProcAttr.Cloneflags = uintptr(flags)
    52  	cmd.ExtraFiles = e.ExtraFiles
    53  
    54  	if err := e.CommandRunner.Start(cmd); err != nil {
    55  		return 0, fmt.Errorf("system: failed to start the supplied command: %s", err)
    56  	}
    57  
    58  	return cmd.Process.Pid, nil
    59  }
    60  
    61  func makeSysProcIDMap(maxUid int) ([]syscall.SysProcIDMap, error) {
    62  	return []syscall.SysProcIDMap{
    63  		syscall.SysProcIDMap{
    64  			ContainerID: 0,
    65  			HostID:      maxUid,
    66  			Size:        1,
    67  		},
    68  		syscall.SysProcIDMap{
    69  			ContainerID: 1,
    70  			HostID:      1,
    71  			Size:        maxUid - 1,
    72  		},
    73  	}, nil
    74  }