On March 7, 2022, security researcher Max Kellerman disclosed Dirty Pipe, a Linux local privilege escalation vulnerability with a CVSS score of 7.8 (HIGH), along with a proof of concept demonstrating how to exploit it. The vulnerability affects the Linux Kernel and allows users with low privileges to overwrite read-only files on kernels version 5.8 and later.
Background
Before diving into the vulnerability itself, here are a few key concepts worth understanding:
Page Cache: Every time Linux reads a file, it keeps a copy of that file's contents in RAM. This is called the page cache. It is faster to read from RAM than from disk, so the kernel serves file reads from here. If something modifies this RAM copy without saving to disk, that page becomes "dirty", hence the name Dirty Pipe.
Pipe: A simple one-way data tube the kernel uses to pass data between two running programs. Program A writes into one end, Program B reads from the other.
Pipe Flag (PIPE_BUF_FLAG_CAN_MERGE): A small label the kernel attaches to data sitting inside a pipe. When this flag is set, it tells the kernel: "new data coming into this pipe can be written directly into whatever memory this pipe entry is already pointing at." This is normally fine, but becomes dangerous when the pipe is pointing at a protected file's memory.
splice(): A kernel command that moves data from a file directly into a pipe without going through userspace. Instead of copying data out to the program and back in, it just points the pipe directly at the file's page cache memory, a performance shortcut.
Where Does the Vulnerability Come From?
Every file on Linux has permissions. When you try to write to a file normally, the kernel checks those permissions first - if you don't have write access, it blocks you. That permission check happens in a layer called the VFS (Virtual File System), which sits between your program and the actual file data.
The bug in Dirty Pipe is that there is a second path into file memory that skips that permission check entirely.
Here is how it happens:
When you use splice() to pull data from a file into a pipe, the kernel does not copy the file data - it just makes the pipe point directly at the file's page cache memory (the live copy of the file in RAM). That is fine on its own. The problem is what happens next.
The kernel has a performance feature: if a pipe entry has the PIPE_BUF_FLAG_CAN_MERGE flag set, any new data written into the pipe gets merged directly into whatever memory that pipe entry is already pointing at - no extra copy, no permission check.
The bug is that the kernel forgot to clear that flag after splice() ran. So the pipe is now pointing at the file's protected memory, but the CAN_MERGE flag is still set. When you then call write() into the pipe, the kernel merges your data straight into the file's page cache, because it never checked whether it should.
The result: you modified a file you had no write permission to, and the kernel never stopped you - because you came through the pipe path, not the normal file write path where permissions are enforced.
Affected Versions
The vulnerability affects Linux kernel versions:
- Affected: 5.8 through 5.16.10
- Fixed in:
- 5.16.11
- 5.15.25
- 5.10.102
To check your kernel version:
uname -srmExploitation Overview
The exploit works in three stages regardless of which method is used.
Stage 1 - Prime the Pipe: Fill the pipe buffer completely with any data, then drain it. The pipe is now empty, but the PIPE_BUF_FLAG_CAN_MERGE flag remains set on the stale entries. The kernel forgot to clear it. This is the setup step.
Stage 2 - Splice the Target: Use splice() to pull one byte from a readable target file (e.g. /etc/passwd) into the pipe. The pipe now has an entry pointing directly at that file's live memory in RAM. Because of Stage 1, the CAN_MERGE flag is still set on that entry.
Stage 3 - Write and Overwrite: Call write() into the pipe. The kernel sees CAN_MERGE is set, skips the permission check, and writes your data directly into the file's memory. The file is now modified.
Key constraints to keep in mind:
- You only need read access to the target file - write permission is not required
- Changes exist only in RAM; a reboot restores the original file from disk. An attacker can persist changes by copying the modified in-memory content back to disk (e.g., via cp --no-preserve) before rebooting
- No network access, no special configuration, and no user interaction is needed - this is a local privilege escalation exploit
- In real-world attacks this is commonly chained after an initial remote foothold (e.g. web shell or RCE) to escalate to root
Exploitation
Dirty Pipe has been exploited in two well-known ways by the security community. Both methods follow the same underlying kernel trick - they differ only in what file they target and what outcome they aim for.
Method 1: Overwriting /etc/passwd
The /etc/passwd file stores all user accounts on a Linux system. Each line represents one user, with fields separated by colons:
username:password_hash:user_ID:group_ID:user_info:home_directory:shell
root:x:0:0:root:/root:/bin/bashThe second field is normally just x, which tells Linux that the actual password hash is stored in /etc/shadow. However, Linux still supports placing a password hash directly in /etc/passwd, a legacy feature retained from the era before shadow passwords were widely adopted. If a hash is placed there, Linux uses it for authentication instead of /etc/shadow.
The exploit targets /etc/passwd specifically because it is world-readable, meaning any unprivileged user can open it - which is the one permission Dirty Pipe requires. /etc/shadow cannot be used because it is not readable by normal users.
The exploit opens /etc/passwd as read-only, seeks 4 bytes in (landing just after root), and uses the Dirty Pipe technique to overwrite the x placeholder with an attacker-controlled password hash. This effectively sets a known root password without needing write access to the file. The attacker then switches to root using su with the password they injected.
A well-known public PoC for this method is available at https://github.com/Arinerron/CVE-2022-0847-DirtyPipe-Exploit.
Method 2: SUID Binary Hijacking
SUID (Set User ID) binaries are executables that run with the permissions of their owner rather than the user who launches them. Binaries owned by root with the SUID bit set effectively run as root, regardless of who executes them.
This method works conceptually in four stages:
- Backup the target SUID binary before touching it
- Overwrite the SUID binary using Dirty Pipe with a small piece of code that copies /bin/bash to /tmp/sh and marks it with the SUID bit
- Execute the overwritten binary, which drops the SUID shell into /tmp/sh and simultaneously restores the original binary from the backup
- Use /tmp/sh to obtain a root shell, then delete it when done
This method is notable because it does not touch /etc/passwd or /etc/shadow at all, making it harder to detect through credential-monitoring alone.
Impact
Successful exploitation of Dirty Pipe allows an attacker to:
- Overwrite any file readable by the attacker, regardless of write permissions
- Inject arbitrary content into sensitive files such as /etc/passwd or /etc/shadow
- Hijack SUID binaries to execute code as root
- Achieve full local privilege escalation from any low-privileged user account
Important: Changes made via this exploit live in the page cache only and will be lost on reboot unless the attacker takes additional steps (such as copying the modified content back to disk) to establish persistence.
Detection
Run the following to check if your system is in the vulnerable kernel range:
uname -srmAny kernel version >= 5.8 and below the patched versions (5.16.11, 5.15.25, 5.10.102) is affected.
Mitigation
The fix is straightforward: update the kernel to a patched version.
- 5.16.11 or later
- 5.15.25 or later
- 5.10.102 or later
Use your distribution's package manager to upgrade:
# Debian/Ubuntu
sudo apt update && sudo apt upgrade
# RHEL/CentOS
sudo yum update kernelIf an immediate kernel update is not possible:
- Restrict untrusted interactive accounts
- Enforce strict SELinux or AppArmor policies on sensitive file paths
- Use file integrity monitoring to detect suspicious modifications
Final Thoughts
Dirty Pipe is a reminder that even mature, well-audited kernel subsystems can carry subtle bugs with severe consequences. A single flag that was never cleared on a pipe buffer created a direct path from an unprivileged user to full root access, bypassing decades of VFS permission enforcement entirely.
What makes it particularly dangerous is the low bar for exploitation: any local user with read access to a target file and a vulnerable kernel is a potential attacker. In practice, it is frequently used as the privilege escalation step in a multi-stage attack chain, after an attacker has already gained a low-privileged foothold via a remote vulnerability such as a web application exploit or RCE.
If you are running a kernel in the affected range, patching is not optional.
References
- https://nvd.nist.gov/vuln/detail/CVE-2022-0847
- https://dirtypipe.cm4all.com/ (Max Kellerman's original writeup and PoC)
- https://github.com/febinrev/dirtypipez-exploit (febinrev's dirtypipez PoC)



.png)
.png)





