{"id":"DEBIAN-CVE-2026-23198","details":"In the Linux kernel, the following vulnerability has been resolved:  KVM: Don't clobber irqfd routing type when deassigning irqfd  When deassigning a KVM_IRQFD, don't clobber the irqfd's copy of the IRQ's routing entry as doing so breaks kvm_arch_irq_bypass_del_producer() on x86 and arm64, which explicitly look for KVM_IRQ_ROUTING_MSI.  Instead, to handle a concurrent routing update, verify that the irqfd is still active before consuming the routing information.  As evidenced by the x86 and arm64 bugs, and another bug in kvm_arch_update_irqfd_routing() (see below), clobbering the entry type without notifying arch code is surprising and error prone.  As a bonus, checking that the irqfd is active provides a convenient location for documenting _why_ KVM must not consume the routing entry for an irqfd that is in the process of being deassigned: once the irqfd is deleted from the list (which happens *before* the eventfd is detached), it will no longer receive updates via kvm_irq_routing_update(), and so KVM could deliver an event using stale routing information (relative to KVM_SET_GSI_ROUTING returning to userspace).  As an even better bonus, explicitly checking for the irqfd being active fixes a similar bug to the one the clobbering is trying to prevent: if an irqfd is deactivated, and then its routing is changed, kvm_irq_routing_update() won't invoke kvm_arch_update_irqfd_routing() (because the irqfd isn't in the list).  And so if the irqfd is in bypass mode, IRQs will continue to be posted using the old routing information.  As for kvm_arch_irq_bypass_del_producer(), clobbering the routing type results in KVM incorrectly keeping the IRQ in bypass mode, which is especially problematic on AMD as KVM tracks IRQs that are being posted to a vCPU in a list whose lifetime is tied to the irqfd.  Without the help of KASAN to detect use-after-free, the most common sympton on AMD is a NULL pointer deref in amd_iommu_update_ga() due to the memory for irqfd structure being re-allocated and zeroed, resulting in irqfd-\u003eirq_bypass_data being NULL when read by avic_update_iommu_vcpu_affinity():    BUG: kernel NULL pointer dereference, address: 0000000000000018   #PF: supervisor read access in kernel mode   #PF: error_code(0x0000) - not-present page   PGD 40cf2b9067 P4D 40cf2b9067 PUD 408362a067 PMD 0   Oops: Oops: 0000 [#1] SMP   CPU: 6 UID: 0 PID: 40383 Comm: vfio_irq_test   Tainted: G     U  W  O        6.19.0-smp--5dddc257e6b2-irqfd #31 NONE   Tainted: [U]=USER, [W]=WARN, [O]=OOT_MODULE   Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 34.78.2-0 09/05/2025   RIP: 0010:amd_iommu_update_ga+0x19/0xe0   Call Trace:    \u003cTASK\u003e    avic_update_iommu_vcpu_affinity+0x3d/0x90 [kvm_amd]    __avic_vcpu_load+0xf4/0x130 [kvm_amd]    kvm_arch_vcpu_load+0x89/0x210 [kvm]    vcpu_load+0x30/0x40 [kvm]    kvm_arch_vcpu_ioctl_run+0x45/0x620 [kvm]    kvm_vcpu_ioctl+0x571/0x6a0 [kvm]    __se_sys_ioctl+0x6d/0xb0    do_syscall_64+0x6f/0x9d0    entry_SYSCALL_64_after_hwframe+0x4b/0x53   RIP: 0033:0x46893b     \u003c/TASK\u003e   ---[ end trace 0000000000000000 ]---  If AVIC is inhibited when the irfd is deassigned, the bug will manifest as list corruption, e.g. on the next irqfd assignment.    list_add corruption. next-\u003eprev should be prev (ffff8d474d5cd588),                        but was 0000000000000000. (next=ffff8d8658f86530).   ------------[ cut here ]------------   kernel BUG at lib/list_debug.c:31!   Oops: invalid opcode: 0000 [#1] SMP   CPU: 128 UID: 0 PID: 80818 Comm: vfio_irq_test   Tainted: G     U  W  O        6.19.0-smp--f19dc4d680ba-irqfd #28 NONE   Tainted: [U]=USER, [W]=WARN, [O]=OOT_MODULE   Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 34.78.2-0 09/05/2025   RIP: 0010:__list_add_valid_or_report+0x97/0xc0   Call Trace:    \u003cTASK\u003e    avic_pi_update_irte+0x28e/0x2b0 [kvm_amd]    kvm_pi_update_irte+0xbf/0x190 [kvm]    kvm_arch_irq_bypass_add_producer+0x72/0x90 [kvm]    irq_bypass_register_consumer+0xcd/0x170 [irqbypa ---truncated---","modified":"2026-09-29T13:03:45.824603624Z","published":"2026-02-14T17:15:57.640Z","upstream":["CVE-2026-23198"],"references":[{"type":"ADVISORY","url":"https://security-tracker.debian.org/tracker/CVE-2026-23198"}],"affected":[{"package":{"name":"linux","ecosystem":"Debian:12","purl":"pkg:deb/debian/linux?arch=source&distro=bookworm"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.1.164-1"}]}],"versions":["6.1.106-1","6.1.106-2","6.1.106-3","6.1.112-1","6.1.115-1","6.1.119-1","6.1.123-1","6.1.124-1","6.1.128-1","6.1.129-1","6.1.133-1","6.1.135-1","6.1.137-1","6.1.139-1","6.1.140-1","6.1.147-1","6.1.148-1","6.1.153-1","6.1.158-1","6.1.159-1","6.1.162-1","6.1.27-1","6.1.37-1","6.1.38-1","6.1.38-2","6.1.38-2~bpo11+1","6.1.38-3","6.1.38-4","6.1.38-4~bpo11+1","6.1.52-1","6.1.55-1","6.1.55-1~bpo11+1","6.1.64-1","6.1.66-1","6.1.67-1","6.1.69-1","6.1.69-1~bpo11+1","6.1.76-1","6.1.76-1~bpo11+1","6.1.82-1","6.1.85-1","6.1.90-1","6.1.90-1~bpo11+1","6.1.94-1","6.1.94-1~bpo11+1","6.1.98-1","6.1.99-1"],"ecosystem_specific":{"urgency":"not yet assigned"},"database_specific":{"source":"https://storage.googleapis.com/osv-test-debian-osv/debian-cve-osv/DEBIAN-CVE-2026-23198.json"}},{"package":{"name":"linux","ecosystem":"Debian:13","purl":"pkg:deb/debian/linux?arch=source&distro=trixie"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.12.73-1"}]}],"versions":["6.12.38-1","6.12.41-1","6.12.43-1","6.12.43-1~bpo12+1","6.12.48-1","6.12.57-1","6.12.57-1~bpo12+1","6.12.63-1","6.12.63-1~bpo12+1","6.12.69-1","6.12.69-1~bpo12+1","6.12.73-1~bpo12+1"],"ecosystem_specific":{"urgency":"not yet assigned"},"database_specific":{"source":"https://storage.googleapis.com/osv-test-debian-osv/debian-cve-osv/DEBIAN-CVE-2026-23198.json"}},{"package":{"name":"linux","ecosystem":"Debian:14","purl":"pkg:deb/debian/linux?arch=source&distro=forky"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.18.10-1"}]}],"versions":["6.12.100-1","6.12.101-1","6.12.105-1","6.12.107-1","6.12.111-1","6.12.38-1","6.12.41-1","6.12.43-1","6.12.43-1~bpo12+1","6.12.48-1","6.12.57-1","6.12.57-1~bpo12+1","6.12.63-1","6.12.63-1~bpo12+1","6.12.69-1","6.12.69-1~bpo12+1","6.12.73-1","6.12.73-1~bpo12+1","6.12.74-1","6.12.74-2","6.12.74-2~bpo12+1","6.12.85-1","6.12.85-1~bpo12+1","6.12.86-1","6.12.86-1~bpo12+1","6.12.88-1","6.12.88-1~bpo12+1","6.12.90-1","6.12.90-1~bpo12+1","6.12.90-2","6.12.90-2~bpo12+1","6.12.94-1","6.12.94-1~bpo12+1","6.12.95-1","6.12.95-1~bpo12+1","6.12.96-1","6.13.10-1~exp1","6.13.11-1~exp1","6.13.2-1~exp1","6.13.3-1~exp1","6.13.4-1~exp1","6.13.5-1~exp1","6.13.6-1~exp1","6.13.7-1~exp1","6.13.8-1~exp1","6.13.9-1~exp1","6.13~rc6-1~exp1","6.13~rc7-1~exp1","6.14.3-1~exp1","6.14.5-1~exp1","6.14.6-1~exp1","6.15-1~exp1","6.15.1-1~exp1","6.15.2-1~exp1","6.15.3-1~exp1","6.15.4-1~exp1","6.15.5-1~exp1","6.15.6-1~exp1","6.15~rc7-1~exp1","6.16-1~exp1","6.16.1-1~exp1","6.16.10-1","6.16.11-1","6.16.12-1","6.16.12-1~bpo13+1","6.16.12-2","6.16.3-1","6.16.3-1~bpo13+1","6.16.5-1","6.16.6-1","6.16.7-1","6.16.8-1","6.16.9-1","6.16~rc7-1~exp1","6.17.10-1","6.17.11-1","6.17.12-1","6.17.13-1","6.17.13-1~bpo13+1","6.17.2-1~exp1","6.17.5-1~exp1","6.17.6-1","6.17.7-1","6.17.7-2","6.17.8-1","6.17.8-1~bpo13+1","6.17.9-1","6.18.1-1~exp1","6.18.2-1~exp1","6.18.3-1","6.18.5-1","6.18.5-1~bpo13+1","6.18.8-1","6.18.9-1","6.18.9-1~bpo13+1","6.18~rc4-1~exp1","6.18~rc4-1~exp2","6.18~rc5-1~exp1","6.18~rc6-1~exp1","6.18~rc7-1~exp1"],"ecosystem_specific":{"urgency":"not yet assigned"},"database_specific":{"source":"https://storage.googleapis.com/osv-test-debian-osv/debian-cve-osv/DEBIAN-CVE-2026-23198.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H"}]}