CVE-2026-23198
Fecha de publicación:
14/02/2026
*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
KVM: Don&#39;t clobber irqfd routing type when deassigning irqfd<br />
<br />
When deassigning a KVM_IRQFD, don&#39;t clobber the irqfd&#39;s copy of the IRQ&#39;s<br />
routing entry as doing so breaks kvm_arch_irq_bypass_del_producer() on x86<br />
and arm64, which explicitly look for KVM_IRQ_ROUTING_MSI. Instead, to<br />
handle a concurrent routing update, verify that the irqfd is still active<br />
before consuming the routing information. As evidenced by the x86 and<br />
arm64 bugs, and another bug in kvm_arch_update_irqfd_routing() (see below),<br />
clobbering the entry type without notifying arch code is surprising and<br />
error prone.<br />
<br />
As a bonus, checking that the irqfd is active provides a convenient<br />
location for documenting _why_ KVM must not consume the routing entry for<br />
an irqfd that is in the process of being deassigned: once the irqfd is<br />
deleted from the list (which happens *before* the eventfd is detached), it<br />
will no longer receive updates via kvm_irq_routing_update(), and so KVM<br />
could deliver an event using stale routing information (relative to<br />
KVM_SET_GSI_ROUTING returning to userspace).<br />
<br />
As an even better bonus, explicitly checking for the irqfd being active<br />
fixes a similar bug to the one the clobbering is trying to prevent: if an<br />
irqfd is deactivated, and then its routing is changed,<br />
kvm_irq_routing_update() won&#39;t invoke kvm_arch_update_irqfd_routing()<br />
(because the irqfd isn&#39;t in the list). And so if the irqfd is in bypass<br />
mode, IRQs will continue to be posted using the old routing information.<br />
<br />
As for kvm_arch_irq_bypass_del_producer(), clobbering the routing type<br />
results in KVM incorrectly keeping the IRQ in bypass mode, which is<br />
especially problematic on AMD as KVM tracks IRQs that are being posted to<br />
a vCPU in a list whose lifetime is tied to the irqfd.<br />
<br />
Without the help of KASAN to detect use-after-free, the most common<br />
sympton on AMD is a NULL pointer deref in amd_iommu_update_ga() due to<br />
the memory for irqfd structure being re-allocated and zeroed, resulting<br />
in irqfd->irq_bypass_data being NULL when read by<br />
avic_update_iommu_vcpu_affinity():<br />
<br />
BUG: kernel NULL pointer dereference, address: 0000000000000018<br />
#PF: supervisor read access in kernel mode<br />
#PF: error_code(0x0000) - not-present page<br />
PGD 40cf2b9067 P4D 40cf2b9067 PUD 408362a067 PMD 0<br />
Oops: Oops: 0000 [#1] SMP<br />
CPU: 6 UID: 0 PID: 40383 Comm: vfio_irq_test<br />
Tainted: G U W O 6.19.0-smp--5dddc257e6b2-irqfd #31 NONE<br />
Tainted: [U]=USER, [W]=WARN, [O]=OOT_MODULE<br />
Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 34.78.2-0 09/05/2025<br />
RIP: 0010:amd_iommu_update_ga+0x19/0xe0<br />
Call Trace:<br />
<br />
avic_update_iommu_vcpu_affinity+0x3d/0x90 [kvm_amd]<br />
__avic_vcpu_load+0xf4/0x130 [kvm_amd]<br />
kvm_arch_vcpu_load+0x89/0x210 [kvm]<br />
vcpu_load+0x30/0x40 [kvm]<br />
kvm_arch_vcpu_ioctl_run+0x45/0x620 [kvm]<br />
kvm_vcpu_ioctl+0x571/0x6a0 [kvm]<br />
__se_sys_ioctl+0x6d/0xb0<br />
do_syscall_64+0x6f/0x9d0<br />
entry_SYSCALL_64_after_hwframe+0x4b/0x53<br />
RIP: 0033:0x46893b<br />
<br />
---[ end trace 0000000000000000 ]---<br />
<br />
If AVIC is inhibited when the irfd is deassigned, the bug will manifest as<br />
list corruption, e.g. on the next irqfd assignment.<br />
<br />
list_add corruption. next->prev should be prev (ffff8d474d5cd588),<br />
but was 0000000000000000. (next=ffff8d8658f86530).<br />
------------[ cut here ]------------<br />
kernel BUG at lib/list_debug.c:31!<br />
Oops: invalid opcode: 0000 [#1] SMP<br />
CPU: 128 UID: 0 PID: 80818 Comm: vfio_irq_test<br />
Tainted: G U W O 6.19.0-smp--f19dc4d680ba-irqfd #28 NONE<br />
Tainted: [U]=USER, [W]=WARN, [O]=OOT_MODULE<br />
Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 34.78.2-0 09/05/2025<br />
RIP: 0010:__list_add_valid_or_report+0x97/0xc0<br />
Call Trace:<br />
<br />
avic_pi_update_irte+0x28e/0x2b0 [kvm_amd]<br />
kvm_pi_update_irte+0xbf/0x190 [kvm]<br />
kvm_arch_irq_bypass_add_producer+0x72/0x90 [kvm]<br />
irq_bypass_register_consumer+0xcd/0x170 [irqbypa<br />
---truncated---
Gravedad: Pendiente de análisis
Última modificación:
14/02/2026