Description: I noticed that crun (v1.28) behaves differently from the latest versions of runc (v1.4.2) and youki (v0.6.0) when parsing mount options that contain a null byte (\u0000).
When mounting filesystems such as cgroup, mqueue, sysfs, or when mounting tmpfs to shm, appending a null byte to a mount option (e.g., nosuid\u0000) causes crun to successfully create the container, whereas runc and youki error out.
Specification and Security Basis: While JSON allows \u0000 in strings, Linux mount(2) treats null bytes as C-string terminators. It appears that crun silently truncates the mount option at the null byte and proceeds with the operation. This behavior might be inconsistent with expected configuration fidelity and poses a potential security risk: if additional security-critical mount options follow the null byte, they might be silently discarded without alerting the user.
Steps to reproduce the issue:
- Use the following minimal
config.json snippet where \u0000 is injected into the mount options:
config.json snippet
"mounts": [
{
"destination": "/proc",
"type": "proc",
"source": "proc"
},
{
"destination": "/dev",
"type": "tmpfs",
"source": "tmpfs",
"options": [
"nosuid",
"strictatime",
"mode=755",
"size=65536k"
]
},
{
"destination": "/dev/pts",
"type": "devpts",
"source": "devpts",
"options": [
"nosuid",
"noexec",
"newinstance",
"ptmxmode=0666",
"mode=0620",
"gid=5"
]
},
{
"destination": "/dev/shm",
"type": "tmpfs",
"source": "shm",
"options": [
"nosuid",
"noexec",
"nodev",
"mode=1777",
"size=65536k"
]
},
{
"destination": "/dev/mqueue",
"type": "mqueue",
"source": "mqueue",
"options": [
"nosuid",
"noexec",
"nodev"
]
},
{
"destination": "/sys",
"type": "sysfs",
"source": "sysfs",
"options": [
"nosuid",
"noexec",
"nodev",
"ro"
]
},
{
"destination": "/sys/fs/cgroup",
"type": "cgroup2",
"source": "cgroup2",
"options": [
"nosuid\u0000",
"noexec",
"nodev",
"relatime",
"ro",
"nsdelegate"
]
}
]
- Run the container creation command:
sudo crun create -b . mycontainer
Describe the results you received and expected:
- Expected behavior:
crun should explicitly reject mount options containing null bytes and error out immediately, preventing silent configuration truncation (similar to how runc and youki handle it).
- Actual behavior:
crun silently ignores the null byte (and anything following it), and successfully creates the container.
Logs and Outputs:
Output from crun:
Returns exit code 0 and successfully creates the container
For comparison, output from runc and youki (which behave correctly by throwing an error indicating the invalid argument):
runc output:
ERRO[0000] runc create failed: unable to start container process: error during container init: error mounting "cgroup2" to rootfs at "/sys/fs/cgroup": mount src=cgroup2, dst=/sys/fs/cgroup, dstFd=/proc/thread-self/fd/11, flags=MS_RDONLY|MS_NODEV|MS_NOEXEC|MS_RELATIME, data=nosuid,nsdelegate: invalid argument
youki output:
ERROR libcontainer::rootfs::mount: failed to mount Mount { destination: "/sys/fs/cgroup", typ: Some("cgroup2"), source: Some("cgroup2"), options: Some(["nosuid\0", "noexec", "nodev", "relatime", "ro", "nsdelegate"]), uid_mappings: None, gid_mappings: None }: syscall
ERROR libcontainer::process::init::process: failed to prepare rootfs err=Mount(Syscall(Nix(EINVAL)))
ERROR libcontainer::process::container_intermediate_process: failed to initialize container process: failed to prepare rootfs
Description: I noticed that
crun(v1.28) behaves differently from the latest versions ofrunc(v1.4.2) andyouki(v0.6.0) when parsing mount options that contain a null byte (\u0000).When mounting filesystems such as
cgroup,mqueue,sysfs, or when mountingtmpfstoshm, appending a null byte to a mount option (e.g.,nosuid\u0000) causescrunto successfully create the container, whereasruncandyoukierror out.Specification and Security Basis: While JSON allows
\u0000in strings, Linuxmount(2)treats null bytes as C-string terminators. It appears thatcrunsilently truncates the mount option at the null byte and proceeds with the operation. This behavior might be inconsistent with expected configuration fidelity and poses a potential security risk: if additional security-critical mount options follow the null byte, they might be silently discarded without alerting the user.Steps to reproduce the issue:
config.jsonsnippet where\u0000is injected into the mount options:config.json snippet
sudo crun create -b . mycontainerDescribe the results you received and expected:
crunshould explicitly reject mount options containing null bytes and error out immediately, preventing silent configuration truncation (similar to howruncandyoukihandle it).crunsilently ignores the null byte (and anything following it), and successfully creates the container.Logs and Outputs:
Output from
crun:For comparison, output from
runcandyouki(which behave correctly by throwing an error indicating the invalid argument):runcoutput:youkioutput: