## Why does this matter more than other Linux LPEs?

Linux LPE CVEs ship daily. Most are race-dependent, narrowly version-specific, or both. **Copy Fail isn't** — it's a straight-line logic flaw with four properties that almost never appear together:

<ul class="bullets">
  <li><b>Portable.</b> Same script roots Ubuntu, Amazon Linux, RHEL, SUSE. No per-distro offsets, no version checks, no recompilation.</li>
  <li><b>Tiny.</b> 732-byte Python script, stdlib only (<code>os</code>, <code>socket</code>, <code>zlib</code>). No compiled payload, no dependencies. Python 3.10+ for <code>os.splice</code>.</li>
  <li><b>Stealthy.</b> The write bypasses the VFS path entirely; the corrupted page is never marked dirty. Nothing hits disk &mdash; on eviction or reboot, the cache reloads clean and a forensic disk image shows the original file. (See the integrity-tool FAQ entry below for the in-cache detection window.)</li>
  <li><b>Cross-container.</b> The page cache is shared across the host. A pod with the right primitives compromises the node and crosses tenant boundaries — container escape primitive, not just LPE.</li>
</ul>

<table class="compare">
  <thead>
    <tr>
      <th></th>
      <th>typical Linux LPE</th>
      <th class="hl">Copy Fail</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>Race condition</td><td class="dim">required</td><td class="hl">none</td></tr>
    <tr><td>Per-distro offsets</td><td class="dim">required</td><td class="hl">none</td></tr>
    <tr><td>Reliability</td><td class="dim">30–80% per attempt</td><td class="hl">100%, single shot</td></tr>
    <tr><td>Affected window</td><td class="dim">narrow kernel range</td><td class="hl">2017 → 2026 (9 yrs)</td></tr>
  </tbody>
</table>

<p style="font-size:13px;color:var(--ink-faint);margin-top:8px">Comparison framing the typical LPE class against Copy Fail's specific guarantees, not any one named CVE.</p>

## What is Copy Fail in one sentence?

An unprivileged local user can write 4 controlled bytes into the page cache of any readable file on a Linux system, and use that to gain root.

## Why is the page cache the target, not the file on disk?

The page cache is the in-memory copy the kernel reads when it loads a binary. Modifying the cached copy of `/usr/bin/su` is equivalent — for `execve` purposes — to modifying the binary itself, except nothing on disk changes, no inotify fires, no checksum mismatches.

## Will my file integrity tool detect this?

Probably yes — *while the corruption is hot in cache*. Standard hashing tools (`sha256sum`, AIDE, Tripwire) read via `read()`, which goes through the page cache — the same path `execve` uses. So during the window, the hash differs from the baseline.

The corruption is transient, though. Nothing is written back to disk: once the page is evicted (memory pressure, `echo 3 > /proc/sys/vm/drop_caches`) or the system reboots, the cache reloads clean from disk and hashes match again. A forensic image of the disk shows the unmodified file.

IMA appraisal in enforcing mode with measurement-on-every-read catches it at `execve` time, before the corrupted binary runs.

## Should I be afraid?

If you run multi-tenant Linux, shared-kernel containers, CI runners that execute untrusted code, or anything where someone you don't fully trust can `execve` as a regular user — yes. Patch.

Single-user laptop with full-disk encryption and a locked screen — far less urgent. Patch anyway.

## Why "Copy Fail"?

Because `authencesn` doesn't actually copy when it should. It uses the caller's destination buffer as a scratch pad, scribbles 4 bytes past the legitimate output region, and never restores them. The "copy" of the AAD ESN bytes "fails" to stay inside the destination buffer.

## How is this different from Dirty Pipe?

Same family — page-cache corruption from unprivileged userspace, no on-disk change, write to setuid binary, root. Different mechanism: Dirty Pipe abused pipe buffer flags. Copy Fail abuses an AEAD scratch write that crosses a chained scatterlist boundary.

Copy Fail is more portable. One script, every distro, no offsets. Dirty Pipe needed kernel ≥ 5.8 with specific patches; Copy Fail covers the entire 2017–2026 window.

## How is this different from Dirty Cow?

No race condition. Dirty Cow needed to win a TOCTOU window in the COW path — multiple attempts, occasionally crashes the system. Copy Fail is straight-line code. It either fires or it doesn't, and it always fires.

## Does it require `/usr/bin/su`?

No. Any setuid-root binary readable by the user works. `passwd`, `chsh`, `chfn`, `mount`, `sudo`, `pkexec` are all viable. The PoC defaults to `su` because it's present on every distro tested.

## Is this remotely exploitable?

Not by itself — it requires local code execution as a regular user. Chain it with anything that gives you that (web RCE landing in an unprivileged service account, an SSH foothold, a malicious PR on a CI runner) and you're root.

## What does the patch do?

It reverts the 2017 `algif_aead` in-place optimization. After the patch, `req->src` and `req->dst` are separate scatterlists again — page-cache pages live in the read-only source, the user buffer is the only thing crypto can write to. Mainline commit `a664bf3d603d`.

## Will you release the full PoC?

Yes — it's [on this page](#exploit). We held it for a month while distros prepared patches; the major builds are out as of this writing.

## Was this AI-found?

AI-assisted. The starting insight — that `splice()` hands page-cache pages into the crypto subsystem and that scatterlist page provenance might be an under-explored bug class — came from human research by Taeyang Lee at Xint.

From there, [Xint Code](#contact) scaled the audit across the entire `crypto/` subsystem in roughly an hour. Copy Fail was the highest-severity finding in the run.

## Where's the full technical write-up?

Root cause, scatterlist diagrams, the 2011 → 2015 → 2017 history, and the exploit walkthrough are on the [Xint blog](https://xint.io/blog/copy-fail-linux-distributions). Part 2 (Kubernetes container escape) is forthcoming.
