diff options
-rw-r--r-- | cmd/podman/common/specgen.go | 63 | ||||
-rw-r--r-- | pkg/specgen/generate/oci.go | 4 | ||||
-rw-r--r-- | pkg/specgen/specgen.go | 3 | ||||
-rw-r--r-- | test/system/030-run.bats | 17 |
4 files changed, 87 insertions, 0 deletions
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 2f45e559d..24b45e479 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -566,6 +566,14 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.Devices = append(s.Devices, specs.LinuxDevice{Path: dev}) } + for _, rule := range c.DeviceCGroupRule { + dev, err := parseLinuxResourcesDeviceAccess(rule) + if err != nil { + return err + } + s.DeviceCGroupRule = append(s.DeviceCGroupRule, dev) + } + s.Init = c.Init s.InitPath = c.InitPath s.Stdin = c.Interactive @@ -885,3 +893,58 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) } return mount, envs, nil } + +var cgroupDeviceType = map[string]bool{ + "a": true, // all + "b": true, // block device + "c": true, // character device +} + +var cgroupDeviceAccess = map[string]bool{ + "r": true, //read + "w": true, //write + "m": true, //mknod +} + +// parseLinuxResourcesDeviceAccess parses the raw string passed with the --device-access-add flag +func parseLinuxResourcesDeviceAccess(device string) (specs.LinuxDeviceCgroup, error) { + var devType, access string + var major, minor *int64 + + value := strings.Split(device, " ") + if len(value) != 3 { + return specs.LinuxDeviceCgroup{}, fmt.Errorf("invalid device cgroup rule requires type, major:Minor, and access rules: %q", device) + } + + devType = value[0] + if !cgroupDeviceType[devType] { + return specs.LinuxDeviceCgroup{}, fmt.Errorf("invalid device type in device-access-add: %s", devType) + } + + number := strings.SplitN(value[1], ":", 2) + i, err := strconv.ParseInt(number[0], 10, 64) + if err != nil { + return specs.LinuxDeviceCgroup{}, err + } + major = &i + if len(number) == 2 && number[1] != "*" { + i, err := strconv.ParseInt(number[1], 10, 64) + if err != nil { + return specs.LinuxDeviceCgroup{}, err + } + minor = &i + } + access = value[2] + for _, c := range strings.Split(access, "") { + if !cgroupDeviceAccess[c] { + return specs.LinuxDeviceCgroup{}, fmt.Errorf("invalid device access in device-access-add: %s", c) + } + } + return specs.LinuxDeviceCgroup{ + Allow: true, + Type: devType, + Major: major, + Minor: minor, + Access: access, + }, nil +} diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index bf8d44ed6..6e310d8a6 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -321,6 +321,10 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt } } + for _, dev := range s.DeviceCGroupRule { + g.AddLinuxResourcesDevice(true, dev.Type, dev.Major, dev.Minor, dev.Access) + } + BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g) for name, val := range s.Env { diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index c5cc726d7..7eec48a55 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -239,6 +239,9 @@ type ContainerStorageConfig struct { // Devices are devices that will be added to the container. // Optional. Devices []spec.LinuxDevice `json:"devices,omitempty"` + // DeviceCGroupRule are device cgroup rules that allow containers + // to use additional types of devices. + DeviceCGroupRule []spec.LinuxDeviceCgroup `json:"device_cgroup_rule,omitempty"` // IpcNS is the container's IPC namespace. // Default is private. // Conflicts with ShmSize if not set to private. diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 32fc85c4e..3d9d834b3 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -706,4 +706,21 @@ EOF run_podman rmi nomtab } +@test "podman run --device-cgroup-rule tests" { + skip_if_rootless "cannot add devices in rootless mode" + + run_podman run --device-cgroup-rule="b 7:* rmw" --rm $IMAGE + run_podman run --device-cgroup-rule="c 7:* rmw" --rm $IMAGE + run_podman run --device-cgroup-rule="a 7:1 rmw" --rm $IMAGE + run_podman run --device-cgroup-rule="a 7 rmw" --rm $IMAGE + run_podman 125 run --device-cgroup-rule="b 7:* rmX" --rm $IMAGE + is "$output" "Error: invalid device access in device-access-add: X" + run_podman 125 run --device-cgroup-rule="b 7:2" --rm $IMAGE + is "$output" 'Error: invalid device cgroup rule requires type, major:Minor, and access rules: "b 7:2"' + run_podman 125 run --device-cgroup-rule="x 7:* rmw" --rm $IMAGE + is "$output" "Error: invalid device type in device-access-add:" + run_podman 125 run --device-cgroup-rule="a a:* rmw" --rm $IMAGE + is "$output" "Error: strconv.ParseInt: parsing \"a\": invalid syntax" +} + # vim: filetype=sh |