From a76407ac61dd57429a1350f840c323f45a97b27f Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 24 Feb 2014 15:47:23 -0800 Subject: [PATCH] Cgroups allow devices for privileged containers Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- execdriver/namespaces/driver.go | 38 ++++++++++++++++++++++++++++++++- integration/container_test.go | 4 ++-- pkg/libcontainer/nsinit/init.go | 9 +------- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/execdriver/namespaces/driver.go b/execdriver/namespaces/driver.go index 6cb2e5b522..cd5bb9f35e 100644 --- a/execdriver/namespaces/driver.go +++ b/execdriver/namespaces/driver.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/dotcloud/docker/execdriver" "github.com/dotcloud/docker/execdriver/lxc" + "github.com/dotcloud/docker/pkg/cgroups" "github.com/dotcloud/docker/pkg/libcontainer" "github.com/dotcloud/docker/pkg/libcontainer/nsinit" "io" @@ -13,6 +14,7 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "syscall" ) @@ -125,7 +127,40 @@ func (d *driver) Name() string { } func (d *driver) GetPidsForContainer(id string) ([]int, error) { - return nil, ErrNotSupported + pids := []int{} + + subsystem := "cpu" + cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem) + if err != nil { + return pids, err + } + cgroupRoot = filepath.Dir(cgroupRoot) + + cgroupDir, err := cgroups.GetThisCgroupDir(subsystem) + if err != nil { + return pids, err + } + + filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks") + if _, err := os.Stat(filename); os.IsNotExist(err) { + filename = filepath.Join(cgroupRoot, cgroupDir, "docker", id, "tasks") + } + + output, err := ioutil.ReadFile(filename) + if err != nil { + return pids, err + } + for _, p := range strings.Split(string(output), "\n") { + if len(p) == 0 { + continue + } + pid, err := strconv.Atoi(p) + if err != nil { + return pids, fmt.Errorf("Invalid pid '%s': %s", p, err) + } + pids = append(pids, pid) + } + return pids, nil } func writeContainerFile(container *libcontainer.Container, rootfs string) error { @@ -219,6 +254,7 @@ func createContainer(c *execdriver.Command) *libcontainer.Container { } if c.Privileged { container.Capabilities = nil + container.Cgroups.DeviceAccess = true } if c.Resources != nil { container.Cgroups.CpuShares = c.Resources.CpuShares diff --git a/integration/container_test.go b/integration/container_test.go index ea0283260a..8e4314f456 100644 --- a/integration/container_test.go +++ b/integration/container_test.go @@ -1581,8 +1581,8 @@ func TestPrivilegedCanMknod(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer runtime.Nuke() - if output, _ := runContainer(eng, runtime, []string{"-privileged", "_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" { - t.Fatal("Could not mknod into privileged container") + if output, err := runContainer(eng, runtime, []string{"-privileged", "_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" { + t.Fatalf("Could not mknod into privileged container %s %v", output, err) } } diff --git a/pkg/libcontainer/nsinit/init.go b/pkg/libcontainer/nsinit/init.go index 23303cd704..d6d7dc3347 100644 --- a/pkg/libcontainer/nsinit/init.go +++ b/pkg/libcontainer/nsinit/init.go @@ -9,7 +9,6 @@ import ( "github.com/dotcloud/docker/pkg/libcontainer/network" "github.com/dotcloud/docker/pkg/system" "github.com/dotcloud/docker/pkg/user" - "log" "os" "os/exec" "path/filepath" @@ -23,7 +22,6 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync if err != nil { return err } - log.Printf("initializing namespace at %s", rootfs) // We always read this as it is a way to sync with the parent as well context, err := syncPipe.ReadFromParent() @@ -32,10 +30,8 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync return err } syncPipe.Close() - log.Printf("received context from parent %v", context) if console != "" { - log.Printf("setting up console for %s", console) // close pipes so that we can replace it with the pty closeStdPipes() slave, err := openTerminal(console, syscall.O_RDWR) @@ -66,11 +62,9 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync if err := system.Sethostname(container.Hostname); err != nil { return fmt.Errorf("sethostname %s", err) } - log.Printf("dropping capabilities") if err := capabilities.DropCapabilities(container); err != nil { return fmt.Errorf("drop capabilities %s", err) } - log.Printf("setting user in namespace") if err := setupUser(container); err != nil { return fmt.Errorf("setup user %s", err) } @@ -87,7 +81,6 @@ func execArgs(args []string, env []string) error { if err != nil { return err } - log.Printf("execing %s goodbye", name) if err := system.Exec(name, args[0:], env); err != nil { return fmt.Errorf("exec %s", err) } @@ -111,7 +104,7 @@ func resolveRootfs(uncleanRootfs string) (string, error) { } func setupUser(container *libcontainer.Container) error { - if container.User != "" { + if container.User != "" && container.User != "root" { uid, gid, suppGids, err := user.GetUserGroupSupplementary(container.User, syscall.Getuid(), syscall.Getgid()) if err != nil { return err