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