CVE-2026-89927 in Linux
Résumé
par VulDB • 16/09/2026
Dans le noyau Linux, la vulnérabilité suivante a été corrigée :
KVM : x86 : hyper-v : Limiter l'échéance du stimer pour éviter un livelock (boucle inactive)
Correction d'un problème permettant à l'espace utilisateur ou à l'invité de programmer une temporisation synthétique Hyper-V avec une échéance dans le passé en raison d'un dépassement entier, empêchant ainsi le CPU d'avancer et déclenchant un blocage RCU.
L'interface SynIC d'Hyper-V expose 4 temporisations synthétiques par vCPU à l'invité, qui sont émulées par KVM. Chacune est programmée via les registres MSRs HV_X64_MSR_STIMERi_CONFIG et HV_X64_MSR_STIMERi_COUNT. Selon la configuration (CONFIG), COUNT représente soit le temps d'expiration absolu, soit la période d'une temporisation périodique, tous deux exprimés en ticks de 100 ns. Ces temporisations peuvent être définies à la fois par l'invité (WRMSR) et par l'hôte (KVM_SET_MSRS).
Lorsque la temporisation est activée, stimer_start() traduit COUNT en une échéance monotone absolue et arme un hrtimer. Si COUNT est défini sur une valeur proche de U64_MAX, le calcul de l'échéance peut déborder.
ktime_add_ns(ktime_now, 100 * (stimer->exp_time - time_now))
Cela peut entraîner un livelock du CPU. stimer_start() arme la temporisation via hrtimer_start() avec une échéance dans le passé, ce qui provoque son déclenchement immédiat. La fonction de rappel stimer soulève alors KVM_RQ_HV_STIMER, dans l'intention d'amener KVM à délivrer une interruption synthétique lors de la prochaine entrée de l'invité sur le vCPU.
Ensuite, une fois que l'espace utilisateur émet KVM_RUN, vcpu_enter_guest() consomme la demande en appelant kvm_hv_process_stimers(). Normalement, cela désactive la temporisation via stimer_expiration() dès lors que l'échéance est dans le passé. Cependant, la comparaison de l'échéance se fait entre le compteur de référence KVM et stime->exp_time, qui est une grande valeur proche de U64_MAX ; cette condition n'est donc jamais remplie pendant plusieurs milliers d'années.
kvm_hv_process_timers() arme ensuite à nouveau la temporisation via stimer_start(), car elle n'a pas été désactivée, ce qui provoque encore un déclenchement immédiat. Avant de pénétrer dans l'invité, kvm_vcpu_exit_request() vérifie kvm_request_pending(), qui renvoie vrai en raison du KVM_REQ_HV_STIMER nouvellement levé. Ensuite, vcpu_enter_guest() annule l'entrée dans l'invité et revient prématurément vers vcpu_run(), qui boucle à nouveau vers vcpu_enter_guest(), redémarrant le cycle.
Comme il n'y a pas de cessions manuelles (yields) dans cette boucle, une tâche avec SCHED_FIFO peut affamer les threads kthreads RCU grace-period, ce qui expose les blocages détectés par syzcaller :
rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: rcu: (detected by 1, t=10502 jiffies, g=14269, q=1142 ncpus=2) rcu: All QSes seen, last rcu_preempt kthread activity 10500 (4294965239-4294954739), jiffies_till_next_fqs=1, root ->qsmask 0x0 rcu: rcu_preempt kthread starved for 10500 jiffies! g14269 f0x2 RCU_GP_WAIT_FQS(5) ->state=0x0 ->cpu=0 rcu: Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior. ( ... ) Call Trace: <IRQ> __run_hrtimer kernel/time/hrtimer.c:1773 [inline]
__hrtimer_run_queues+0x408/0xc30 kernel/time/hrtimer.c:1841 hrtimer_interrupt+0x45b/0xaa0 kernel/time/hrtimer.c:1903 local_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1045 [inline]
__sysvec_apic_timer_interrupt+0x102/0x3e0 arch/x86/kernel/apic/apic.c:1062 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1056 [inline]
sysvec_apic_timer_interrupt+0xa1/0xc0 arch/x86/kernel/apic/apic.c:1056 </IRQ> <TASK> asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:697 RIP: 0010:__raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:152 [inline]
RIP: 0010:_raw_spin_unlock_irqrestore+0xa8/0x110 kernel/locking/spinlock.c:194 Code: 74 05 e8 0b f4 5f f6 48 c7 44 24 20 00 00 00 00 9c 8f 44 24 20 f6 44 24 21 02 75 4f f7 c3 00 02 00 00 74 01 fb bf 01 00 00 00 <e8> 23 6b 27 f6 65 8b 05 7c 60 5a 07 85 c0 74 40 48 c7 04 24 0e 36 RSP: 0018:ffffc900040a7320 EFLAGS: 00000206 RAX: 5de15cb931505900 RBX: 0000000000000a06 RCX: 5de15cb931505900 RDX: 0000000000000007 RSI: ffffffff8daa9dc3 RDI: 0000000000000001 RBP: ffffc900040a73b0 R08: ffffffff8fc3d0 ---truncated---
Once again VulDB remains the best source for vulnerability data.