Post

Copy fail

Most linux LPEs need a race window or a kernel-specific offset. Copy fail is a straight-line logic flaw, it needs neither.

Copy fail

Linux kernel developers: “Let’s optimize copying for performance.”

Attackers: “Appreciate it. We’ll take root now.”

And that’s basically the story of CVE-2026-31431, nicknamed Copy Fail a local privilege escalation vulnerability that turned a weird Linux crypto subsystem optimization into a reliable root exploit.

This bug is beautiful in the same way watching someone pick a bank vault lock using a spoon is beautiful.

Links: Original Writeup


The Vulnerability in One Sentence

A local attacker could abuse Linux’s AF_ALG crypto interface + splice() + page cache behavior to overwrite protected file contents in memory and execute modified privileged binaries like /usr/bin/su.

Translation:

You weren’t supposed to write to root-owned files.

The kernel accidentally helped anyway.

Fantastic.


First Understand Normal File Behavior

Normally:

1
cat /usr/bin/su

Kernel flow:

Disk → Kernel Buffer → Userspace

And if you try:

1
echo hacked > /usr/bin/su

Linux responds with:

permission-denied

permission denied

Because Linux still had standards.


Then Someone Said “What If We Avoid Copying?”

Linux has a syscall called:

splice()

It allows moving file data between kernel objects without copying data into userspace.

Normal read:

Disk → Kernel → Userspace

splice() read:

Disk → Kernel → Another Kernel Object

Faster? Yes.

Safer? Well… you’re reading this blog.


Enter AF_ALG (The Weird Kid Nobody Looked At)

Linux has a feature called:

AF_ALG

It lets userspace applications access kernel cryptographic operations.

Example:

  • AES
  • HMAC
  • AEAD encryption

Useful feature.

Almost nobody looked at it deeply.

Which in security usually translates to:

free real estate.


The Dangerous Optimization

Back in 2017, developers introduced an optimization.

Instead of creating separate memory buffers for source and destination:

src -> separate dst -> separate

They basically went:

src = dst

Because copying memory is apparently offensive now.

This introduced dangerous overlap behavior.

The crypto subsystem assumed:

“I’m writing temporary data to safe memory.”

Reality:

“Congratulations, you’re writing into cached pages of real files.”

Small difference.

Very small.

Extremely normal.


What Is Page Cache?

When Linux reads a file:

/usr/bin/su

it often stores the file in RAM.

That RAM copy is called:

Page Cache

Flow:

Disk → Page Cache → Program Execution

Copy Fail abused this.

Instead of modifying the actual file on disk:

it modified the cached version in memory.

Meaning:

1
sha256sum /usr/bin/su

might still show the original file hash.

Security teams:

“Everything looks fine.”

Attackers:

“Yes yes absolutely fine.”

absolutely


The Exploit Chain

This is where things get spicy.


Step 1: Open a SUID binary

1
f = os.open("/usr/bin/su",0)

Why su?

Because:

  • owned by root
  • executable
  • SUID bit enabled

Perfect target.


Step 2: Use splice()

Exploit moves file pages into kernel-controlled pipes.

1
os.splice(file, pipe)

Now attacker controls references to file-backed pages.

Not ownership. Just references.

That distinction ruined someone’s week.


Step 3: Send pages into vulnerable crypto interface

1
socket(AF_ALG)

Then send crafted data.

The vulnerable authencesn() path performs an unintended write.


Step 4: Arbitrary 4-byte overwrite

The bug gives attackers a predictable:

4-byte overwrite primitive

That sounds tiny.

Until you realize:

1
2
while i < len(payload):
    overwrite_4_bytes()

And suddenly tiny corruption becomes:

rewrite entire binary in memory

Which is exactly what this PoC does.

Very rude. Very effective.


Step 5: Execute modified binary

1
os.system("su")

And boom:

root shell.

  • No race condition.
  • No kernel panic roulette.
  • No advanced ROP chain.

Just:

“Thanks for the root shell.”


Why Researchers Loved/Hated This Bug

This exploit was terrifying because it was:

  • reliable
  • clean
  • fast
  • highly reproducible

Compared to:

Dirty COW

  • Race condition nightmare.

Dirty Pipe

  • Pipe flag abuse.

Copy Fail

Just calmly walks into kernel internals and leaves with root.

Like it owns the place.

Which technically… it does after exploitation.


Why Defenders Should Care

Traditional file monitoring may fail because:

  • disk file unchanged
  • memory page modified

Your EDR might be staring at disk integrity logs while an attacker is already root LOL.

Awkward.

no-god-please


What This Bug Teaches

Modern exploitation is increasingly about:

  • weird kernel interactions
  • logic flaws
  • abuse of legitimate features
  • unintended side effects

Not every exploit looks like movie-style shellcode flying across the screen.

Sometimes it’s:

“What if I politely ask Linux optimizations to betray everyone?”

And Linux responds:

“Sure.”

okay


Remember every time someone says:

“It’s just a small optimization.”

Security engineers should immediately become uncomfortable.

This post is licensed under CC BY 4.0 by the author.