Merge pull request #6097 from timthelion/consistentdevices

Refactor device handling code
This commit is contained in:
unclejack 2014-05-31 03:34:52 +03:00
commit 000552944e
11 changed files with 377 additions and 144 deletions

View file

@ -2,6 +2,8 @@ package cgroups
import (
"errors"
"github.com/dotcloud/docker/pkg/libcontainer/devices"
)
var (
@ -10,17 +12,18 @@ var (
type Cgroup struct {
Name string `json:"name,omitempty"`
Parent string `json:"parent,omitempty"`
Parent string `json:"parent,omitempty"` // name of parent cgroup or slice
DeviceAccess bool `json:"device_access,omitempty"` // name of parent cgroup or slice
Memory int64 `json:"memory,omitempty"` // Memory limit (in bytes)
MemoryReservation int64 `json:"memory_reservation,omitempty"` // Memory reservation or soft_limit (in bytes)
MemorySwap int64 `json:"memory_swap,omitempty"` // Total memory usage (memory + swap); set `-1' to disable swap
CpuShares int64 `json:"cpu_shares,omitempty"` // CPU shares (relative weight vs. other containers)
CpuQuota int64 `json:"cpu_quota,omitempty"` // CPU hardcap limit (in usecs). Allowed cpu time in a given period.
CpuPeriod int64 `json:"cpu_period,omitempty"` // CPU period to be used for hardcapping (in usecs). 0 to use system default.
CpusetCpus string `json:"cpuset_cpus,omitempty"` // CPU to use
Freezer string `json:"freezer,omitempty"` // set the freeze value for the process
AllowAllDevices bool `json:"allow_all_devices,omitempty"` // If this is true allow access to any kind of device within the container. If false, allow access only to devices explicitly listed in the allowed_devices list.
AllowedDevices []devices.Device `json:"allowed_devices,omitempty"`
Memory int64 `json:"memory,omitempty"` // Memory limit (in bytes)
MemoryReservation int64 `json:"memory_reservation,omitempty"` // Memory reservation or soft_limit (in bytes)
MemorySwap int64 `json:"memory_swap,omitempty"` // Total memory usage (memory + swap); set `-1' to disable swap
CpuShares int64 `json:"cpu_shares,omitempty"` // CPU shares (relative weight vs. other containers)
CpuQuota int64 `json:"cpu_quota,omitempty"` // CPU hardcap limit (in usecs). Allowed cpu time in a given period.
CpuPeriod int64 `json:"cpu_period,omitempty"` // CPU period to be used for hardcapping (in usecs). 0 to use system default.
CpusetCpus string `json:"cpuset_cpus,omitempty"` // CPU to use
Freezer string `json:"freezer,omitempty"` // set the freeze value for the process
Slice string `json:"slice,omitempty"` // Parent slice to use for systemd
}

View file

@ -11,41 +11,13 @@ func (s *devicesGroup) Set(d *data) error {
return err
}
if !d.c.DeviceAccess {
if !d.c.AllowAllDevices {
if err := writeFile(dir, "devices.deny", "a"); err != nil {
return err
}
allow := []string{
// allow mknod for any device
"c *:* m",
"b *:* m",
// /dev/null, zero, full
"c 1:3 rwm",
"c 1:5 rwm",
"c 1:7 rwm",
// consoles
"c 5:1 rwm",
"c 5:0 rwm",
"c 4:0 rwm",
"c 4:1 rwm",
// /dev/urandom,/dev/random
"c 1:9 rwm",
"c 1:8 rwm",
// /dev/pts/ - pts namespaces are "coming soon"
"c 136:* rwm",
"c 5:2 rwm",
// tuntap
"c 10:200 rwm",
}
for _, val := range allow {
if err := writeFile(dir, "devices.allow", val); err != nil {
for _, dev := range d.c.AllowedDevices {
if err := writeFile(dir, "devices.allow", dev.GetCgroupAllowString()); err != nil {
return err
}
}

View file

@ -21,11 +21,6 @@ type systemdCgroup struct {
cleanupDirs []string
}
type DeviceAllow struct {
Node string
Permissions string
}
var (
connLock sync.Mutex
theConn *systemd1.Conn
@ -116,24 +111,9 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
systemd1.Property{"PIDs", dbus.MakeVariant([]uint32{uint32(pid)})},
)
if !c.DeviceAccess {
if !c.AllowAllDevices {
properties = append(properties,
systemd1.Property{"DevicePolicy", dbus.MakeVariant("strict")},
systemd1.Property{"DeviceAllow", dbus.MakeVariant([]DeviceAllow{
{"/dev/null", "rwm"},
{"/dev/zero", "rwm"},
{"/dev/full", "rwm"},
{"/dev/random", "rwm"},
{"/dev/urandom", "rwm"},
{"/dev/tty", "rwm"},
{"/dev/console", "rwm"},
{"/dev/tty0", "rwm"},
{"/dev/tty1", "rwm"},
{"/dev/pts/ptmx", "rwm"},
// There is no way to add /dev/pts/* here atm, so we hack this manually below
// /dev/pts/* (how to add this?)
// Same with tuntap, which doesn't exist as a node most of the time
})})
systemd1.Property{"DevicePolicy", dbus.MakeVariant("strict")})
}
// Always enable accounting, this gets us the same behaviour as the fs implementation,
@ -167,28 +147,16 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
cgroup := props["ControlGroup"].(string)
if !c.DeviceAccess {
if !c.AllowAllDevices {
mountpoint, err := cgroups.FindCgroupMountpoint("devices")
if err != nil {
return nil, err
}
path := filepath.Join(mountpoint, cgroup)
allow := []string{
// allow mknod for any device
"c *:* m",
"b *:* m",
// /dev/pts/ - pts namespaces are "coming soon"
"c 136:* rwm",
// tuntap
"c 10:200 rwm",
}
for _, val := range allow {
if err := ioutil.WriteFile(filepath.Join(path, "devices.allow"), []byte(val), 0700); err != nil {
dir := filepath.Join(mountpoint, cgroup)
// We use the same method of allowing devices as in the fs backend. This needs to be changed to use DBUS as soon as possible. However, that change has to wait untill http://cgit.freedesktop.org/systemd/systemd/commit/?id=90060676c442604780634c0a993e3f9c3733f8e6 has been applied in most commonly used systemd versions.
for _, dev := range c.AllowedDevices {
if err := writeFile(dir, "devices.allow", dev.GetCgroupAllowString()); err != nil {
return nil, err
}
}
@ -295,6 +263,10 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
return &res, nil
}
func writeFile(dir, file, data string) error {
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
}
func (c *systemdCgroup) Cleanup() error {
// systemd cleans up, we don't need to do much