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  }