Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Commit

Permalink
Separate the code paths for userns and default cases.
Browse files Browse the repository at this point in the history
Signed-off-by: Mrunal Patel <mrunalp@gmail.com> (github: mrunalp)
  • Loading branch information
mrunalp committed Jan 14, 2015
1 parent 6647d5b commit 0c50197
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 20 deletions.
34 changes: 18 additions & 16 deletions namespaces/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,27 +101,29 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
defer libcontainer.DeleteState(dataPath)

// Start the setup process to setup the init process
log.Println("Starting setup")
setupCmd := setupCommand(container, console, dataPath, os.Args[0])
setupOut, _ := setupCmd.StderrPipe()
err = setupCmd.Start()
if err != nil {
command.Process.Kill()
command.Wait()
log.Println("setup failed: %v", err)
return -1, err
}
out, _ := ioutil.ReadAll(setupOut)
log.Println("Setup output: ", string(out))

if err := setupCmd.Wait(); err != nil {
if _, ok := err.(*exec.ExitError); !ok {
if container.Namespaces.Contains(libcontainer.NEWUSER) {
log.Println("Starting setup")
setupCmd := setupCommand(container, console, dataPath, os.Args[0])
setupOut, _ := setupCmd.StderrPipe()
err = setupCmd.Start()
if err != nil {
command.Process.Kill()
command.Wait()
log.Println("setup failed: %v", err)
return -1, err
}
out, _ := ioutil.ReadAll(setupOut)
log.Println("Setup output: ", string(out))

if err := setupCmd.Wait(); err != nil {
if _, ok := err.(*exec.ExitError); !ok {
command.Process.Kill()
command.Wait()
return -1, err
}
}
log.Println("Setup return code", setupCmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus())
}
log.Println("Setup return code", setupCmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus())

// send the state to the container's init process then shutdown writes for the parent
if err := json.NewEncoder(parent).Encode(networkState); err != nil {
Expand Down
113 changes: 109 additions & 4 deletions namespaces/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/docker/libcontainer/apparmor"
"github.com/docker/libcontainer/console"
"github.com/docker/libcontainer/label"
"github.com/docker/libcontainer/mount"
"github.com/docker/libcontainer/netlink"
"github.com/docker/libcontainer/network"
"github.com/docker/libcontainer/security/capabilities"
Expand Down Expand Up @@ -47,6 +48,20 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, pip
pipe.Close()
}()

if container.Namespaces.Contains(libcontainer.NEWUSER) {
err = initUserNs(container, uncleanRootfs, consolePath, pipe, args)
} else {
err = initDefault(container, uncleanRootfs, consolePath, pipe, args)
}
return err
}

func initDefault(container *libcontainer.Config, uncleanRootfs, consolePath string, pipe *os.File, args []string) (err error) {
rootfs, err := utils.ResolveRootfs(uncleanRootfs)
if err != nil {
return err
}

// clear the current processes env and replace it with the environment
// defined on the container
if err := LoadContainerEnvironment(container); err != nil {
Expand All @@ -63,7 +78,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, pip
return err
}
if consolePath != "" {
if err := console.OpenAndDup("/dev/console"); err != nil {
if err := console.OpenAndDup(consolePath); err != nil {
return err
}
}
Expand All @@ -76,20 +91,110 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, pip
}
}

if container.WorkingDir == "" {
container.WorkingDir = "/"
if err := setupNetwork(container, networkState); err != nil {
return fmt.Errorf("setup networking %s", err)
}
if err := setupRoute(container); err != nil {
return fmt.Errorf("setup route %s", err)
}

if err := setupRlimits(container); err != nil {
return fmt.Errorf("setup rlimits %s", err)
}

label.Init()

if err := mount.InitializeMountNamespace(rootfs,
consolePath,
container.RestrictSys,
0, // Default Root Uid
(*mount.MountConfig)(container.MountConfig)); err != nil {
return fmt.Errorf("setup mount namespace %s", err)
}

if container.Hostname != "" {
if err := syscall.Sethostname([]byte(container.Hostname)); err != nil {
return fmt.Errorf("sethostname %s", err)
return fmt.Errorf("unable to sethostname %q: %s", container.Hostname, err)
}
}

if err := apparmor.ApplyProfile(container.AppArmorProfile); err != nil {
return fmt.Errorf("set apparmor profile %s: %s", container.AppArmorProfile, err)
}

if err := label.SetProcessLabel(container.ProcessLabel); err != nil {
return fmt.Errorf("set process label %s", err)
}

// TODO: (crosbymichael) make this configurable at the Config level
if container.RestrictSys {
if err := restrict.Restrict("proc/sys", "proc/sysrq-trigger", "proc/irq", "proc/bus"); err != nil {
return err
}
}

pdeathSignal, err := system.GetParentDeathSignal()
if err != nil {
return fmt.Errorf("get parent death signal %s", err)
}

if err := FinalizeNamespace(container); err != nil {
return fmt.Errorf("finalize namespace %s", err)
}

// FinalizeNamespace can change user/group which clears the parent death
// signal, so we restore it here.
if err := RestoreParentDeathSignal(pdeathSignal); err != nil {
return fmt.Errorf("restore parent death signal %s", err)
}

return system.Execv(args[0], args[0:], os.Environ())
}

func initUserNs(container *libcontainer.Config, uncleanRootfs, consolePath string, pipe *os.File, args []string) (err error) {
// clear the current processes env and replace it with the environment
// defined on the container
if err := LoadContainerEnvironment(container); err != nil {
return err
}

// We always read this as it is a way to sync with the parent as well
var networkState *network.NetworkState
if err := json.NewDecoder(pipe).Decode(&networkState); err != nil {
return err
}
// join any namespaces via a path to the namespace fd if provided
if err := joinExistingNamespaces(container.Namespaces); err != nil {
return err
}
if consolePath != "" {
if err := console.OpenAndDup("/dev/console"); err != nil {
return err
}
}
if _, err := syscall.Setsid(); err != nil {
return fmt.Errorf("setsid %s", err)
}
if consolePath != "" {
if err := system.Setctty(); err != nil {
return fmt.Errorf("setctty %s", err)
}
}

if container.WorkingDir == "" {
container.WorkingDir = "/"
}

if err := setupRlimits(container); err != nil {
return fmt.Errorf("setup rlimits %s", err)
}

if container.Hostname != "" {
if err := syscall.Sethostname([]byte(container.Hostname)); err != nil {
return fmt.Errorf("sethostname %s", err)
}
}

if err := apparmor.ApplyProfile(container.AppArmorProfile); err != nil {
fmt.Println("apparmor issue: %v", err)
return fmt.Errorf("set apparmor profile %s: %s", container.AppArmorProfile, err)
Expand Down

0 comments on commit 0c50197

Please sign in to comment.