# CVE-2022-0847(Dirty-Pipe-vulnerability)

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:  

     - 5.16.11
    - 5.15.25
    - 5.10.102

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 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.


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.


- 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.