← back
CVE-2025-38352highunder attackCWE-367

posix-cpu-timers: fix race between handle_posix_cpu_timers() and posix_cpu_timer_del()

76Vexday Risk Score

Prioritize patching. It under exploitation confirmed by CISA and has a public proof of concept.

ssvc Actcvss 7.8epss 1.3%
from disclosure to weapon152 days
Published on NVDJul 22
1st PoC+152d
CISA KEV+44d
exploitation probability
1.3%top 33% of all CVEs
observed exploitation
yesCISA + VulnCheck
8 public exploit(s)
Action required by CISAfederal deadline: 2025-09-25

Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.

Summary

Race condition (CWE-362) no subsistema de temporizadores POSIX CPU do kernel Linux que pode degenerar em use-after-free (CWE-416) quando um processo em finalização, não autorreaping (ex.: sob ptrace ou aguardado por wait() controlado), é reaped pelo pai/debugger exatamente enquanto handle_posix_cpu_timers() ainda processa seus timers a partir de contexto IRQ. Importa porque há PoC pública funcional, exploração ativa registrada no catálogo KEV da CISA e o relato original veio do Google (Benoît Sevens), em contexto consistente com kernels Android da linha 5.10.x — mas a exploração exige ganhar uma corrida de timing fina (AC:H), não é trivial de disparar por acaso.

Technical detail

O código vive em kernel/time/posix-cpu-timers.c, nas funções run_posix_cpu_timers()/handle_posix_cpu_timers() e posix_cpu_timer_del(). O bug foi introduzido pelo commit 0bdd2ed4138e ('sched: run_posix_cpu_timers: Don't check ->exit_state, use lock_task_sighand()'), que removeu uma checagem de exit_state e passou a confiar apenas em lock_task_sighand() para serializar acesso à task.

A janela de corrida existe porque uma task exiting não-autorreaping pode já ter passado por exit_notify() e ainda assim ser chamada via handle_posix_cpu_timers() a partir de uma interrupção de timer. Depois que essa função executa unlock_task_sighand(), existe um intervalo em que o pai ou um debugger pode reap a task (release_task()) antes que o processamento do timer termine. Se, nesse intervalo, uma chamada concorrente a posix_cpu_timer_del() tentar remover o mesmo cpu timer, as funções auxiliares cpu_timer_task_rcu() e/ou lock_task_sighand() falham em localizar a task já liberada — e por isso não detectam que timer->it.cpu.firing != 0, ou seja, que o timer ainda está em uso por handle_posix_cpu_timers(). O delete prossegue como se fosse seguro, e a estrutura associada ao timer/sighand pode ser acessada depois de liberada.

A correção adiciona uma checagem explícita de tsk->exit_state no início de run_posix_cpu_timers(): se a task já está em processo de saída, a função retorna sem prosseguir, eliminando a janela em que release_task() poderia correr concorrentemente com o processamento do timer. O próprio patch observa que essa correção não é necessária quando CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y, porque nesse modo exit_task_work() é executado antes de exit_notify(), o que já impede a ordem de eventos que gera a corrida — mas o autor manteve a checagem como defesa em profundidade, já que task_work_add() falharia de qualquer forma nesse caso.

Researched and written with AI from the vendor advisory and public analysis, with the sources above. Always confirm the fixed version in the official advisory before acting.
In the Linux kernel, the following vulnerability has been resolved: posix-cpu-timers: fix race between handle_posix_cpu_timers() and posix_cpu_timer_del() If an exiting non-autoreaping task has already passed exit_notify() and calls handle_posix_cpu_timers() from IRQ, it can be reaped by its parent or debugger right after unlock_task_sighand(). If a concurrent posix_cpu_timer_del() runs at that moment, it won't be able to detect timer->it.cpu.firing != 0: cpu_timer_task_rcu() and/or lock_task_sighand() will fail. Add the tsk->exit_state check into run_posix_cpu_timers() to fix this. This fix is not needed if CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y, because exit_task_work() is called before exit_notify(). But the check still makes sense, task_work_add(&tsk->posix_cputimers_work.work) will fail anyway in this case.
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Affected products
Linux · Linux
⚠ Public resources, to assess the exposure of systems you control or are authorized to test. Test only with authorization.