Kaynağa Gözat

Merge pull request #21487 from tonistiigi/fix-old-dind

Fix setting cgroup permission to user/privileged devices
Sebastiaan van Stijn 9 yıl önce
ebeveyn
işleme
f3d824771a

+ 16 - 4
daemon/container_operations_unix.go

@@ -295,7 +295,18 @@ func specDevice(d *configs.Device) specs.Device {
 	}
 }
 
-func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []specs.Device, err error) {
+func specDeviceCgroup(d *configs.Device) specs.DeviceCgroup {
+	t := string(d.Type)
+	return specs.DeviceCgroup{
+		Allow:  true,
+		Type:   &t,
+		Major:  &d.Major,
+		Minor:  &d.Minor,
+		Access: &d.Permissions,
+	}
+}
+
+func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []specs.Device, devPermissions []specs.DeviceCgroup, err error) {
 	resolvedPathOnHost := deviceMapping.PathOnHost
 
 	// check if it is a symbolic link
@@ -309,7 +320,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
 	// if there was no error, return the device
 	if err == nil {
 		device.Path = deviceMapping.PathInContainer
-		return append(devs, specDevice(device)), nil
+		return append(devs, specDevice(device)), append(devPermissions, specDeviceCgroup(device)), nil
 	}
 
 	// if the device is not a device node
@@ -330,6 +341,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
 				// add the device to userSpecified devices
 				childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, deviceMapping.PathInContainer, 1)
 				devs = append(devs, specDevice(childDevice))
+				devPermissions = append(devPermissions, specDeviceCgroup(childDevice))
 
 				return nil
 			})
@@ -337,10 +349,10 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
 	}
 
 	if len(devs) > 0 {
-		return devs, nil
+		return devs, devPermissions, nil
 	}
 
-	return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
+	return devs, devPermissions, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
 }
 
 func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {

+ 5 - 5
daemon/daemon_unix.go

@@ -130,7 +130,7 @@ func getBlkioWeightDevices(config containertypes.Resources) ([]specs.WeightDevic
 		weight := weightDevice.Weight
 		d := specs.WeightDevice{Weight: &weight}
 		d.Major = int64(stat.Rdev / 256)
-		d.Major = int64(stat.Rdev % 256)
+		d.Minor = int64(stat.Rdev % 256)
 		blkioWeightDevices = append(blkioWeightDevices, d)
 	}
 
@@ -187,7 +187,7 @@ func getBlkioReadIOpsDevices(config containertypes.Resources) ([]specs.ThrottleD
 		rate := iopsDevice.Rate
 		d := specs.ThrottleDevice{Rate: &rate}
 		d.Major = int64(stat.Rdev / 256)
-		d.Major = int64(stat.Rdev % 256)
+		d.Minor = int64(stat.Rdev % 256)
 		blkioReadIOpsDevice = append(blkioReadIOpsDevice, d)
 	}
 
@@ -205,7 +205,7 @@ func getBlkioWriteIOpsDevices(config containertypes.Resources) ([]specs.Throttle
 		rate := iopsDevice.Rate
 		d := specs.ThrottleDevice{Rate: &rate}
 		d.Major = int64(stat.Rdev / 256)
-		d.Major = int64(stat.Rdev % 256)
+		d.Minor = int64(stat.Rdev % 256)
 		blkioWriteIOpsDevice = append(blkioWriteIOpsDevice, d)
 	}
 
@@ -223,7 +223,7 @@ func getBlkioReadBpsDevices(config containertypes.Resources) ([]specs.ThrottleDe
 		rate := bpsDevice.Rate
 		d := specs.ThrottleDevice{Rate: &rate}
 		d.Major = int64(stat.Rdev / 256)
-		d.Major = int64(stat.Rdev % 256)
+		d.Minor = int64(stat.Rdev % 256)
 		blkioReadBpsDevice = append(blkioReadBpsDevice, d)
 	}
 
@@ -241,7 +241,7 @@ func getBlkioWriteBpsDevices(config containertypes.Resources) ([]specs.ThrottleD
 		rate := bpsDevice.Rate
 		d := specs.ThrottleDevice{Rate: &rate}
 		d.Major = int64(stat.Rdev / 256)
-		d.Major = int64(stat.Rdev % 256)
+		d.Minor = int64(stat.Rdev % 256)
 		blkioWriteBpsDevice = append(blkioWriteBpsDevice, d)
 	}
 

+ 11 - 2
daemon/oci_linux.go

@@ -78,6 +78,7 @@ func setResources(s *specs.Spec, r containertypes.Resources) error {
 func setDevices(s *specs.Spec, c *container.Container) error {
 	// Build lists of devices allowed and created within the container.
 	var devs []specs.Device
+	devPermissions := s.Linux.Resources.Devices
 	if c.HostConfig.Privileged {
 		hostDevices, err := devices.HostDevices()
 		if err != nil {
@@ -86,18 +87,26 @@ func setDevices(s *specs.Spec, c *container.Container) error {
 		for _, d := range hostDevices {
 			devs = append(devs, specDevice(d))
 		}
+		rwm := "rwm"
+		devPermissions = []specs.DeviceCgroup{
+			{
+				Allow:  true,
+				Access: &rwm,
+			},
+		}
 	} else {
 		for _, deviceMapping := range c.HostConfig.Devices {
-			d, err := getDevicesFromPath(deviceMapping)
+			d, dPermissions, err := getDevicesFromPath(deviceMapping)
 			if err != nil {
 				return err
 			}
-
 			devs = append(devs, d...)
+			devPermissions = append(devPermissions, dPermissions...)
 		}
 	}
 
 	s.Linux.Devices = append(s.Linux.Devices, devs...)
+	s.Linux.Resources.Devices = devPermissions
 	return nil
 }
 

+ 27 - 0
integration-cli/docker_cli_run_unix_test.go

@@ -13,6 +13,7 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"syscall"
 	"time"
 
 	"github.com/docker/docker/pkg/homedir"
@@ -980,3 +981,29 @@ func (s *DockerSuite) TestRunPidsLimit(c *check.C) {
 	out = inspectField(c, "skittles", "HostConfig.PidsLimit")
 	c.Assert(out, checker.Equals, "2", check.Commentf("setting the pids limit failed"))
 }
+
+func (s *DockerSuite) TestRunPrivilegedAllowedDevices(c *check.C) {
+	testRequires(c, DaemonIsLinux)
+
+	file := "/sys/fs/cgroup/devices/devices.list"
+	out, _ := dockerCmd(c, "run", "--privileged", "busybox", "cat", file)
+	c.Logf("out: %q", out)
+	c.Assert(strings.TrimSpace(out), checker.Equals, "a *:* rwm")
+}
+
+func (s *DockerSuite) TestRunUserDeviceAllowed(c *check.C) {
+	testRequires(c, DaemonIsLinux)
+
+	fi, err := os.Stat("/dev/snd/timer")
+	if err != nil {
+		c.Skip("Host does not have /dev/snd/timer")
+	}
+	stat, ok := fi.Sys().(*syscall.Stat_t)
+	if !ok {
+		c.Skip("Could not stat /dev/snd/timer")
+	}
+
+	file := "/sys/fs/cgroup/devices/devices.list"
+	out, _ := dockerCmd(c, "run", "--device", "/dev/snd/timer:w", "busybox", "cat", file)
+	c.Assert(out, checker.Contains, fmt.Sprintf("c %d:%d w", stat.Rdev/256, stat.Rdev%256))
+}