Browse code

Fix setting cgroup permission to user/privileged devices

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2016/03/25 04:01:12
Showing 3 changed files
... ...
@@ -295,7 +295,18 @@ func specDevice(d *configs.Device) specs.Device {
295 295
 	}
296 296
 }
297 297
 
298
-func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []specs.Device, err error) {
298
+func specDeviceCgroup(d *configs.Device) specs.DeviceCgroup {
299
+	t := string(d.Type)
300
+	return specs.DeviceCgroup{
301
+		Allow:  true,
302
+		Type:   &t,
303
+		Major:  &d.Major,
304
+		Minor:  &d.Minor,
305
+		Access: &d.Permissions,
306
+	}
307
+}
308
+
309
+func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []specs.Device, devPermissions []specs.DeviceCgroup, err error) {
299 310
 	resolvedPathOnHost := deviceMapping.PathOnHost
300 311
 
301 312
 	// check if it is a symbolic link
... ...
@@ -309,7 +320,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
309 309
 	// if there was no error, return the device
310 310
 	if err == nil {
311 311
 		device.Path = deviceMapping.PathInContainer
312
-		return append(devs, specDevice(device)), nil
312
+		return append(devs, specDevice(device)), append(devPermissions, specDeviceCgroup(device)), nil
313 313
 	}
314 314
 
315 315
 	// if the device is not a device node
... ...
@@ -330,6 +341,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
330 330
 				// add the device to userSpecified devices
331 331
 				childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, deviceMapping.PathInContainer, 1)
332 332
 				devs = append(devs, specDevice(childDevice))
333
+				devPermissions = append(devPermissions, specDeviceCgroup(childDevice))
333 334
 
334 335
 				return nil
335 336
 			})
... ...
@@ -337,10 +349,10 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
337 337
 	}
338 338
 
339 339
 	if len(devs) > 0 {
340
-		return devs, nil
340
+		return devs, devPermissions, nil
341 341
 	}
342 342
 
343
-	return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
343
+	return devs, devPermissions, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
344 344
 }
345 345
 
346 346
 func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
... ...
@@ -78,6 +78,7 @@ func setResources(s *specs.Spec, r containertypes.Resources) error {
78 78
 func setDevices(s *specs.Spec, c *container.Container) error {
79 79
 	// Build lists of devices allowed and created within the container.
80 80
 	var devs []specs.Device
81
+	devPermissions := s.Linux.Resources.Devices
81 82
 	if c.HostConfig.Privileged {
82 83
 		hostDevices, err := devices.HostDevices()
83 84
 		if err != nil {
... ...
@@ -86,18 +87,26 @@ func setDevices(s *specs.Spec, c *container.Container) error {
86 86
 		for _, d := range hostDevices {
87 87
 			devs = append(devs, specDevice(d))
88 88
 		}
89
+		rwm := "rwm"
90
+		devPermissions = []specs.DeviceCgroup{
91
+			{
92
+				Allow:  true,
93
+				Access: &rwm,
94
+			},
95
+		}
89 96
 	} else {
90 97
 		for _, deviceMapping := range c.HostConfig.Devices {
91
-			d, err := getDevicesFromPath(deviceMapping)
98
+			d, dPermissions, err := getDevicesFromPath(deviceMapping)
92 99
 			if err != nil {
93 100
 				return err
94 101
 			}
95
-
96 102
 			devs = append(devs, d...)
103
+			devPermissions = append(devPermissions, dPermissions...)
97 104
 		}
98 105
 	}
99 106
 
100 107
 	s.Linux.Devices = append(s.Linux.Devices, devs...)
108
+	s.Linux.Resources.Devices = devPermissions
101 109
 	return nil
102 110
 }
103 111
 
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"strconv"
14 14
 	"strings"
15 15
 	"sync"
16
+	"syscall"
16 17
 	"time"
17 18
 
18 19
 	"github.com/docker/docker/pkg/homedir"
... ...
@@ -980,3 +981,29 @@ func (s *DockerSuite) TestRunPidsLimit(c *check.C) {
980 980
 	out = inspectField(c, "skittles", "HostConfig.PidsLimit")
981 981
 	c.Assert(out, checker.Equals, "2", check.Commentf("setting the pids limit failed"))
982 982
 }
983
+
984
+func (s *DockerSuite) TestRunPrivilegedAllowedDevices(c *check.C) {
985
+	testRequires(c, DaemonIsLinux)
986
+
987
+	file := "/sys/fs/cgroup/devices/devices.list"
988
+	out, _ := dockerCmd(c, "run", "--privileged", "busybox", "cat", file)
989
+	c.Logf("out: %q", out)
990
+	c.Assert(strings.TrimSpace(out), checker.Equals, "a *:* rwm")
991
+}
992
+
993
+func (s *DockerSuite) TestRunUserDeviceAllowed(c *check.C) {
994
+	testRequires(c, DaemonIsLinux)
995
+
996
+	fi, err := os.Stat("/dev/snd/timer")
997
+	if err != nil {
998
+		c.Skip("Host does not have /dev/snd/timer")
999
+	}
1000
+	stat, ok := fi.Sys().(*syscall.Stat_t)
1001
+	if !ok {
1002
+		c.Skip("Could not stat /dev/snd/timer")
1003
+	}
1004
+
1005
+	file := "/sys/fs/cgroup/devices/devices.list"
1006
+	out, _ := dockerCmd(c, "run", "--device", "/dev/snd/timer:w", "busybox", "cat", file)
1007
+	c.Assert(out, checker.Contains, fmt.Sprintf("c %d:%d w", stat.Rdev/256, stat.Rdev%256))
1008
+}