CAP_SYS_RAWIO authorises raw hardware I/O: the ioperm(2) and iopl(2) syscalls for x86 port access, and open/read/write on the raw memory devices /dev/mem, /dev/kmem, and /dev/port where they exist and are not blocked by CONFIG_STRICT_DEVMEM. Because physical memory and I/O ports are a property of the single host machine, not of any namespace, writing to them reaches kernel memory directly and ignores container boundaries.
Confirm the capability and that a usable device node is present:
capsh --print | grep -o cap_sys_rawio
grep CapEff /proc/self/status # bit 17 set
ls -l /dev/mem /dev/port 2>/dev/null # need a raw memory device exposed in the container
Route: write kernel memory via /dev/mem#
With /dev/mem readable and writable, the attacker maps physical pages, scans for a known kernel structure, and patches it. A common objective is to locate the credentials of a process and overwrite its UID/GID fields to 0, or to flip a security flag such as an LSM enforcement toggle.
int fd = open("/dev/mem", O_RDWR);
// mmap a window of physical memory and scan for a signature
void *p = mmap(0, LEN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, phys_off);
// locate task_struct->cred, overwrite uid/gid/euid/egid with 0
Translating a kernel virtual address to a physical offset for /dev/mem requires leaking the kernel base (for example from /proc/kallsyms if readable, or a known offset for the running kernel). Where /dev/mem is restricted to the first 1 MiB by STRICT_DEVMEM, the port and iopl paths remain for hardware that maps control registers into I/O space.
Route: I/O port access#
iopl(3) raises the process I/O privilege level so that in/out instructions on any port succeed, and ioperm enables specific ports. This reaches device controllers directly and, on suitable hardware, DMA-capable peripherals, which can be steered to read or write arbitrary physical memory.
Exploitation notes#
- Modern kernels build with
CONFIG_STRICT_DEVMEMand oftenCONFIG_IO_STRICT_DEVMEM, which confine/dev/memto device ranges and block RAM access; checkzcat /proc/config.gz | grep DEVMEMor/boot/config-$(uname -r). Where RAM is blocked this capability loses most of its escape value. - This route is hardware- and offset-sensitive and is best reserved for cases where cleaner capabilities (CAP_SYS_MODULE, CAP_SYS_ADMIN) are absent but a raw memory device is exposed.
- Exposed raw memory devices usually mean a
--privilegedcontainer or an explicit--device=/dev/mem; see Kernel memory devices.