Skip to content

Back to the catalog

Samsung Kernel UAF (CVE-2026-20971)
lucidbitlabs.comwriteup

Samsung Kernel UAF (CVE-2026-20971)

LucidBit Labs details CVE-2026-20971, a use-after-free race condition in Samsung's PROCA/FIVE kernel integrity subsystem, exploitable via procfs handlers (/proc/pid/integrity/*) that fetch task_integrity pointers without taking a reference before an execve() concurrently frees the old object. The bug affects Galaxy S9 through S25 and other Samsung devices on both Qualcomm and Exynos chipsets, is triggerable from any untrusted app, and yields memory corruption primitives (though not a full LPE exploit); Samsung patched it in the 01-2026 update.

TL;DR Race-condition UAF in Samsung's PROCA/FIVE kernel integrity subsystem (CVE-2026-20971) exploitable from any app on Galaxy S9-S25 devices, patched Jan 2026.
Document

What it is

CVE-2026-20971 is a use-after-free in Samsung's FIVE kernel integrity subsystem (part of PROCA/KNOX). The summary covers the root cause and affected range; what it omits is the exploitation analysis — three concrete primitives derived from the bug, an execve trick that unlocks the most dangerous one, and how KCFI ultimately neutralizes it. That is the reason to read the page.

The three primitives

The /proc/<pid>/integrity/* handlers each grab task->integrity (a raw pointer, no refcount taken) and can be preempted before use, letting a concurrent execve() free it via task_integrity_put(old_tint).

  • Primitive 1 — infoleak (proc_integrity_value_read). Reads user_value at offset 0; if the slot is reclaimed with controlled data before the reader resumes, procfs prints the first qword of the freed allocation. No crash risk, DWORD leak, and doubles as a "did reclaim happen" oracle to guard riskier primitives.
  • Primitive 2 — arbitrary call (proc_integrity_reset_file), dead-ended by CFI. d_path() on a freed reset_file reaches path->dentry->d_op->d_dname(...), an indirect call through freed memory. The kernel ships CONFIG_CFI_CLANG=y (KCFI), so the target must be a type-compatible indirect-call target; the authors found no useful function matching the d_dname prototype and call this a "truly dead end." Reported as a case where CFI was a highly effective mitigation.
  • Primitive 3 — constrained write (proc_integrity_label_read). The value_lock spinlock sits at offset 0xc; spin_lock/spin_unlock on the reclaimed object produce a small write (locked-byte/pending/tail transitions) into whatever overlaps that offset — usable against a pointer, refcount, length or flags field. The spinlock can also be abused as a timing widener: forcing contention keeps the reader spinning on the committed old address while another CPU frees and reclaims.

The /system/bin/monkey trick

The arbitrary-call path normally fails because reset_file has refcount > 1 in every app inspected. The authors bypass the dedicated-cache cross-cache problem by targeting reset_file (larger race window) instead of task_integrity itself. To force refcount 1: five_bprm_check() assigns a fresh tint before search_binary_handler() proves loadability, so an executable that passes early checks but returns -ENOEXEC leaves reset_file holding the only reference. /system/bin/monkey exists on all test devices — 0755, on an executable mount, but plain text with no #! line — so execve("/system/bin/monkey", ...) deterministically records it as the CAUSE_EXEC reset file.

flowchart TD
    A[execve on /proc reader path] --> B[handler fetches TASK_INTEGRITY, preempted]
    B --> C[target execve frees old tint via task_integrity_put]
    C --> D{which handler / target?}
    D -->|value_read| E[Primitive 1: infoleak, no crash]
    D -->|label_read spinlock| F[Primitive 3: constrained write at 0xc]
    D -->|reset_file d_dname| G[Primitive 2: indirect call]
    G --> H[KCFI type check]
    H -->|no compatible target| I[dead end / panic]

Caveats

The page describes primitives, not a full LPE — no chained exploit is published. The race window is "a couple of opcodes" wide and task_integrity uses its own task_integrity_cache, so any valuable UAF requires a cross-cache attack. Primitive 3's write can be transient (fast-path lock/unlock leaves memory unchanged), and abusing the spinlock for timing risks a hard-lockup panic if the lock isn't freed within 10–20 seconds.

Organisations named here

  • LucidBit Labs

CVEs named here

  • CVE-2026-20971

Technologies named here

  • PROCA
  • FIVE
  • Samsung Galaxy S21
  • KNOX
  • Samsung Galaxy S22
  • Kernel Control Flow Integrity
  • Samsung Galaxy S24
  • Samsung Galaxy A54
  • Samsung devices with Qualcomm chipsets
  • Samsung devices with Exynos chipsets
  • Samsung PROCA kernel subsystem
  • Samsung FIVE
  • /system/bin/monkey system binary
  • Android
  • Linux kernel
  • Samsung Knox