Put an io_uring on it: Exploiting the Linux Kernel

We discussed this vulnerability as part of our weekly podcast on 16 March 2022

We have previously discussed this vulnerability, which provides a primitive to free adjacent memory.

This post covers more on the discovery of the issue and the exploitation techniques.

Heap Spray Primitive - Fairly common technique of using setxattr to to spray the head along with something to block the copy from finishing. The idea being that you can get setxattr to allocate a buffer with size of your choosing, then copies your data into it. Writes it to the extended attribute, and frees the buffer. So its useful just for spaying the heap with specific data when you can block the copy so it doesn’t get free’d too quickly. Blocking the copy was by having the memory be a mmap’d file backed by FUSE. So a userland application could block the return.

Memory Leak Primitive - This one was cool, and kinda turned the setxattr primitive around. Rather than using setxattr to spray the heap with data to fill a buffer that had been free’d instead she free’d the setxattr buffer, so it would get reused by some other object. Unblocked that datacopy, so when the buffer is copied into the extended attribute it will contain the new objects data. Then could be read just using getxattr.

The overall strategy here was to leak a few important structures: an io_tctx_node for a task_struct pointer (common target for Linux privelege escalation), seq_operations an operations structure so it contains function pointers, useful to break kASLR. Then targeted an sk_filter and its prog field with an eBPF program attached. Crafting a malicious eBPF program that would overwrite the effective uid/gid of the previously leaked task_struct.

I’ve of course glossed over some details of the exploit, its a great post to check out though. And at the surface this looks like a fairly education bug if someone wants to play around with some kernel exploitation.