freenode
Kernel & Low-Level

Kernel proposal blocks proc and sysfs files as storage backends

Loop, NVMe, the SCSI target and similar paths would refuse pseudo filesystem files after a capability bypass let unprivileged tasks trigger kernel actions.

Linux kernel developer Christian Brauner has proposed refusing procfs, sysfs and other pseudo filesystem files as backing storage for loop devices and several similar kernel interfaces, after showing that those files can be used to skip capability checks.

Loop will attach almost any regular file that implements the usual read and write iterators, including kernel interfaces that were never meant to be disks. Brauner wrote that /proc/kcore attaches as a read-only loop device the size of the kernel virtual address space, 64 PiB with five-level paging, and that a sysfs attribute becomes a 4096-byte writable loop device. Writing a block through the loop device for the transparent hugepage control file changes that setting.

The serious problem is credentials. Loop performs those reads and writes from a kernel worker that runs with kernel credentials. Many sysfs methods call capable() against the caller at read or write time. Opening a loop device needs no capabilities, only access to the device nodes, so those checks run against the worker instead of the task that set the device up.

On a current release candidate, Brauner showed a root user with an empty capability set who could not kill another user's process and could not write the memory hard-offline interface directly. Putting that write-only sysfs file behind a loop device and writing a page address through it made the kernel report a memory failure and kill the victim. The same pattern reaches radio kill switches (which want CAP_NET_ADMIN), the reboot mode file (CAP_SYS_BOOT), md and SCSI disk attributes (CAP_SYS_ADMIN), and DMI firmware entries. An unprivileged container handed a loop device could change a network device's GRO flush timeout that its own namespace is not allowed to touch. Stacking overlayfs over sysfs does not close the hole: reads are still served by the pseudo filesystem underneath.

The patches add one helper that accepts only regular files, and block devices where a caller asks for them, refuses pseudo filesystems (looking through overlayfs), and checks that the file is open for the intended access. Loop, zloop, the NVMe target file backend, the SCSI target file backend and its protection file, FUSE passthrough, the USB mass-storage gadget, file-backed EROFS, and process accounting would all use it. Accounting already rejected procfs and sysfs but missed other pseudo filesystems such as cgroup2. Brauner noted that path is not abusable the way loop is, because records are written with the credentials of whoever turned accounting on.

The change is still a request for comments. Tests cover the refused cases and check that ordinary files, memfds and block devices still work.