Vulnerability Analysis

Dirty Pipe (CVE-2022-0847): A Deep Dive into the Linux Kernel Vulnerability

Dirty Pipe allowed any local user to overwrite data in read-only files, including SUID binaries, leading to trivial root escalation. The bug was elegant, dangerous, and surprisingly recent.

Nayan Dey
Engineering Lead
5 min read

On March 7, 2022, security researcher Max Kellermann published the details of CVE-2022-0847, a vulnerability he named "Dirty Pipe." The name was a deliberate callback to Dirty COW (CVE-2016-5195), another Linux kernel vulnerability that allowed unauthorized file modifications. But while Dirty COW relied on a complex race condition, Dirty Pipe was simpler, more reliable, and arguably more dangerous.

How Max Found It

Kellermann did not discover Dirty Pipe through deliberate security research. He found it while investigating corrupted log files at a customer site. Gzip-compressed access logs were occasionally producing CRC errors when decompressed. After months of debugging, he traced the corruption to the Linux kernel's pipe handling code.

The bug was introduced in Linux kernel 5.8 (released August 2020) through commit f6dd975583bd which refactored the pipe buffer handling. The change inadvertently allowed the PIPE_BUF_FLAG_CAN_MERGE flag to persist on pipe buffers that referenced page cache pages, enabling writes to those pages through the pipe — even if the underlying file was read-only.

The Technical Details

To understand Dirty Pipe, you need to understand how Linux pipes and the page cache interact.

When you read a file in Linux, the kernel loads its contents into the page cache — a shared, in-memory copy of file data. Multiple processes reading the same file share the same page cache pages. The page cache is the single source of truth for file contents; writing to a page cache page modifies the file for everyone.

Linux pipes use a ring buffer of pipe_buffer structures, each of which can reference a page of memory. When you splice() data from a file into a pipe, the kernel does not copy the data — it creates a pipe_buffer that directly references the file's page cache page. This is an optimization to avoid unnecessary memory copies.

The vulnerability was in how the PIPE_BUF_FLAG_CAN_MERGE flag was handled:

  1. Create a pipe
  2. Fill the pipe with arbitrary data (this creates pipe buffers with the CAN_MERGE flag set)
  3. Drain the pipe (this empties the pipe but the flag state is retained)
  4. Use splice() to read from a target file into the pipe (this creates a pipe buffer pointing to the target file's page cache page — and the CAN_MERGE flag from step 2 is inherited)
  5. Write new data to the pipe — because CAN_MERGE is set, the kernel writes your data directly into the page cache page, overwriting the file's contents
// Simplified exploit concept
int fd = open("/etc/passwd", O_RDONLY);
int pipefd[2];
pipe(pipefd);

// Step 1-3: Prepare pipe with CAN_MERGE flag
char buf[PAGE_SIZE];
write(pipefd[1], buf, PAGE_SIZE);
read(pipefd[0], buf, PAGE_SIZE);

// Step 4: Splice target file into pipe
loff_t offset = target_offset;
splice(fd, &offset, pipefd[1], NULL, 1, 0);

// Step 5: Write overwrites the page cache!
write(pipefd[1], "root::0:0:", 10);
// /etc/passwd now has a passwordless root entry

The beauty (from an attacker's perspective) of this exploit is its reliability. There is no race condition, no heap spraying, no address space layout randomization to defeat. It works deterministically, every time.

Exploitation Scenarios

Instant Root Access

The simplest exploitation path: overwrite /etc/passwd to add a passwordless root account, or overwrite a SUID binary (like su) to inject a backdoor. Max Kellermann's proof-of-concept demonstrated both approaches.

Container Escapes

In containerized environments, Dirty Pipe could be used to overwrite files in the host's page cache if the container shared file mounts with the host. Container runtimes that used read-only bind mounts for security were undermined, because Dirty Pipe bypassed file permission checks entirely.

Data Manipulation

Beyond privilege escalation, Dirty Pipe enabled silent modification of any file readable by the attacker. This could be used to:

  • Modify application binaries to inject backdoors
  • Alter log files to cover tracks
  • Tamper with configuration files to weaken security settings
  • Modify database files to corrupt or manipulate data

Affected Systems

  • Linux kernel 5.8 through 5.16.10 (fixed in 5.16.11, 5.15.25, and 5.10.102)
  • Android 12 and some Android 11 devices running kernel 5.10
  • All major Linux distributions shipping affected kernel versions
  • Container hosts running affected kernels (containers inherit the host kernel)
  • Cloud instances from AWS, GCP, Azure running affected AMIs/images

The Fix

The fix was a one-line change: ensure that the PIPE_BUF_FLAG_CAN_MERGE flag is cleared when a new pipe buffer is initialized from a splice() operation. The patch was merged into the stable kernel trees within days of responsible disclosure.

// The fix: clear flags when initializing from splice
buf->flags = 0;  // Previously, flags were not reset

Comparison with Dirty COW

| Feature | Dirty COW (2016) | Dirty Pipe (2022) | |---------|-----------------|-------------------| | CVE | CVE-2016-5195 | CVE-2022-0847 | | Mechanism | Race condition in COW | Missing flag cleanup in pipes | | Reliability | Probabilistic | Deterministic | | Kernel versions | 2.6.22+ (9 years) | 5.8+ (1.5 years) | | Exploitation | Complex, may crash | Simple, stable | | Scope | Write to any file | Write to any readable file |

Lessons Learned

Kernel security is supply chain security. Every application, container, and service running on Linux inherits the kernel's vulnerabilities. Your application might be perfectly secure, but if the kernel underneath it has a privilege escalation bug, an attacker with any foothold can escalate to root.

Patching speed matters. Proof-of-concept exploits for Dirty Pipe were published within hours of the disclosure. Organizations with slow patching cycles were exposed for days or weeks.

Monitor for kernel vulnerabilities. Add kernel version tracking to your vulnerability management program. Many organizations meticulously track application-layer CVEs but ignore kernel-level issues.

How Safeguard.sh Helps

Safeguard.sh tracks kernel-level vulnerabilities alongside application dependencies, giving you a complete view of your exposure across the full stack. When vulnerabilities like Dirty Pipe are disclosed, our platform identifies affected systems across your infrastructure and helps prioritize patching based on actual exploitation risk. Our policy engine can enforce minimum kernel version requirements before workloads are deployed.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.