CVE-2026-64560
posix-cpu-timers: Prevenir UAF causado por corrida exec() de não-líder
- Publicado
- 29 de jul. de 2026
- Atualizado
- 8 de set. de 2026
- Atribuindo CNA
- Linux
- Evidência observada
- 10 de ago. de 2026
CVSS primário
nvd · CVSS 3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HBaixo · próximos 30 dias
- Percentil
- 35,5%
- Data do modelo
- 21 de set. de 2026
EPSS é uma estimativa estatística, não uma certeza ou uma medida de impacto. Combine-o com CVSS, status KEV, exposição e seu ambiente.
Resumo
No Linux kernel, a seguinte vulnerabilidade foi resolvida: posix-cpu-timers: Prevenir UAF causado por corrida de exec() de não-líder Wongi e Jungwoo decodificaram e reportaram uma corrida relacionada a exec() de não-líder que pode resultar em um UAF: sys_timer_delete() exec() posix_cpu_timer_del() // Observa o antigo líder 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; // Retorna sem ação if(!sighand) return 0; free_posix_timer(); Isso é "inofensivo" a menos que o temporizador excluído estivesse armado e enfileirado em p->signal porque em exec() um temporizador direcionado a TGID é herdado. Como sys_timer_delete() liberou o objeto de temporizador posix subjacente, run_posix_cpu_timers() ou qualquer operação de adicionar/remover relacionada a timerqueue em outros temporizadores acessará o nó timerqueue do objeto liberado, o que resulta em um UAF. Há um problema semelhante em relação a posix_cpu_timer_set(). Para temporizadores posix regulares, isso apenas retorna transientemente -ESRCH ao espaço do usuário, mas para o caso de uso em do_cpu_nanosleep() é o mesmo UAF, apenas com a diferença de que o k_itimer é alocado na pilha. Além disso, posix_cpu_timer_rearm() falha ao rearmar o temporizador, o que significa que ele para de expirar. Ao debater soluções, Frederic apontou outro problema: posix_cpu_timer_del(tmr) __exit_signal(p) posix_cpu_timers*_exit(p); unhash_task(p); p->sighand = NULL; sh = lock_task_sighand(p) sighand = p->sighand; if (!sighand) return NULL; lock(sighand); if (!sh) WARN_ON_ONCE(timer_queued(tmr)); Em arquiteturas fracamente ordenadas, não é garantido que posix_cpu_timer_del() observará os stores em posix_cpu_timers*_exit() quando p->sighand for observado como NULL, o que significa que o WARN() pode ser um falso positivo. Resolva esses problemas: 1) Alterando o store em __exit_signal() para smp_store_release(). 2) Adicionando um smp_acquire__after_ctrl_dep() no caminho !sighand de lock_task_sighand(). 3) Criando uma função auxiliar para buscar a tarefa e bloquear sighand que não retorna quando sighand == NULL. Em vez disso, ela tenta novamente a busca da tarefa e só desiste se essa falhar. 4) Usando essa auxiliar nas três funções afetadas. #1/#2 garante que o lado do leitor que observa sighand == NULL também observe todos os stores anteriores, ou seja, os stores em posix_cpu_timers*_exit() e os de unhash_task(). #3 garante que a situação de exec() de não-líder descrita acima seja tratada com elegância. Quando a busca da tarefa retorna o antigo líder, mas sighand == NULL, então ela tenta novamente. No caso de exec() de não-líder, a busca subsequente da tarefa observará o novo líder devido a #1/#2. Em cenários normais de exit(), a busca subsequente falha. Quando a busca da tarefa falha, a função também verifica se o temporizador ainda está enfileirado e emite um aviso se for o caso. Infelizmente, não há nada que possa ser feito sobre isso, mas como a tarefa já não está mais visível, o temporizador não deve mais ser acessado. Essa verificação também requer ordenação de memória, que não é fornecida quando a primeira busca falha. Para conseguir isso, a verificação é precedida por um smp_rmb() que faz par com o smp_wmb() em write_seqlock() em __exit_signal(). Isso garante que os stores em posix_cpu_timers*_exit() sejam visíveis. A história do problema de exec() de não-líder remonta aos primeiros dias dos temporizadores de CPU posix, que armazenavam um ponteiro para a tarefa líder do grupo no temporizador. Isso obviamente falha quando um exec() de não-líder troca o líder. O commit e0a70217107e ("posix-cpu-timers: workaround to suppress the problems with mt exec") adicionou uma solução temporária para isso em 2010, que sobrev ---truncado---
Uso responsável
Use informações de vulnerabilidade apenas em sistemas que você possui ou está autorizado a testar. O Kitploit vincula-se a metadados de pesquisa pública e não armazena código de exploração ou cargas maliciosas.