CVE-2026-64560
posix-cpu-timers : Prévenir l'UAF causé par la course exec() d'un non-leader
- Publié
- 29 juil. 2026
- Mise à jour
- 8 sept. 2026
- Attribution de CNA
- Linux
- Preuve observée
- 10 août 2026
CVSS primaire
nvd · CVSS 3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HFaible · 30 prochains jours
- Percentile
- 35,5 %
- Date du modèle
- 21 sept. 2026
EPSS est une estimation statistique, et non une certitude ou une mesure d'impact. Combinez-le avec CVSS, le statut KEV, l'exposition et votre environnement.
Résumé
Dans le noyau Linux, la vulnérabilité suivante a été résolue : posix-cpu-timers : Empêcher l'UAF causé par une course liée à exec() non-leader Wongi et Jungwoo ont décodé et signalé une course liée à exec() non-leader qui peut entraîner une UAF : ``` sys_timer_delete() exec() de_thread() switch_leader(); release_task(old_leader) __exit_signal(old_leader) sighand = lock(old_leader, sighand); posix_cpu_timers*_exit(); unhash_task(old_leader); old_leader->sighand = NULL; unlock(sighand); posix_cpu_timer_del() // Observe l'ancien leader p = pid_task(pid, pid_type); sighand = lock_task_sighand(p) sh = lock(p, sighand) (p->sighand == NULL) unlock(sh) return NULL; // Retourne sans action if(!sighand) return 0; free_posix_timer(); ``` C'est « inoffensif » sauf si le minuteur supprimé était armé et mis en file d'attente dans p->signal car lors d'un exec(), un minuteur ciblé par TGID est hérité. Comme sys_timer_delete() a libéré l'objet minuteur posix sous-jacent, run_posix_cpu_timers() ou toute opération d'ajout/suppression liée à timerqueue sur d'autres minuteurs accédera au nœud timerqueue de l'objet libéré, ce qui entraîne une UAF. Il existe un problème similaire avec posix_cpu_timer_set(). Pour les minuteurs posix classiques, cela retourne simplement -ESRCH à l'espace utilisateur de manière transitoire, mais pour le cas d'utilisation dans do_cpu_nanosleep(), c'est la même UAF, sauf que le k_itimer est alloué sur la pile. De plus, posix_cpu_timer_rearm() ne réarme pas le minuteur, ce qui signifie qu'il cesse d'expirer. En débattant des solutions, Frederic a souligné un autre problème : ``` posix_cpu_timer_del(tmr) sh = lock_task_sighand(p) sighand = p->sighand; if (!sighand) return NULL; lock(sighand); if (!sh) WARN_ON_ONCE(timer_queued(tmr)); __exit_signal(p) posix_cpu_timers*_exit(p); unhash_task(p); p->sighand = NULL; ``` Sur les architectures à ordonnancement faible, il n'est pas garanti que posix_cpu_timer_del() observe les écritures dans posix_cpu_timers*_exit() lorsque p->sighand est observé comme NULL, ce qui signifie que le WARN() peut être un faux positif. Résolvez ces problèmes en : 1) Changeant l'écriture dans __exit_signal() en smp_store_release(). 2) Ajoutant un smp_acquire__after_ctrl_dep() dans le chemin !sighand de lock_task_sighand(). 3) Créant une fonction d'assistance pour rechercher la tâche et verrouiller sighand qui ne retourne pas lorsque sighand == NULL. Au lieu de cela, elle réessaie la recherche de tâche et seulement si cela échoue, elle abandonne. 4) Utilisant cette assistance dans les trois fonctions affectées. #1/#2 garantit que le côté lecteur qui observe sighand == NULL observe également toutes les écritures précédentes, c'est-à-dire les écritures dans posix_cpu_timers*_exit() et celles dans unhash_task(). #3 garantit que la situation exec() non-leader décrite ci-dessus est gérée avec élégance. Lorsque la recherche de tâche retourne l'ancien leader, mais que sighand == NULL, elle réessaie. Dans le cas exec() non-leader, la recherche de tâche suivante observera le nouveau leader grâce à #1/#2. Dans les scénarios exit() normaux, la recherche suivante échoue. Lorsque la recherche de tâche échoue, la fonction vérifie également si le minuteur est toujours en file d'attente et émet un avertissement si c'est le cas. Malheureusement, il n'y a rien qui puisse être fait à ce sujet, mais comme la tâche n'est déjà plus visible, le minuteur ne devrait plus être accédé. Cette vérification nécessite également un ordonnancement mémoire, qui n'est pas fourni lorsque la première recherche échoue. Pour y parvenir, la vérification est précédée d'un smp_rmb() qui s'associe avec le smp_wmb() dans write_seqlock() dans __exit_signal(). Cela garantit que les écritures dans posix_cpu_timers*_exit() sont visibles. L'historique du problème exec() non-leader remonte aux premiers jours des minuteurs CPU posix, qui stockaient un pointeur vers la tâche leader du groupe dans le minuteur. Cela échoue évidemment lorsqu'un exec() non-leader change le leader. Le commit e0a70217107e (« posix-cpu-timers: workaround to suppress the problems with mt exec ») a ajouté une solution temporaire pour cela en 2010 qui surv ---tronqué---
Utilisation responsable
Utilisez les informations de vulnérabilité uniquement sur les systèmes que vous possédez ou que vous êtes autorisé à tester. Kitploit renvoie aux métadonnées de la recherche publique et ne stocke pas de code d'exploitation ni de charges utiles malveillantes.