Browse code

Cgroups allow devices for privileged containers Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/02/25 08:47:23
Showing 3 changed files
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"fmt"
7 7
 	"github.com/dotcloud/docker/execdriver"
8 8
 	"github.com/dotcloud/docker/execdriver/lxc"
9
+	"github.com/dotcloud/docker/pkg/cgroups"
9 10
 	"github.com/dotcloud/docker/pkg/libcontainer"
10 11
 	"github.com/dotcloud/docker/pkg/libcontainer/nsinit"
11 12
 	"io"
... ...
@@ -13,6 +14,7 @@ import (
13 13
 	"os"
14 14
 	"os/exec"
15 15
 	"path/filepath"
16
+	"strconv"
16 17
 	"strings"
17 18
 	"syscall"
18 19
 )
... ...
@@ -125,7 +127,40 @@ func (d *driver) Name() string {
125 125
 }
126 126
 
127 127
 func (d *driver) GetPidsForContainer(id string) ([]int, error) {
128
-	return nil, ErrNotSupported
128
+	pids := []int{}
129
+
130
+	subsystem := "cpu"
131
+	cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem)
132
+	if err != nil {
133
+		return pids, err
134
+	}
135
+	cgroupRoot = filepath.Dir(cgroupRoot)
136
+
137
+	cgroupDir, err := cgroups.GetThisCgroupDir(subsystem)
138
+	if err != nil {
139
+		return pids, err
140
+	}
141
+
142
+	filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
143
+	if _, err := os.Stat(filename); os.IsNotExist(err) {
144
+		filename = filepath.Join(cgroupRoot, cgroupDir, "docker", id, "tasks")
145
+	}
146
+
147
+	output, err := ioutil.ReadFile(filename)
148
+	if err != nil {
149
+		return pids, err
150
+	}
151
+	for _, p := range strings.Split(string(output), "\n") {
152
+		if len(p) == 0 {
153
+			continue
154
+		}
155
+		pid, err := strconv.Atoi(p)
156
+		if err != nil {
157
+			return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
158
+		}
159
+		pids = append(pids, pid)
160
+	}
161
+	return pids, nil
129 162
 }
130 163
 
131 164
 func writeContainerFile(container *libcontainer.Container, rootfs string) error {
... ...
@@ -219,6 +254,7 @@ func createContainer(c *execdriver.Command) *libcontainer.Container {
219 219
 	}
220 220
 	if c.Privileged {
221 221
 		container.Capabilities = nil
222
+		container.Cgroups.DeviceAccess = true
222 223
 	}
223 224
 	if c.Resources != nil {
224 225
 		container.Cgroups.CpuShares = c.Resources.CpuShares
... ...
@@ -1581,8 +1581,8 @@ func TestPrivilegedCanMknod(t *testing.T) {
1581 1581
 	eng := NewTestEngine(t)
1582 1582
 	runtime := mkRuntimeFromEngine(eng, t)
1583 1583
 	defer runtime.Nuke()
1584
-	if output, _ := runContainer(eng, runtime, []string{"-privileged", "_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" {
1585
-		t.Fatal("Could not mknod into privileged container")
1584
+	if output, err := runContainer(eng, runtime, []string{"-privileged", "_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" {
1585
+		t.Fatalf("Could not mknod into privileged container %s %v", output, err)
1586 1586
 	}
1587 1587
 }
1588 1588
 
... ...
@@ -9,7 +9,6 @@ import (
9 9
 	"github.com/dotcloud/docker/pkg/libcontainer/network"
10 10
 	"github.com/dotcloud/docker/pkg/system"
11 11
 	"github.com/dotcloud/docker/pkg/user"
12
-	"log"
13 12
 	"os"
14 13
 	"os/exec"
15 14
 	"path/filepath"
... ...
@@ -23,7 +22,6 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync
23 23
 	if err != nil {
24 24
 		return err
25 25
 	}
26
-	log.Printf("initializing namespace at %s", rootfs)
27 26
 
28 27
 	// We always read this as it is a way to sync with the parent as well
29 28
 	context, err := syncPipe.ReadFromParent()
... ...
@@ -32,10 +30,8 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync
32 32
 		return err
33 33
 	}
34 34
 	syncPipe.Close()
35
-	log.Printf("received context from parent %v", context)
36 35
 
37 36
 	if console != "" {
38
-		log.Printf("setting up console for %s", console)
39 37
 		// close pipes so that we can replace it with the pty
40 38
 		closeStdPipes()
41 39
 		slave, err := openTerminal(console, syscall.O_RDWR)
... ...
@@ -66,11 +62,9 @@ func Init(container *libcontainer.Container, uncleanRootfs, console string, sync
66 66
 	if err := system.Sethostname(container.Hostname); err != nil {
67 67
 		return fmt.Errorf("sethostname %s", err)
68 68
 	}
69
-	log.Printf("dropping capabilities")
70 69
 	if err := capabilities.DropCapabilities(container); err != nil {
71 70
 		return fmt.Errorf("drop capabilities %s", err)
72 71
 	}
73
-	log.Printf("setting user in namespace")
74 72
 	if err := setupUser(container); err != nil {
75 73
 		return fmt.Errorf("setup user %s", err)
76 74
 	}
... ...
@@ -87,7 +81,6 @@ func execArgs(args []string, env []string) error {
87 87
 	if err != nil {
88 88
 		return err
89 89
 	}
90
-	log.Printf("execing %s goodbye", name)
91 90
 	if err := system.Exec(name, args[0:], env); err != nil {
92 91
 		return fmt.Errorf("exec %s", err)
93 92
 	}
... ...
@@ -111,7 +104,7 @@ func resolveRootfs(uncleanRootfs string) (string, error) {
111 111
 }
112 112
 
113 113
 func setupUser(container *libcontainer.Container) error {
114
-	if container.User != "" {
114
+	if container.User != "" && container.User != "root" {
115 115
 		uid, gid, suppGids, err := user.GetUserGroupSupplementary(container.User, syscall.Getuid(), syscall.Getgid())
116 116
 		if err != nil {
117 117
 			return err