Dirty Pipe (`CVE-2022-0847`) proved that there is a new way to exploit Linux syscalls to write to files with a read-only privileges.This bug was found by security researcher Max Kellermann.It is a local privilege escalation vulnerability in the Linux kernel that could potentially allow an unprivileged user to do the following:
- Modify/overwrite arbitrary read-only files like /etc/passwd
- Obtain an elevated shell.
## Affected kernel versions
- linux kernel versions 5.8 , 5.9 are affected by this bug.
- So far this vulnerability has been patched in these kernel versions:
In old linux kernel, to copy a file one needs to read the file (`copy from kernel to user`) and then write to a new file (`copy from the user to the kernel`).In kernel v2.2 the `sendfile` syscall was introduced followed by `splice` syscall in v2.5 and `copy_file_range` in v4.5. The purpose of all these syscalls is very simple – allow the user to copy from one file to another without moving through the user-mode, sparing the most expensive step of data transition between files. Reduced operations copy like the one described is called `zero-copy`.
`splice` - This system call moves data between a file descriptor and a pipe, without requiring the data to cross the user-mode/kernel-mode address space boundary, which results in better performance.
`pipe` is a FIFO file, which is used broadly in communication between processes. From the kernel point-of-view, a pipe is an implementation of a file (aka `file struct`).A pipe object (`pipe_inode_info struct`) is implemented as a kind of a ring buffer. It contains internal buffers of the `pipe_buf `struct type.
Starting from kernel v5.8, the responsibility for protecting pages from modification (like in the case of zero-copy) moved to the `pipe_buffer`.
struct page *page;
unsigned int offset , len;
const struct pipe_buf_operations *ops;
unsigned int flags;
unsigned long private;
Starting from kernel v5.8, the responsibility for protecting pages from modification (like in the case of zero-copy) moved to the `pipe_buffer`.a flag was introduced to specify if new data could be written to the buffer or not `PIPE_BUF_FLAG_CAN_MERGE`.From kernel 5.8 this flag became part of the series of flags of the `pipe_buffer` struct.
#### BUG IN SPLICE
The problem is that when the `CAN_MERGE` flag became part of the `pipe_buffer `struct.One of the places that missed the initialization of the flags was the splice implementation, in the `copy_page_to_iter_pipe` function as well as in the `push_pipe` function.This means that when performing splice, which copies a reference to the read file’s page, the page is not protected from modification. The protection of the page would depend on the previous value of the `CAN_MERGE `flag according to the previous data written to the same buffer before.
#### LIMITS OF THIS CVE
- The exploit must write at least 1 byte, so the first byte of each page in a file cannot be modified (including the first byte of the file).
- you need to be able to open file with read permissions.
- The file’s size cannot be modified.