-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
What happened?
Hi,
I’m using Kubernetes with CRI-O as the container runtime interface and passing USB and other devices to containers using the devices field.
On the host, the device files have correct permissions (e.g., 0660) with specific owners and groups. However, inside the container (using crun as the OCI runtime), the uid and gid are preserved, but the device permissions are always 0666.
I opened an issue in crun, and the response was that the OCI config.json passed to the runtime does not include a fileMode field for the devices, so crun falls back to its default (0666). Here is an example of the generated config:
"devices": [
{
"path": "/dev/bus/usb/002/002",
"type": "c",
"major": 189,
"minor": 129,
"uid": 107,
"gid": 107
}
]
As per the OCI runtime spec, the fileMode field is optional, but when not provided, the runtime will use its own default (often 0666). This behavior causes all containers to have full read/write access to the device regardless of host file permissions.
What did you expect to happen?
From what I understand, the CRI implementation (in this case CRI-O) should be responsible for populating the fileMode in the OCI spec if it wants to preserve the host permissions.
Could CRI-O be updated to propagate the device file permissions (mode) into the OCI config? Otherwise, this could lead to unexpected security and access issues inside containers.
How can we reproduce it (as minimally and precisely as possible)?
On the host node, set a device file (e.g. /dev/bus/usb/002/002) with specific permissions:
sudo chown 107:107 /dev/bus/usb/002/002
sudo chmod 0660 /dev/bus/usb/002/002
Deploy a pod that requests the device using the devices field in the PodSpec (via Kubernetes Device Plugin or static configuration if supported).
Inside the running container, check the device file permissions:
ls -l /dev/bus/usb/002/002
Anything else we need to know?
No response
CRI-O and Kubernetes version
$ crio --version
[vagrant@node02 ~]$ crio --version
crio version 1.33.2
GitCommit: 0da1b7c95fa3ec7cb83306a39724bf39e35033f4
GitCommitDate: 2025-07-01T08:46:54Z
GitTreeState: dirty
BuildDate: 1970-01-01T00:00:00Z
GoVersion: go1.24.2
Compiler: gc
Platform: linux/amd64
Linkmode: static
BuildTags:
static
netgo
osusergo
exclude_graphdriver_btrfs
seccomp
apparmor
selinux
LDFlags: unknown
SeccompEnabled: true
AppArmorEnabled: false
[vagrant@node02 ~]$
$ kubectl version --output=json
selecting docker as container runtime
Client Version: v1.33.2
Kustomize Version: v5.6.0
Server Version: v1.33.2OS version
# On Linux:
$ cat /etc/os-release
# paste output here
$ uname -a
# paste output here