Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-38352-PoC — PoC and GDB script assists in triggering CVE-2025-38352 | Kitploit
Tools/GitHubGitHub/longwasu/cve-2025-38352-poc
Memory ForensicsVulnerability AnalysisExploitationReverse EngineeringDebuggersPapers & ResearchLearning & EducationBinary Exploitation
GitHublongwasu/cve-2025-38352-poc

CVE-2025-38352-PoC

PoC and GDB script assists in triggering CVE-2025-38352

View Repository
7h 16m agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-38352: Linux Kernel POSIX CPU Timer TOCTOU Race Condition & UAF

A reproducible Proof-of-Concept (PoC) and automated GDB orchestration script for CVE-2025-38352, a Time-of-Check to Time-of-Use (TOCTOU) race condition in the Linux kernel's POSIX CPU timer subsystem (kernel/time/posix-cpu-timers.c) leading to Use-After-Free (UAF).

Disclaimer: This project is for educational, defensive, and security research purposes only. All testing and reproduction were conducted in an isolated ARM64 QEMU virtual machine.


🧠 How the Bug Works

  1. Process A creates child Process B.

  2. Process B creates a CPU timer and begins exiting, entering the zombie state. Just as B is exiting, a timer interrupt arrives on its CPU core. The kernel enters interrupt context to process the timer, but temporarily releases its lock (unlock_task_sighand) to avoid deadlocks.

  3. At the exact same time on another core, Process A reaps the exiting B, cleaning up its signal handler (sighand = NULL) and unhashing its PID.

  4. Another thread in B calls timer delete (posix_cpu_timer_del). It attempts to look up the task via its PID and check its signal handler, but finds them already cleaned up / NULL. Misinterpreting that the task is completely dead and no timers could possibly be firing, it assumes it is safe and frees the timer from memory.

  5. Meanwhile, the timer interrupt handler on the first core resumes to fire the expired timer. Because the timer was just freed in Step 4, accessing it triggers a Use-After-Free and crashes the kernel.


🔬 Synchronization Strategy (poc_gdb_script.py)

Because QEMU's GDB stub does not support set non-stop on (halting one vCPU halts all vCPUs), standard multi-threaded synchronization cannot be achieved via plain breakpoints.

This repository solves the problem via In-Memory Instruction Patching:

  1. Stage 1 (CPU Barrier):

    • Breakpoints are placed at the 4 critical kernel functions:
      • exit_notify (CPU 2)
      • kernel_wait4 (CPU 0)
      • __arm64_sys_timer_delete (CPU 1)
      • handle_posix_cpu_timers (CPU 2)
    • As each vCPU reaches its rendezvous point, GDB patches its $pc with the ARM64 self-branch opcode 0x14000000 (b . infinite loop) and resumes execution.
    • Once all 4 vCPUs are pinned at their exact locations, GDB restores the original instructions and hands execution to Stage 2.
  2. Stage 2 (Sequential Orchestration):

    • GDB locks the scheduler (set scheduler-locking on) and steps each vCPU forward sequentially:
      • Step 1 (CPU 2): Advance handle_posix_cpu_timers past unlock_task_sighand().
      • Step 2 (CPU 0): Advance past .

🚀 How to Reproduce

1. Download Target Kernel Source

Download or clone the Android Common Kernel source tree at commit 1bf1aa362e6b9573a310fcd14f35bc875b42ba83:

root@kitploit:~
# Option A: Download tarball directly
curl -LO https://android.googlesource.com/kernel/common/+archive/1bf1aa362e6b9573a310fcd14f35bc875b42ba83.tar.gz
mkdir -p kernel-cve && tar -xzf 1bf1aa362e6b9573a310fcd14f35bc875b42ba83.tar.gz -C kernel-cve
cd kernel-cve

# Option B: Clone repository
git clone https://android.googlesource.com/kernel/common
cd common
git checkout 1bf1aa362e6b9573a310fcd14f35bc875b42ba83

2. Revert the Patch in run_posix_cpu_timers()

Open kernel/time/posix-cpu-timers.c, locate function run_posix_cpu_timers() (around line 1435–1448), and comment out the patch lines:

root@kitploit:~
void run_posix_cpu_timers(void)
{
    struct task_struct *tsk = current;

    lockdep_assert_irqs_disabled();

    /*
     * Ensure that release_task(tsk) can't happen while
     * handle_posix_cpu_timers() is running. Otherwise, a concurrent
     * posix_cpu_timer_del() may fail to lock_task_sighand(tsk) and
     * miss timer->it.cpu.firing != 0.
     */
//  if (tsk->exit_state)
//      return;

3. Disable CONFIG_POSIX_CPU_TIMERS_TASK_WORK

Note: When CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y, CPU timers are executed from task_work context instead of timer IRQ, bypassing this race condition. Therefore, it must be disabled to reproduce the vulnerability.

Because CONFIG_POSIX_CPU_TIMERS_TASK_WORK lacks a prompt string in upstream Kconfig, it defaults to y and cannot be toggled directly in menuconfig. You can expose it as follows:

  1. In kernel/time/Kconfig (around line 56), add a prompt string and change the default:
    root@kitploit:~
    config POSIX_CPU_TIMERS_TASK_WORK
        bool "POSIX CPU timers task work"
        default n
    
  2. Generate default config and disable the option:
    root@kitploit:~
    ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig
    scripts/config --disable POSIX_CPU_TIMERS_TASK_WORK
    ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make olddefconfig
    
  3. Verify that it is disabled in .config:
    root@kitploit:~
    grep POSIX_CPU_TIMERS_TASK_WORK .config
    # Expected output: # CONFIG_POSIX_CPU_TIMERS_TASK_WORK is not set
    

4. Build the Kernel

Compile the ARM64 kernel image:

root@kitploit:~
time ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j$(nproc) Image

5. Compile Userspace PoC

Cross-compile poc.c:

root@kitploit:~
aarch64-linux-gnu-gcc -ggdb3 ./poc.c -o poc

6. Start QEMU with GDB Stub

Launch your QEMU virtual machine with 4 vCPUs (-smp 4) and enable the GDB stub (-s flag, port 1234):

root@kitploit:~
qemu-system-aarch64 \
    -M virt \
    -cpu cortex-a57 \
    -smp 4 \
    -m 2G \
    -kernel arch/arm64/boot/Image \
    -append "console=ttyAMA0 root=/dev/vda oops=panic panic_on_warn=1" \
    ... \
    -s

7. Attach GDB and Run Script

From your host terminal, attach GDB to QEMU and load the orchestration script:

root@kitploit:~
gdb-multiarch vmlinux
pwndbg> target remote :1234
pwndbg> source poc_gdb_script.py
pwndbg> continue

8. Trigger Vulnerability

Inside the QEMU guest shell, run the compiled binary:

root@kitploit:~
./poc

[!TIP] Timing & Troubleshooting:
If the timer fires prematurely before the target thread has reached the zombie state, GDB will log:

root@kitploit:~
[!] ERROR: handle_posix_cpu_timers fired before exit_state == EXIT_ZOMBIE
  • Option 1: Simply re-run ./poc and source script GDB a few times.
  • Option 2: Increase TIMER_FIRE_MS in poc.c (e.g., from #define TIMER_FIRE_MS 10 to 20), recompile poc.c, and run again. This grants the thread extra time to reach exit_notify() and transition into EXIT_ZOMBIE before the timer expires.

9. Demo

https://github.com/user-attachments/assets/11481b5c-25f8-46c3-be3a-7b79a06a4948


📚 References

  • Race Against Time in the Kernel Clockwork by StreyPaws
  • CVE-2025-38352 Root Cause Analysis by Faith
Download Tool
kernel_wait4
tsk->sighand = NULL
  • Step 3 (CPU 1): Advance timer_delete to call release_posix_timer() (freeing sigq).
  • Step 4 (CPU 2): Release scheduler locking to allow CPU 2 to fire the freed timer $\rightarrow$ Crash!