github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/daemon/execdriver/native/exec.go (about) 1 // +build linux 2 3 package native 4 5 import ( 6 "fmt" 7 "os" 8 "os/exec" 9 "strings" 10 "syscall" 11 12 "github.com/docker/docker/daemon/execdriver" 13 "github.com/opencontainers/runc/libcontainer" 14 // Blank import 'nsenter' so that init in that package will call c 15 // function 'nsexec()' to do 'setns' before Go runtime take over, 16 // it's used for join to exist ns like 'docker exec' command. 17 _ "github.com/opencontainers/runc/libcontainer/nsenter" 18 "github.com/opencontainers/runc/libcontainer/utils" 19 ) 20 21 // Exec implements the exec driver Driver interface, 22 // it calls libcontainer APIs to execute a container. 23 func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) { 24 active := d.activeContainers[c.ID] 25 if active == nil { 26 return -1, fmt.Errorf("No active container exists with ID %s", c.ID) 27 } 28 29 user := processConfig.User 30 if c.RemappedRoot.UID != 0 && user == "" { 31 //if user namespaces are enabled, set user explicitly so uid/gid is set to 0 32 //otherwise we end up with the overflow id and no permissions (65534) 33 user = "0" 34 } 35 36 p := &libcontainer.Process{ 37 Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...), 38 Env: c.ProcessConfig.Env, 39 Cwd: c.WorkingDir, 40 User: user, 41 } 42 43 if processConfig.Privileged { 44 p.Capabilities = execdriver.GetAllCapabilities() 45 } 46 // add CAP_ prefix to all caps for new libcontainer update to match 47 // the spec format. 48 for i, s := range p.Capabilities { 49 if !strings.HasPrefix(s, "CAP_") { 50 p.Capabilities[i] = fmt.Sprintf("CAP_%s", s) 51 } 52 } 53 54 config := active.Config() 55 if err := setupPipes(&config, processConfig, p, pipes); err != nil { 56 return -1, err 57 } 58 59 if err := active.Start(p); err != nil { 60 return -1, err 61 } 62 63 if hooks.Start != nil { 64 pid, err := p.Pid() 65 if err != nil { 66 p.Signal(os.Kill) 67 p.Wait() 68 return -1, err 69 } 70 71 // A closed channel for OOM is returned here as it will be 72 // non-blocking and return the correct result when read. 73 chOOM := make(chan struct{}) 74 close(chOOM) 75 hooks.Start(&c.ProcessConfig, pid, chOOM) 76 } 77 78 ps, err := p.Wait() 79 if err != nil { 80 exitErr, ok := err.(*exec.ExitError) 81 if !ok { 82 return -1, err 83 } 84 ps = exitErr.ProcessState 85 } 86 return utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), nil 87 }