runtime: allow loopback devices for sandbox cgroup only

When sandbox_cgroup_only is enabled, the kata shim threads inherit
the sandbox device cgroup. For container rootfs whose mount source
is a regular file backed by a loop device (notably the blockfile
snapshotter), containerd's mount package opens /dev/loop-control to
allocate a free /dev/loopN and then opens that block node to attach
the backing file. Neither device is on the sandbox cgroup allowlist,
so both opens fail with EPERM.

This change adds /dev/loop-control (char 10:237) and the /dev/loopN
block nodes (block major 7, any minor) to the sandbox device cgroup
allowlist when sandbox_cgroup_only is true, mirroring the existing
treatment of /dev/null, /dev/urandom and /dev/ptmx. The additions
are gated on SandboxCgroupOnly because that is the only mode in
which the shim itself is constrained by this cgroup.

Assisted-By: Claude 4.7
Signed-off-by: PiotrProkop <pprokop@nvidia.com>
This commit is contained in:
PiotrProkop
2026-05-11 11:03:53 +02:00
parent 2b329074f1
commit 5cd187619e

View File

@@ -888,6 +888,8 @@ func (s *Sandbox) createResourceController() error {
nullDeviceExist := false
urandomDeviceExist := false
ptmxDeviceExist := false
loopControlDeviceExist := false
loopBlockDeviceExist := false
for _, device := range resources.Devices {
if device.Type == "c" && device.Major == intptr(1) && device.Minor == intptr(3) {
nullDeviceExist = true
@@ -900,6 +902,14 @@ func (s *Sandbox) createResourceController() error {
if device.Type == "c" && device.Major == intptr(5) && device.Minor == intptr(2) {
ptmxDeviceExist = true
}
if device.Type == "c" && device.Major == intptr(10) && device.Minor == intptr(237) {
loopControlDeviceExist = true
}
if device.Type == "b" && device.Major == intptr(7) && device.Minor == nil {
loopBlockDeviceExist = true
}
}
if !nullDeviceExist {
@@ -927,6 +937,27 @@ func (s *Sandbox) createResourceController() error {
}
// When sandbox_cgroup_only is enabled the shim threads inherit
// the sandbox device cgroup, so any rootfs whose mount source is
// a regular file backed by a loop device (e.g. the blockfile
// snapshotter) needs /dev/loop-control and the /dev/loopN block
// nodes allowlisted, otherwise containerd's loop setup fails
// with EPERM on open("/dev/loop-control").
if s.config.SandboxCgroupOnly {
if !loopControlDeviceExist {
// "/dev/loop-control"
resources.Devices = append(resources.Devices, specs.LinuxDeviceCgroup{
Type: "c", Major: intptr(10), Minor: intptr(237), Access: rwm, Allow: true,
})
}
if !loopBlockDeviceExist {
// "/dev/loop*" (block major 7, any minor)
resources.Devices = append(resources.Devices, specs.LinuxDeviceCgroup{
Type: "b", Major: intptr(7), Access: rwm, Allow: true,
})
}
}
if spec.Linux.Resources.CPU != nil {
resources.CPU = &specs.LinuxCPU{
Cpus: spec.Linux.Resources.CPU.Cpus,