## https://sploitus.com/exploit?id=F8E5B958-B5DC-57C1-9FA9-076BF3B70128
# CVE-2026-64560 β Linux Kernel posix-cpu-timers Non-leader exec() Race Condition UAF
> **Reproducer / PoC (Proof-of-Concept)**: Linux & Android (NDK)
> This repository is intended solely for verifying patch status and research purposes on **personal test devices**; it does not contain any privilege escalation or exploitation primitives.
[] ()
[] ()
[]()
[]()
---
## 1. Vulnerability Overview
| Field | Content |
|---|---|
| **CVE ID** | CVE-2026-64560 |
| **Title** | posix-cpu-timers: Prevent UAF caused by non-leader exec() race |
| **Type** | Use-After-Free (CWE-416), Race Condition |
| **CNA** | kernel.org (Linux CNA) |
| **CVSS v3.1** | **7.8 High** β `CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H` |
| **CVSS v4.0 (SUSE)** | **8.5 High** β `CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N` |
| **EPSS** | ~0.12% (2nd percentile, as of August 2026) |
| **CISA KEV** | Not listed |
| **Publication Date** | July 29, 2026 |
| **Patch Submission (mainline)** | [`920f893f735e92ba3a1cd9256899a186b161928d`] (https://github.com/torvalds/linux/commit/920f893f735e92ba3a1cd9256899a186b161928d) |
| **Issue Submission (Fixes:)** | [`55e8c8eb2c7b`](https://github.com/torvalds/linux/commit/55e8c8eb2c7b) (v5.7, 2020) β "posix-cpu-timers: Store a reference to a pid, not a task" |
| **Fixer** | Thomas Gleixner \ |
| **Reporter** | Wongi Lee \, Jungwoo Lee \ |
| **Affected Files** | `kernel/exit.c`, `kernel/signal.c`, `kernel/time/posix-cpu-timers.c` |
### Affected Versions
The vulnerability was introduced in **v5.7** (May 2020), and the fix has been backported to all stable branches:
| Branch | Affected | Fixed Version (β₯) | Stable Fix Commit |
|---|---|---|---|
| 5.10 LTS | 5.7 ~ 5.10.261 | **5.10.262** | `67aa823e3e8c` |
| 5.15 LTS | ~ 5.15.212 | **5.15.213** | `d8bcb28abad8` |
| 6.1 LTS | ~ 6.1.179 | **6.1.180** | `cc35ddbc4973` |
| 6.6 LTS | ~ 6.6.146 | **6.6.147** | `12a891c773ae` |
| 6.12 LTS | ~ 6.12.99 | **6.12.100** | `e74443f5db00` |
| 6.18 | ~ 6.18.40 | **6.18.41** | `6a7ecc25abe6` |
| 7.1 | ~ 7.1.4 | **7.1.5** | `ad1cafa1bdaa` |
| mainline | `siglock` to protect the timerqueue.
The 2020 commit `55e8c8eb2c7b` replaced the ** task pointers cached in the timer were replaced with pid references** (to fix an issue introduced by the 2010 workaround `e0a70217107e`), requiring a `pid_task(pid, type)` lookup before each operation. This change left open the race condition window for this CVE.
### 2.2 Race Condition Scenario (exec by a non-leader thread)
When `execve()` is initiated by a **non-leader thread**, `de_thread()` β `switch_leader()` causes the TGID to transfer from the old leader to the new leader. The old leader then executes `release_task()` β `__exit_signal ()`, during which `old_leader->sighand = NULL` and `unhash_task(old_leader)` are performed.
At the same time, on another CPU, `sys_timer_delete()` β `posix_cpu_timer_del()` is executed:
```
sys_timer_delete() exec()
posix_cpu_timer_del()
// The old leader is observed
p = pid_task(pid, pid_type); de_thread()
switch_leader();
release_task(old_leader)
__exit_signal(old_leader)
sighand = lock(old_leader, sighand);
posix_cpu_timers*_exit();
sighand = lock_task_sighand(p) unhash_task(old_leader);
sh = lock(p, sighand) old_leader->sighand = NULL;
unlock(sighand);
(p->sighand == NULL)
unlock(sh)
return NULL;
// Return directly without removing the link!
if (!sighand)
return 0;
free_posix_timer(); // β k_itimer is released
```
`posix_cpu_timer_del()` identifies `p` as the **old leader**. At this point, `p->sighand == NULL`, so the function assumes that "the task is exiting, and the exit path will handle removing the link," and thus **returns successfully without doing anything**. Subsequently, `free_posix_timer()` releases `k_itimer`.
**Key point**: `exec()` differs from `exit()`βduring `exec()`, the TGID remains unchanged, and armed timers attached at the process level (`p->signal->cpu_timers`) **are inherited and remain enqueued**. Consequently:
- `run_posix_cpu_timers()` (which traverses the timerqueue during a tick) accesses the `timerqueue_node` of a deallocated object β **UAF read/write**;
- Add/delete operations on other timers will also traverse this RBTree containing dangling nodes β UAF.
Similar issues exist in:
- **`posix_cpu_timer_set()`**: Regular timers merely return `-ESRCH` temporarily; however, the kernelβs internal `do_cpu_nanosleep()` uses a `k_itimer` allocated on the stack, resulting in the same UAF.
- **`posix_cpu_timer_rearm()`**: Silent rearm failure causes the timer to no longer expire (functional bug).
### 2.3 Secondary Issues on Weakly Ordered Architectures
Frederic Weisbecker points out: `tsk->sighand = NULL` in `__exit_signal()` is a regular store. On weakly ordered architectures such as ARM64, when `posix_cpu_timer_del()` observes `sighand == NULL`,** **it is not guaranteed** that the de-queue write preceding `posix_cpu_timers*_exit()` will be observed, causing `WARN_ON_ONCE(timer_queued(tmr))` to potentially generate a false positive.
### 2.4 Fix
1. Change to `smp_store_release(&tsk->sighand, NULL)` in `__exit_signal()`;
2. Add `smp_acquire__after_ctrl_dep()` to the `!sighand` path in `lock_task_sighand()`;
3. Add a new helper function `timer_lock_sighand()`: Look up the task and lock `sighand`; if `sighand == NULL`, **do not return but retry the lookup**βin `exec` scenarios, this will find the new leader; in `exit` scenarios, it will only give up if the lookup fails;
4. The three affected functions (`_del` / `_set` / `_rearm`) have been uniformly updated to use this helper.
See [patches/920f893f735e.patch](patches/920f893f735e.patch) for the full diff.
---
## 3. PoC Description (Trigger Verification, Not a Privilege Escalation Exploit)
A **race condition trigger** is provided in the `poc/` directory: two threads run in high-intensity loops
- **Thread A (timer thread)**: Repeatedly calls `timer_create(CLOCK_PROCESS_CPUTIME_ID)` β arm (with a very short initial expiration time) β busy-wait trigger β `timer_delete()`;
- **Thread B (exec thread)**: repeatedly calls `fork()` β **creates a non-leader thread in the child process, which then calls `execve()`** (non-leader `exec` is a prerequisite for this vulnerability), and the parent process immediately recovers it via `waitpid()`.
When `timer_delete()` happens to race-conditionally conflict with `de_thread()`/`__exit_signal()`, the already-released `k_itimer` in an unpatched kernel remains hanging on the rbtree of `signal->cpu_timers`, and subsequently, `run_posix_cpu_timers()` or other timerqueue operations will access the dangling node. With a KASAN-enabled kernel, reports such as `BUG: KASAN: use-after-free in run_posix_cpu_timers` / `timerqueue_del` can be reliably observed; without KASAN, the issue typically manifests as sporadic kernel warnings or panics.
> **Nature of the Vulnerability**: This is a pure C race condition trigger that **does not include** any exploitation primitives such as heap spray, object placeholders, or RIP control. Turning this into a privilege escalation exploit requires a significant amount of additional work (heap spraying, placeholder objects in the slab cache where `k_itimer` resides, bypassing KASLR/CFI, etc.), and is highly dependent on the specific kernel build. This repository intentionally excludes these components.
### Table of Contents
```
βββ README.md β This document
βββ patches/
β βββ 920f893f735e.patch β Full text of the mainline fix patch
βββ poc/
βββ cve_2026_64560_poc.c β Trigger source code (universal for Linux/Android)
βββ Makefile β Cross-compilation for Linux / NDK
βββ Android.mk β NDK ndk-build (optional)
```
### 3.1 Compiling and Running on Linux x86_64
```bash
cd poc
make # Generate cve_2026_64560_poc
sudo ./cve_2026_64560_poc -d 60
# Observe dmesg: sudo dmesg -wH | grep -iE 'kasan|use-after|BUG|WARNING'
```
### 3.2 Android (NDK Cross-Compilation, adb Push)
```bash
cd poc
export ANDROID_NDK_HOME=/path/to/ndk
make android # Build cve_2026_64560_poc_arm64 (static, pie)
adb push cve_2026_64560_poc_arm64 /data/local/tmp/cvepoc
adb shell chmod 755 /data/local/tmp/cvepoc
adb shell /data/local/tmp/cvepoc -d 120
# Observe the kernel logs:
adb shell su 0 dmesg -w | grep -iE 'kasan|use-after|BUG|WARNING|timer'
# Without root access, you can also use `adb shell cat /sys/fs/pstore/console-ramoops*` after triggering a crash to view the logs
```
Device requirements:
1. The kernel version must fall within the affected range (5.7 through the version prior to the fix listed in the table above); devices with an SPL β€ 2026-08-01 are generally affected;
2. The device must not have this patch applied (after applying the patch, the PoC will simply spin indefinitely and exit);
3. To view a clear KASAN report, a KASAN-enabled kernel is required (a self-compiled GKI/boot.img will suffice); when triggered on a stock kernel, the behavior typically manifests as a watchdog/panic or silent corruption.
### 3.3 Exploit Mechanism (Why Itβs Designed This Way)
- The `CLOCK_PROCESS_CPUTIME_ID` timer targets **TGID** β It is attached to `signal->cpu_timers` and is inherited after `exec` β β This is a prerequisite for UAF (`CLOCK_THREAD_CPUTIME_ID` does not work);
- **Non-leader thread exec** β `switch_leader()` causes the old leader returned by `pid_task(TGID)` to immediately have `sighand = NULL` ββ This is a necessary condition for the race condition;
- High-frequency `timer_create/arm/delete` operations combined with high-frequency `fork`/`exec` operations running in parallel maximize the probability that `posix_cpu_timer_del()` falls within the window; The timer expiration handling (`run_posix_cpu_timers`) itself will also trigger the suspended node; no additional trigger is needed.
---
## 4. Self-Check: Has My Device Been Patched?
```bash
# Android:
adb shell cat /proc/version # Is the kernel version >= the patched version in the table above?
adb shell getprop ro.build.version.security_patch # Is the SPL > 2026-08
# Linux:
uname -r
# Or directly check if the source code contains `timer_lock_sighand`:
grep -r timer_lock_sighand /usr/src/linux/kernel/time/posix-cpu-timers.c
```
If the PoC runs for several minutes without any KASAN or panic errors and the kernel version is β₯ the patched version, the issue is considered fixed (the PoC itself also includes a `--check` mode for lightweight smoke testing).
---
## 5. Reference Links
- CVE entry: https://vulners.com/cve/CVE-2026-64560
- GitHub Advisory: https://github.com/advisories/GHSA-78ph-mc3q-52vv
- Mainline fix commit: https://github.com/torvalds/linux/commit/920f893f735e92ba3a1cd9256899a186b161928d
- Commit introducing the issue (v5.7): https://github.com/torvalds/linux/commit/55e8c8eb2c7b6bf30e99423ccfe7ca032f498f59
- 2010 workaround: https://github.com/torvalds/linux/commit/e0a70217107e
- SUSE tracking (including Bugzilla 1273004/1273007): https://www.suse.com/security/cve/CVE-2026-64560
---
## Disclaimer
This repository is intended solely for security research and defense verification. **Run only on devices you own or for which you have obtained written authorization**. The PoC may cause kernel instability or even a panic; do not run it on production devices. The author is not responsible for any consequences resulting from misuse.