mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Fix setting cgroup permission to user/privileged devices
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit ee61235880
)
This commit is contained in:
parent
6d324b4192
commit
c5e8051c81
3 changed files with 54 additions and 6 deletions
|
@ -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
|
resolvedPathOnHost := deviceMapping.PathOnHost
|
||||||
|
|
||||||
// check if it is a symbolic link
|
// 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 there was no error, return the device
|
||||||
if err == nil {
|
if err == nil {
|
||||||
device.Path = deviceMapping.PathInContainer
|
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
|
// 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
|
// add the device to userSpecified devices
|
||||||
childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, deviceMapping.PathInContainer, 1)
|
childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, deviceMapping.PathInContainer, 1)
|
||||||
devs = append(devs, specDevice(childDevice))
|
devs = append(devs, specDevice(childDevice))
|
||||||
|
devPermissions = append(devPermissions, specDeviceCgroup(childDevice))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -337,10 +349,10 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(devs) > 0 {
|
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 {
|
func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
|
||||||
|
|
|
@ -78,6 +78,7 @@ func setResources(s *specs.Spec, r containertypes.Resources) error {
|
||||||
func setDevices(s *specs.Spec, c *container.Container) error {
|
func setDevices(s *specs.Spec, c *container.Container) error {
|
||||||
// Build lists of devices allowed and created within the container.
|
// Build lists of devices allowed and created within the container.
|
||||||
var devs []specs.Device
|
var devs []specs.Device
|
||||||
|
devPermissions := s.Linux.Resources.Devices
|
||||||
if c.HostConfig.Privileged {
|
if c.HostConfig.Privileged {
|
||||||
hostDevices, err := devices.HostDevices()
|
hostDevices, err := devices.HostDevices()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -86,18 +87,26 @@ func setDevices(s *specs.Spec, c *container.Container) error {
|
||||||
for _, d := range hostDevices {
|
for _, d := range hostDevices {
|
||||||
devs = append(devs, specDevice(d))
|
devs = append(devs, specDevice(d))
|
||||||
}
|
}
|
||||||
|
rwm := "rwm"
|
||||||
|
devPermissions = []specs.DeviceCgroup{
|
||||||
|
{
|
||||||
|
Allow: true,
|
||||||
|
Access: &rwm,
|
||||||
|
},
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, deviceMapping := range c.HostConfig.Devices {
|
for _, deviceMapping := range c.HostConfig.Devices {
|
||||||
d, err := getDevicesFromPath(deviceMapping)
|
d, dPermissions, err := getDevicesFromPath(deviceMapping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
devs = append(devs, d...)
|
devs = append(devs, d...)
|
||||||
|
devPermissions = append(devPermissions, dPermissions...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Linux.Devices = append(s.Linux.Devices, devs...)
|
s.Linux.Devices = append(s.Linux.Devices, devs...)
|
||||||
|
s.Linux.Resources.Devices = devPermissions
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/homedir"
|
"github.com/docker/docker/pkg/homedir"
|
||||||
|
@ -980,3 +981,29 @@ func (s *DockerSuite) TestRunPidsLimit(c *check.C) {
|
||||||
out = inspectField(c, "skittles", "HostConfig.PidsLimit")
|
out = inspectField(c, "skittles", "HostConfig.PidsLimit")
|
||||||
c.Assert(out, checker.Equals, "2", check.Commentf("setting the pids limit failed"))
|
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))
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue