Safeguard
Vulnerability Analysis

Dirty COW Linux kernel privilege escalation (CVE-2016-5195)

Dirty COW (CVE-2016-5195) let local attackers hijack a kernel race condition for root. Nine years old, still found in fleets — here's how to find and fix it.

Nayan Dey
Security Researcher
8 min read

Dirty COW (CVE-2016-5195) is a privilege escalation vulnerability in the Linux kernel's memory management subsystem that allows a local, unprivileged user to gain write access to read-only memory mappings — and from there, root. The flaw is a race condition in how the kernel handles the copy-on-write (COW) breakage of private read-only memory mappings, and it sat undiscovered in the kernel for nine years before being found actively exploited in the wild in 2016. Because the bug lives in a code path exercised by nearly every distribution, patch level, and container runtime built on a vulnerable kernel, Dirty COW became one of the most consequential local privilege escalation (LPE) bugs in Linux history — and it remains a staple in post-exploitation toolkits, rooting frameworks, and container-escape research to this day.

Impact

Dirty COW does not grant remote code execution on its own. An attacker needs some existing foothold — a low-privileged shell, a web shell, a compromised container, or a malicious app on a device — to trigger the race condition. Once triggered, however, the impact is severe: the attacker can overwrite files they should only be able to read, including SUID binaries and files owned by root, and use that write access to plant malicious code that executes with elevated privileges. In practice this means full root compromise of the host.

This made Dirty COW a favorite second stage for:

  • Web shell operators escalating from a compromised web application user to root on the underlying server.
  • Android rooting tools (e.g., variants nicknamed "Cowroot") that used the bug to root devices without unlocking bootloaders.
  • Malware droppers, including the ZNIU mobile malware family, which bundled a Dirty COW variant to gain persistence on Android devices.
  • Container breakout research, since a vulnerable host kernel underneath an unpatched container runtime could allow escalation from inside a container to the host, depending on isolation configuration.

Because the vulnerable code path (get_user_pages() / GUP fast path handling of MADV_DONTNEED races against COW page faults) is deep in core memory management, exploitation is largely OS- and architecture-agnostic — working PoCs surfaced for x86, x86_64, and ARM within days of disclosure.

Affected Versions and Components

The vulnerable code was introduced into the Linux kernel in version 2.6.22, released in 2007, and remained present until fixes landed in October 2016 — meaning virtually every kernel shipped for nearly a decade was theoretically exploitable.

Fixed upstream kernel versions:

  • Linux 4.8.3
  • Linux 4.7.9
  • Linux 4.4.26
  • Corresponding backports across the stable and long-term-support (LTS) branches

Because of the kernel's long shelf life in enterprise Linux, the real-world affected surface was enormous and included:

  • RHEL / CentOS 5, 6, and 7 (all actively supported branches at the time)
  • Debian (stable, oldstable, and testing branches)
  • Ubuntu (all LTS releases then supported)
  • SUSE Linux Enterprise Server
  • Android, across essentially every device shipping a kernel derived from the affected lineage — Google shipped fixes in its November 2016 security bulletin, but OEM fragmentation meant many devices stayed exposed far longer
  • Any container host (Docker, LXC, etc.) running an unpatched kernel, since containers share the host kernel

If you're running a kernel that predates the October/November 2016 vendor advisories for your distribution and haven't backported the fix, you should treat the system as vulnerable regardless of how "old" the CVE is — legacy appliances, embedded Linux devices, and long-lived VM images are exactly where Dirty COW still turns up in modern audits.

Severity, Exploitability, and Real-World Risk

  • CVSS v3 Base Score: 7.8 (High)AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H. The vector reflects local attack vector and low complexity, but high impact once triggered: full confidentiality, integrity, and availability compromise of the host.
  • EPSS: Dirty COW's exploit prediction score sits at the high end of the distribution. Multiple mature, public, weaponized exploits (including the widely circulated dirtyc0w.c PoC and the branded "dirtycow.ninja" release) mean exploitation requires minimal skill, and the probability of observed exploitation activity is correspondingly high.
  • CISA Known Exploited Vulnerabilities (KEV) Catalog: CVE-2016-5195 is listed in CISA's KEV catalog, reflecting confirmed active exploitation in the wild — federal civilian agencies under Binding Operational Directive 22-01 are required to remediate KEV-listed vulnerabilities on an accelerated timeline, and it's a strong signal for any organization prioritizing patch backlogs.

The combination of a "High" CVSS score, mature public exploitation tooling, and KEV inclusion puts Dirty COW squarely in the category of vulnerabilities that should never survive in a production fleet's patch backlog — the barrier to exploitation is low, the impact is total host compromise, and the fix has been available since 2016.

Timeline

  • 2007 — The vulnerable copy-on-write handling logic is merged into Linux kernel 2.6.22.
  • September–October 2016 — Security researcher Phil Oester discovers the bug being actively exploited against one of his systems and captures the exploit traffic, prompting formal analysis.
  • October 13, 2016 — Linus Torvalds authors the upstream kernel patch, noting he had attempted to fix a related issue roughly a decade earlier but the fix was incomplete.
  • October 18–21, 2016 — CVE-2016-5195 is assigned; Red Hat coordinates disclosure; the "Dirty COW" branding and a dedicated public information site accelerate awareness across the security community.
  • October–November 2016 — Major distributions (Red Hat, Debian, Ubuntu, SUSE) ship emergency kernel updates; Google includes the fix in its November 2016 Android Security Bulletin.
  • Late 2016–2017 — Public, working exploits proliferate rapidly; Android rooting tools and the ZNIU malware family adopt Dirty COW variants for privilege escalation.
  • 2022 — CVE-2016-5195 is added to CISA's Known Exploited Vulnerabilities catalog, formalizing what the security community already knew: this bug is exploited in practice, not just in theory.

Remediation

The fix for Dirty COW is a kernel patch — there is no reliable configuration-only mitigation, so remediation is fundamentally a patch management problem:

  1. Identify affected hosts. Inventory running kernel versions across servers, VMs, containers hosts, and embedded/IoT Linux devices with uname -r, and cross-reference against your distribution's fixed-version advisory (RHSA-2016:2098, USN-3105-1, DSA-3696-1, etc.).
  2. Patch the kernel. Update to a fixed upstream version (4.8.3, 4.7.9, 4.4.26, or later) or your distribution's backported equivalent:
    • RHEL/CentOS: yum update kernel and reboot into the new kernel.
    • Debian/Ubuntu: apt update && apt upgrade linux-image-$(uname -r) and reboot.
    • SUSE: apply the relevant SUSE Security Update and reboot.
  3. Reboot to load the patched kernel. A kernel update without a reboot (or live patch) leaves the vulnerable kernel running in memory. If reboot windows are constrained, use a live-patching solution (kpatch, Ksplice, KernelCare) to apply the fix without downtime.
  4. Patch Android/embedded fleets separately. Apply the November 2016 (or later) security patch level; for OEM devices that never received a fix, treat them as end-of-life risk and plan replacement or network isolation.
  5. Audit container hosts. Containers inherit the host kernel's vulnerabilities. Patch the underlying host, not just container images, and confirm your container runtime doesn't grant capabilities (e.g., unnecessary CAP_SYS_PTRACE or privileged mode) that widen the blast radius of any future LPE.
  6. Hunt for exploitation artifacts on hosts that were exposed for any meaningful window: unexpected modification timestamps on SUID binaries, unfamiliar processes tied to files like /proc/self/mem, or known exploit binary names (cowroot, dirtyc0w) surfacing in EDR telemetry.
  7. Close the loop with verification. Re-check uname -r post-patch and confirm against the vendor's fixed-version table — Dirty COW audits regularly turn up systems where the patch shipped but the host was never rebooted.

How Safeguard Helps

Nine-year-old kernel bugs like Dirty COW persist in production not because teams don't know about them, but because they're buried in sprawling dependency and infrastructure inventories with no clear signal on which assets actually matter. Safeguard's SBOM generation and ingestion continuously catalog kernel and OS package versions across your fleet — including containers and legacy VM images — so a CVE like this one is flagged the moment a vulnerable version is present, not discovered during the next audit cycle. Reachability analysis then separates hosts where the vulnerable code path is actually exposed to an exploitable entry point (an internet-facing service, a multi-tenant container host, a device accepting untrusted app installs) from isolated systems where risk is lower, so remediation effort goes where it matters first. Griffin AI correlates KEV status, EPSS trends, and your specific asset context to prioritize Dirty COW-class findings above cosmetic CVEs that never get exploited in practice. And where a fix is available, Safeguard's auto-fix PRs open the kernel or base-image version bump directly against your infrastructure-as-code or Dockerfiles, cutting the time between "patch exists" and "patch deployed" from weeks to hours.

Never miss an update

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