Dirty Pipe
CVE-2022-0847
Theory
In March 2022, a researcher named Max Kellerman publicly disclosed a Linux Kernel vulnerability (nicknamed "Dirty Pipe" for its similarities to the notorious "Dirty Cow" exploit affecting older versions of the kernel) that allowed attackers to arbitrarily overwrite files on the operating system. Arbitrary file overwrites at the kernel level can be very easily leveraged to escalate privileges on the machine
The vulnerability arises because of how the kernel implements "pipes": the Linux kernel provides a system call called "splice()
", which is effectively a shortcut designed to speed up the process of pushing the contents of a file into a pipe. This optimisation is achieved by moving references to the pages storing the file contents, rather than moving the entirety of the data. In other words, splice()
allows us to point a pipe at a page which is already loaded into memory, containing a section of a file originally opened by a process requesting read-only access.
It's not quite that simple, however; we are still missing one final piece of the puzzle. Usually when you write to a pipe after splicing a file, a new pipe_buffer
is created to avoid overwriting the spliced data. So, how do we force the kernel to allow us to overwrite the relevant page(s)?
This is the real crux of the vulnerability, and it can all be traced back to two commits in the Linux kernel:
A bug was introduced in Linux Kernel v4.9 (2016) which allowed pipes to be created with arbitrary flags. None of the flags available at the time were in any way dangerous, so this wasn't an issue, until...
Linux Kernel v5.8 (2020) added a new flag —
PIPE_BUF_FLAG_CAN_MERGE
. In simple terms, this flag tells the kernel that the page can be updated without forcing a rewrite of the data.
To summarise: we have a flag that allows us to tell the kernel that it's okay to overwrite the data in a page, we have a bug that allows us to specify arbitrary flags for a pipe, and we have a system call that inadvertently allows us to point pipes at page buffers which were opened as read-only. What could possibly go wrong?
Put simply, the exploit first opens a target file with the read-only flag set — in order to do this, we must choose a file that we have permission to read. The exploit then prepares a pipe in a special way, forcing the addition of the PIPE_BUF_FLAG_CAN_MERGE
flag. Next, it uses splice()
to make the pipe point at the desired section of the target file. Finally, it writes whatever arbitrary data that the user has specified into the pipe, overwriting the target page by merit of the PIPE_BUF_FLAG_CAN_MERGE
flag.
Practice
The vulnerability has been patched in Linux kernel versions 5.16.11, 5.15.25 and 5.10.102, and Linux kernel versions newer than 5.8 are affected.
If you are not sure if a target system is vulnerable you may use this bash scripts developed by basharkey.
Resources
Last updated