Like a janitor tossing a bin someone's still reaching into — the kernel frees a timer object while another thread still has its hand in the queue
CVE-2026-64560 is a use-after-free in the Linux kernel's POSIX CPU timer subsystem, present since v5.7 (May 2020). When a non-leader thread calls execve(), de_thread() swaps the thread-group leader and __exit_signal() nullifies the old leader's sighand pointer. A concurrent timer_delete() or timer_settime() call observes sighand == NULL, bails out without dequeuing the timer, and leaves a freed k_itimer node dangling in the signal->cpu_timers rbtree. When run_posix_cpu_timers() next walks the tree, it dereferences freed memory. Affected versions span 5.7 through 7.1.4 across all architectures. Stable-branch fixes landed in 5.10.262, 5.15.213, 6.1.180, 6.6.147, 6.12.100, 6.18.41, and 7.1.5. Android GKI kernels on SPL ≤ 2026-08-01 are also affected.
The NVD rates this 7.8 HIGH (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H). Red Hat independently scored it 7.0 HIGH, diverging on Attack Complexity — they rate it AC:H, which better reflects the race-condition mechanics. Red Hat's score is more honest: winning this race reliably is non-trivial, and the only public PoC (villager1314/CVE-2026-64560-Analysis) is a crash trigger that explicitly lacks privilege-escalation primitives. Converting a timerqueue UAF to a controlled write requires heap shaping, cross-cache object replacement, and bypassing KASLR+SMEP+SMAP+CFI — feasible for a skilled researcher, but not script-kiddie territory. The vendor severity is directionally correct but slightly overstated on complexity grounds.
5 steps from start to impact.
Obtain local code execution
AV:L means the attacker is already past the perimeter.- Local user account or code execution on the target host
- Kernel version 5.7 through 7.1.4 (unpatched)
- Requires prior compromise or insider access — this is NOT the initial entry point
- Cloud/container workloads often run minimal images with restricted user capabilities
Arm POSIX CPU timers in a tight loop
CLOCK_PROCESS_CPUTIME_ID timers with very short expiration windows using timer_create() and timer_settime(). This is the 'timer thread' in the villager1314 PoC. The syscalls are available to any unprivileged user — no capabilities required.- Ability to call timer_create() and timer_settime() syscalls
- No seccomp profile blocking timer_create / timer_settime
- Hardened container runtimes (gVisor, Kata) intercept or emulate these syscalls
- Seccomp profiles in Kubernetes (RuntimeDefault or stricter) may block timer_create
timer_create syscall; abnormal timer churn visible in /proc/timer_listRace non-leader exec() against timer deletion
execve(). The goal is to collide de_thread() (which swaps the group leader and nullifies sighand) with posix_cpu_timer_del() observing the stale task pointer. The PoC uses a busy loop to maximize collision probability. On KASAN-enabled kernels this triggers an immediate use-after-free warning; on production kernels, the outcome ranges from silent corruption to a kernel panic.- Winning the race between de_thread() and timer_del()
- No KASAN/KFENCE killing the process before corruption is useful
- Race window is narrow — Red Hat rates AC:H for this reason
- KASAN/KFENCE-enabled kernels catch the UAF immediately and panic cleanly
- Success rate is probabilistic, not deterministic
Escalate UAF to controlled write (theoretical)
k_itimer slab object, (b) reclaim the freed slot with a controlled object (cross-cache spray), (c) trigger run_posix_cpu_timers() to write through the timerqueue node into attacker-controlled memory, and (d) overwrite a function pointer or credential structure. This requires bypassing KASLR, SMEP, SMAP, and (on 6.x+) kCFI. No public exploit achieves this.- Detailed knowledge of target kernel's slab layout
- Ability to perform cross-cache heap spray
- Bypass of KASLR, SMEP, SMAP, kCFI
- No public exploit exists — the villager1314 PoC explicitly states it has no exploitation primitives
- Modern kernel hardening (kCFI on 6.2+, CONFIG_SLAB_FREELIST_HARDENED) makes cross-cache attacks significantly harder
- Each kernel build has a different slab layout, requiring per-target tuning
Achieve root or container escape
current->cred or hijacks a function pointer to gain CAP_SYS_ADMIN / uid 0. In a container context, this means escaping the user namespace and gaining root on the host node. The blast radius is limited to the single host — there is no lateral-movement primitive built into this vulnerability.- Successful completion of step 4
- Target kernel lacks kCFI or has a known bypass
- Blast radius is single-host, not fleet-wide
- Container-escape from kernel UAF is a known but difficult technique
- Host-level EDR should detect credential modification
timer_create and timer_settime syscalls. Most application containers do not need POSIX CPU timers. This breaks step 2 of the attack path. Deploy within the noisgate mitigation SLA of 30 days for HIGH.CONFIG_KASAN or CONFIG_KFENCE on a subset of hosts. These kernel sanitizers detect the UAF immediately and panic the kernel before memory corruption can be leveraged for escalation. This converts the vulnerability from potential-LPE to guaranteed-DoS-only, which is a significant risk reduction. Not suitable for all production workloads due to performance overhead (KASAN: ~2x, KFENCE: ~1%).CAP_DROP ALL in container security contexts. Reduce the population of potential attackers who can reach step 1 of the attack path.- Network firewalls / WAF / IDS — this is a local vulnerability with no network attack surface. Perimeter controls are irrelevant to the attack path.
- ASLR alone — userspace ASLR does not affect kernel exploitation. KASLR helps but is bypassable with kernel info leaks and is not a standalone mitigation.
- AppArmor / SELinux confinement — MAC policies restrict file and capability access but do not block the
timer_create/execvesyscall sequence needed for the race. Only seccomp filters operate at the syscall level. - Live-patching (kpatch/livepatch) — the fix spans multiple files (kernel/exit.c, kernel/signal.c, kernel/time/posix-cpu-timers.c) with memory-ordering changes that are not safely live-patchable. A full reboot into the patched kernel is required.
The supporting signals.
| In-the-Wild Exploitation | Not observed. Not on CISA KEV. No GreyNoise tags. No campaign attribution. The local-only attack vector makes mass exploitation unlikely — each target requires pre-existing access. |
|---|---|
| Proof-of-Concept | Crash PoC available. villager1314/CVE-2026-64560-Analysis provides a race trigger for Linux x86_64 and Android (NDK). It triggers KASAN UAF warnings or kernel panics but explicitly lacks privilege-escalation primitives (no heap spray, no RIP control). A related repo Meniben/redmi14c-pond-cve-2026-64560 targets a specific Android device. No Metasploit/ExploitDB/Nuclei modules found. |
| EPSS | 0.00635 (~0.6% probability of exploitation in next 30 days). Bottom quartile — consistent with local-only kernel race conditions without weaponized exploits. |
| CISA KEV | Not listed as of 2026-10-07. |
| CVSS Vector | NVD: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (7.8). Red Hat: CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H (7.0). The AC:L vs AC:H divergence is the key disagreement — the race condition genuinely narrows the exploitation window. |
| Affected Versions | Introduced in v5.7-rc1 (commit 55e8c8eb2c7b, May 2020). All mainline kernels through 7.1.4 are affected. Android GKI kernels 5.10, 5.15, 6.1, 6.6, 6.12 with SPL ≤ 2026-08-01 are affected. |
| Fixed Versions | 5.10.262, 5.15.213, 6.1.180 (Debian bookworm: 6.1.187-1), 6.6.147, 6.12.100 (Debian trixie: 6.12.107-1), 6.18.41, 7.1.5, 7.2-rc3 (mainline). Debian bullseye: 5.10.262-1. RHEL: RHSA-2026:57252. |
| Scanning / Exposure | Not applicable for GreyNoise/Shodan — this is a local vulnerability with no network attack surface. Exposure is measured by unpatched kernel count, not internet-facing services. |
| Disclosure & Credit | Disclosed 2026-07-29. Reported by Wongi Lee and Jungwoo Lee. Fix authored by Thomas Gleixner. Mainline commit 920f893f735e. |
| CWE | CWE-416 (Use After Free) per NVD. Red Hat also maps CWE-364 (Signal Handler Race Condition). Both are accurate — the root cause is a race, the consequence is UAF. |
Sources.
Why this verdict
- Race-condition complexity is understated by NVD. NVD rates AC:L but the exploit requires winning a narrow race between
de_thread()andtimer_del(). Red Hat independently scored AC:H (7.0), which better reflects the probabilistic nature of the trigger. The PoC author confirms reliability is low without repeated attempts. - No weaponized exploit exists. The only public PoC is a crash trigger with zero exploitation primitives. Converting a timerqueue UAF to a controlled write requires cross-cache heap spray, KASLR bypass, and (on 6.2+) kCFI bypass — substantial additional work that has not been publicly demonstrated.
- Local-only attack vector limits reachability. AV:L means the attacker already has code execution on the target host. This is a privilege-escalation building block, not an initial-access vector. Every exploitation scenario starts with 'attacker is already inside.'
- EPSS corroborates low exploitation probability. At 0.00635, this sits in the bottom quartile of scored CVEs, consistent with the absence of in-the-wild activity and the high bar for weaponization.
- Role multiplier: The Linux kernel is a canonical high-value-role component — it IS the hypervisor (KVM), the container host, the database engine's OS layer. In multi-tenant container environments (Kubernetes nodes, shared hosting), a kernel LPE crosses the container→host trust boundary, which is a host-level blast radius. On KVM hypervisors, it's a tenant-level blast radius. These roles represent a significant fraction of the Linux installed base (>10% of enterprise Linux deployments run containers or KVM). This floors the verdict at HIGH despite the friction factors. However, the blast radius is single-host, not fleet-wide or domain-wide, so the floor is HIGH, not CRITICAL.
Why not higher?
CRITICAL would require either active exploitation, a weaponized public exploit, or a fleet-scale / domain-takeover blast radius. None of these conditions are met. The only PoC is a crash trigger, EPSS is bottom-quartile, no KEV listing exists, and successful exploitation is bounded to a single host. The race condition's unreliability further argues against CRITICAL — even a motivated attacker faces probabilistic failure on each attempt.
Why not lower?
MEDIUM would understate the risk because the Linux kernel is a canonical high-value-role component. On container hosts and KVM hypervisors — which represent >10% of enterprise Linux deployments — a kernel UAF-to-LPE crosses a critical trust boundary (container→host, VM→hypervisor). The UAF primitive class has a long history of successful weaponization in the Linux kernel (cf. CVE-2022-2585, a closely related posix-cpu-timer UAF that was weaponized). The absence of a current exploit does not mean absence of future capability — the technical path is well-understood.
Crowdsourced verification payload.
Run this script on each target Linux host as any user (no root required for the version check). Invoke with: bash check_cve_2026_64560.sh. It compares the running kernel version against known-fixed versions and outputs VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env bash
# check_cve_2026_64560.sh — Detect CVE-2026-64560 (posix-cpu-timers UAF)
# Run on the target Linux host. No root required.
# Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN
set -euo pipefail
KERNEL=$(uname -r)
# Extract major.minor.patch, stripping distro suffixes
VER=$(echo "$KERNEL" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+')
if [[ -z "$VER" ]]; then
echo "UNKNOWN — could not parse kernel version from: $KERNEL"
exit 2
fi
MAJOR=$(echo "$VER" | cut -d. -f1)
MINOR=$(echo "$VER" | cut -d. -f2)
PATCH=$(echo "$VER" | cut -d. -f3)
# version_ge: returns 0 if $1.$2.$3 >= $4.$5.$6
version_ge() {
local a1=$1 a2=$2 a3=$3 b1=$4 b2=$5 b3=$6
if (( a1 > b1 )); then return 0; fi
if (( a1 < b1 )); then return 1; fi
if (( a2 > b2 )); then return 0; fi
if (( a2 < b2 )); then return 1; fi
if (( a3 >= b3 )); then return 0; fi
return 1
}
# Vuln introduced in 5.7.0. Not affected if < 5.7.
if (( MAJOR < 5 )) || { (( MAJOR == 5 )) && (( MINOR < 7 )); }; then
echo "PATCHED — kernel $KERNEL predates the vulnerable commit (introduced in 5.7)"
exit 0
fi
# Fixed version map per stable branch
VULN=0
case "${MAJOR}.${MINOR}" in
5.10) version_ge $MAJOR $MINOR $PATCH 5 10 262 || VULN=1 ;;
5.15) version_ge $MAJOR $MINOR $PATCH 5 15 213 || VULN=1 ;;
5.7|5.8|5.9|5.11|5.12|5.13|5.14|5.16|5.17|5.18|5.19)
# These branches are EOL and have no backported fix
VULN=1 ;;
6.1) version_ge $MAJOR $MINOR $PATCH 6 1 180 || VULN=1 ;;
6.6) version_ge $MAJOR $MINOR $PATCH 6 6 147 || VULN=1 ;;
6.12) version_ge $MAJOR $MINOR $PATCH 6 12 100 || VULN=1 ;;
6.18) version_ge $MAJOR $MINOR $PATCH 6 18 41 || VULN=1 ;;
6.2|6.3|6.4|6.5|6.7|6.8|6.9|6.10|6.11|6.13|6.14|6.15|6.16|6.17)
# Non-LTS branches between 6.1 and 6.6, or 6.6 and 6.12 — EOL, no fix
VULN=1 ;;
7.1) version_ge $MAJOR $MINOR $PATCH 7 1 5 || VULN=1 ;;
7.2|7.*)
# 7.2-rc3+ contains the fix; assume 7.2.0+ is patched
if (( MINOR >= 2 )); then
VULN=0
else
VULN=1
fi
;;
*)
echo "UNKNOWN — unrecognized kernel branch ${MAJOR}.${MINOR} ($KERNEL)"
exit 2
;;
esac
if (( VULN == 1 )); then
echo "VULNERABLE — kernel $KERNEL is affected by CVE-2026-64560"
echo " Fix versions: 5.10.262, 5.15.213, 6.1.180, 6.6.147, 6.12.100, 6.18.41, 7.1.5+"
exit 1
else
echo "PATCHED — kernel $KERNEL includes the fix for CVE-2026-64560"
exit 0
fi