Skip to content

Dirty Pipe

linux bug

dirty pipe, is linux bug that allows you to modify any file, even if you don't have ownership and/or permission, the way it works is to abuse a flag on the pipe called PIPE_BUF_FLAG_CAN_MERGE, the way it works is basically to trick the kernel to set that flag on all pipe_buffers, and then use the splice syscall to read data from the target file into the pipe (note that you need read permission on the file), what this will do is read a page sized content of the file into the page cache, and link this page directly to the pipe, the problem is that it doesn't initialise the pipe_buffer flags, so when you write to the pipe you are writing directly to the page cache of the file, with no permission checking at all.

here I am going to the details, and explain the exploitation path, in the kernel code, I am using kernel 5.17:

1. Set PIPE_BUF_FLAG_CAN_MERGE in the pipe_buffers

basically you need to fill the pipe, so that the all pipe_buffer gets allocated, and kernel automatically sets the PIPE_BUF_FLAG_CAN_MERGE flag on them. fs/pipe.c@pipe_write:529

then you need to read back the same data that you wrote before, to release the pages associated with pipe_buffers, but this will keep the flag set. fs/pipe.c@pipe_read:324 && fs/pipe.c@anon_pipe_buf_release

2. Link the pipe_buffer to the page cache

now you need to use splice to read from the file into the pipe, in this case linux won't copy data from the page cache into new page for the pipe_bufer (in order to save memory), instead it will link the page (from cache) directly to the pipe_buffer, that's fine except that it doesn't initialise the pipe_buffer flags (PIPE_BUF_FLAG_CAN_MERGE flag still set).

3. Holly Sh**

you can now write to the pipe and it will affect the file direcly, thanks to PIPE_BUF_FLAG_CAN_MERGE flag.

NOTES:

note that the write to the pipe (step 3), should all be within page boundary (offset + write_size <= next_page_boundary).