github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/container_daemon/proc_starter/start.go (about)

     1  package proc_starter
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"runtime"
     8  	"strconv"
     9  	"syscall"
    10  
    11  	"flag"
    12  
    13  	"github.com/cloudfoundry-incubator/garden-linux/container_daemon"
    14  	"github.com/cloudfoundry-incubator/garden-linux/system"
    15  	"github.com/docker/docker/pkg/reexec"
    16  )
    17  
    18  func init() {
    19  	runtime.LockOSThread()
    20  	reexec.Register("proc_starter", start)
    21  }
    22  
    23  // proc_starter starts a user process with the correct rlimits and after
    24  // closing any open FDs.
    25  func start() {
    26  	rlimits := flag.String("rlimits", "", "encoded rlimits")
    27  	dropCapabilities := flag.Bool("dropCapabilities", true, "drop capabilities before starting process")
    28  	uid := flag.Int("uid", -1, "user id to run the process as")
    29  	gid := flag.Int("gid", -1, "group id to run the process as")
    30  	workDir := flag.String("workDir", "", "working dir for the process")
    31  	extendedWhitelist := flag.Bool("extendedWhitelist", false, "whitelist CAP_SYS_ADMIN in addition to the default set. Use only with -dropCapabilities=true")
    32  	flag.Parse()
    33  
    34  	closeFds()
    35  
    36  	mgr := &container_daemon.RlimitsManager{}
    37  	must(mgr.Apply(mgr.DecodeLimits(*rlimits)))
    38  
    39  	args := flag.Args()
    40  
    41  	if *dropCapabilities {
    42  		caps := &system.ProcessCapabilities{Pid: os.Getpid()}
    43  		must(caps.Limit(*extendedWhitelist))
    44  	}
    45  
    46  	execer := system.UserExecer{}
    47  	if err := execer.ExecAsUser(*uid, *gid, *workDir, args[0], args[1:]...); err != nil {
    48  		fmt.Fprintf(os.Stderr, "proc_starter: ExecAsUser: %s\n", err)
    49  		os.Exit(255)
    50  	}
    51  }
    52  
    53  func closeFds() {
    54  	fds, err := ioutil.ReadDir("/proc/self/fd")
    55  	if err != nil {
    56  		fmt.Fprintf(os.Stderr, "ERROR: read /proc/self/fd: %s", err)
    57  		os.Exit(255)
    58  	}
    59  
    60  	for _, fd := range fds {
    61  		if fd.IsDir() {
    62  			continue
    63  		}
    64  
    65  		fdI, err := strconv.Atoi(fd.Name())
    66  		if err != nil {
    67  			panic(err) // cant happen
    68  		}
    69  
    70  		if fdI <= 2 {
    71  			continue
    72  		}
    73  
    74  		syscall.CloseOnExec(fdI)
    75  	}
    76  }
    77  
    78  var must = mustNot
    79  
    80  func mustNot(err error) {
    81  	if err != nil {
    82  		panic(err)
    83  	}
    84  }