Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [PATCH v2] KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning
@ 2026-06-25 21:10 syzbot
  2026-06-25 21:20 ` sashiko-bot
  2026-06-25 22:34 ` Aleksandr Nogikh
  0 siblings, 2 replies; 4+ messages in thread
From: syzbot @ 2026-06-25 21:10 UTC (permalink / raw)
  To: syzkaller-bugs, Borislav Petkov, Dave Hansen, kvm, Ingo Molnar,
	Paolo Bonzini, Sean Christopherson, Thomas Gleixner, x86
  Cc: hpa, linux-kernel, syzbot

From: Alexander Potapenko <glider@google.com>

A warning can be triggered in kvm_check_and_inject_events() when an
interrupt disappears between the time it is checked via
kvm_cpu_has_injectable_intr() and the time it is fetched via
kvm_cpu_get_interrupt(). This occurs because the warning incorrectly
assumes that if an interrupt is injectable, fetching it must always return
a valid interrupt vector (i.e., not -1).

However, this assumption is broken by level-triggered interrupts in the
in-kernel PIC that are deasserted concurrently by another thread. For
example, if a misconfigured PIT or a PCI device asserts and then
immediately deasserts a level-triggered interrupt, the vCPU thread might
see the pending interrupt during the check but find it gone during the
fetch, resulting in kvm_cpu_get_interrupt() returning -1.

The warning manifests as follows:

------------[ cut here ]------------
irq == -1
WARNING: arch/x86/kvm/x86.c:10860 at kvm_check_and_inject_events
arch/x86/kvm/x86.c:10860 [inline]
WARNING: arch/x86/kvm/x86.c:10860 at vcpu_enter_guest
arch/x86/kvm/x86.c:11356 [inline]
WARNING: arch/x86/kvm/x86.c:10860 at vcpu_run+0x57ec/0x7950
arch/x86/kvm/x86.c:11770
RIP: 0010:kvm_check_and_inject_events arch/x86/kvm/x86.c:10860 [inline]
RIP: 0010:vcpu_enter_guest arch/x86/kvm/x86.c:11356 [inline]
RIP: 0010:vcpu_run+0x57ec/0x7950 arch/x86/kvm/x86.c:11770
Call Trace:
 <TASK>
 kvm_arch_vcpu_ioctl_run+0x1193/0x2070 arch/x86/kvm/x86.c:12125
 kvm_vcpu_ioctl+0xa61/0xfd0 virt/kvm/kvm_main.c:4470
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
 </TASK>

Since this is a legitimate Time-Of-Check to Time-Of-Use (TOCTOU) race
condition for the in-kernel PIC, WARN_ON_ONCE() must not be used for this
case. Update the warning to exempt the in-kernel PIC, while preserving it
for other interrupt sources (e.g. APIC) as they are not expected to exhibit
this behavior.

Fixes: bf672720e83c ("KVM: x86: check the kvm_cpu_get_interrupt result before using it")
Assisted-by: Gemini:gemini-3.1-pro-preview Gemini:gemini-3-flash-preview syzbot
Reported-by: syzbot+dd769db18693736eee89@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=dd769db18693736eee89
Link: https://syzkaller.appspot.com/ai_job?id=0b59ccd5-8820-460d-84d3-94df6307bd6a
Signed-off-by: Alexander Potapenko <glider@google.com>

---
v2:
- Restrict the warning exemption to the in-kernel PIC case.
- Remove the pr_err_ratelimited() logging.
- Preserve the WARN_ON_ONCE() for non-PIC interrupt sources.

v1:
https://lore.kernel.org/all/345e9d6c-d7d9-4bab-adb3-d6a7bd27599f@mail.kernel.org/T/
---
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0550359ed..f1681aa9f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10857,7 +10857,9 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
 		if (r) {
 			int irq = kvm_cpu_get_interrupt(vcpu);
 
-			if (!WARN_ON_ONCE(irq == -1)) {
+			WARN_ON_ONCE(irq == -1 && !pic_in_kernel(vcpu->kvm));
+
+			if (irq != -1) {
 				kvm_queue_interrupt(vcpu, irq, false);
 				kvm_x86_call(inject_irq)(vcpu, false);
 				WARN_ON(kvm_x86_call(interrupt_allowed)(vcpu, true) < 0);


base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
-- 
See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at syzkaller@googlegroups.com.

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning
  2026-06-25 21:10 [PATCH v2] KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning syzbot
@ 2026-06-25 21:20 ` sashiko-bot
  2026-06-25 22:34 ` Aleksandr Nogikh
  1 sibling, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-06-25 21:20 UTC (permalink / raw)
  To: syzbot; +Cc: kvm

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] The `!pic_in_kernel(vcpu->kvm)` check inadvertently suppresses the warning for APIC bugs in the default full-irqchip mode, contradicting the commit's intent.

Pre-existing issues:
- [High] A malicious guest can still trigger the `WARN_ON_ONCE` in `kvm_check_and_inject_events` when KVM is configured with a split irqchip and Xen emulation is enabled.
--

commit a01ce83aaf4bff44e757aa3ac163f97e316b3056
Author: Alexander Potapenko <glider@google.com>

KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning

This commit addresses a time-of-check to time-of-use race condition in the
in-kernel PIC that triggers a kernel warning when an interrupt disappears
between check and fetch. It modifies kvm_check_and_inject_events() to exempt
the in-kernel PIC from this warning. The intent is to preserve the warning
for other interrupt sources like the APIC.

Link: https://syzkaller.appspot.com/ai_job?id=0b59ccd5-8820-460d-84d3-94df6307bd6a

> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
[ ... ]
> @@ -10857,7 +10857,9 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
>  		if (r) {
>  			int irq = kvm_cpu_get_interrupt(vcpu);
>  
> -			if (!WARN_ON_ONCE(irq == -1)) {
> +			WARN_ON_ONCE(irq == -1 && !pic_in_kernel(vcpu->kvm));

[Severity: Medium]
Does this inadvertently suppress the warning for APIC bugs in the default
full-irqchip mode?

Since pic_in_kernel() evaluates to true when the in-kernel PIC is present,
checking !pic_in_kernel() disables the warning entirely for all interrupt
sources in that configuration. This appears to contradict the commit message
intent of preserving the warning for other sources like the APIC.

[Severity: High]
This is a pre-existing issue, but can a malicious guest still trigger this
warning when KVM is configured with a split irqchip and Xen emulation is
enabled?

If a guest concurrently toggles its evtchn_upcall_pending flag in memory
while the host executes the event injection loop, it seems this path is
directly reachable. Because pic_in_kernel() is false for a split irqchip,
the warning could still fire and potentially lead to a host panic if
panic_on_warn is enabled.

> +
> +			if (irq != -1) {
>  				kvm_queue_interrupt(vcpu, irq, false);
>  				kvm_x86_call(inject_irq)(vcpu, false);
>  				WARN_ON(kvm_x86_call(interrupt_allowed)(vcpu, true) < 0);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/86078441-92eb-4461-b823-7d3539ac5859@mail.kernel.org?part=1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning
  2026-06-25 21:10 [PATCH v2] KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning syzbot
  2026-06-25 21:20 ` sashiko-bot
@ 2026-06-25 22:34 ` Aleksandr Nogikh
  2026-06-25 22:38   ` Sean Christopherson
  1 sibling, 1 reply; 4+ messages in thread
From: Aleksandr Nogikh @ 2026-06-25 22:34 UTC (permalink / raw)
  To: syzbot
  Cc: syzkaller-bugs, Borislav Petkov, Dave Hansen, kvm, Ingo Molnar,
	Paolo Bonzini, Sean Christopherson, Thomas Gleixner, x86, hpa,
	linux-kernel, syzbot

On Thu, Jun 25, 2026 at 11:10 PM 'syzbot' via syzkaller-bugs
<syzkaller-bugs@googlegroups.com> wrote:
>
> From: Alexander Potapenko <glider@google.com>
>
> A warning can be triggered in kvm_check_and_inject_events() when an
> interrupt disappears between the time it is checked via
> kvm_cpu_has_injectable_intr() and the time it is fetched via
> kvm_cpu_get_interrupt(). This occurs because the warning incorrectly
> assumes that if an interrupt is injectable, fetching it must always return
> a valid interrupt vector (i.e., not -1).
>
> However, this assumption is broken by level-triggered interrupts in the
> in-kernel PIC that are deasserted concurrently by another thread. For
> example, if a misconfigured PIT or a PCI device asserts and then
> immediately deasserts a level-triggered interrupt, the vCPU thread might
> see the pending interrupt during the check but find it gone during the
> fetch, resulting in kvm_cpu_get_interrupt() returning -1.
>
> The warning manifests as follows:
>
> ------------[ cut here ]------------
> irq == -1
> WARNING: arch/x86/kvm/x86.c:10860 at kvm_check_and_inject_events
> arch/x86/kvm/x86.c:10860 [inline]
> WARNING: arch/x86/kvm/x86.c:10860 at vcpu_enter_guest
> arch/x86/kvm/x86.c:11356 [inline]
> WARNING: arch/x86/kvm/x86.c:10860 at vcpu_run+0x57ec/0x7950
> arch/x86/kvm/x86.c:11770
> RIP: 0010:kvm_check_and_inject_events arch/x86/kvm/x86.c:10860 [inline]
> RIP: 0010:vcpu_enter_guest arch/x86/kvm/x86.c:11356 [inline]
> RIP: 0010:vcpu_run+0x57ec/0x7950 arch/x86/kvm/x86.c:11770
> Call Trace:
>  <TASK>
>  kvm_arch_vcpu_ioctl_run+0x1193/0x2070 arch/x86/kvm/x86.c:12125
>  kvm_vcpu_ioctl+0xa61/0xfd0 virt/kvm/kvm_main.c:4470
>  vfs_ioctl fs/ioctl.c:51 [inline]
>  __do_sys_ioctl fs/ioctl.c:597 [inline]
>  __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>  do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>  </TASK>
>
> Since this is a legitimate Time-Of-Check to Time-Of-Use (TOCTOU) race
> condition for the in-kernel PIC, WARN_ON_ONCE() must not be used for this
> case. Update the warning to exempt the in-kernel PIC, while preserving it
> for other interrupt sources (e.g. APIC) as they are not expected to exhibit
> this behavior.
>
> Fixes: bf672720e83c ("KVM: x86: check the kvm_cpu_get_interrupt result before using it")
> Assisted-by: Gemini:gemini-3.1-pro-preview Gemini:gemini-3-flash-preview syzbot
> Reported-by: syzbot+dd769db18693736eee89@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=dd769db18693736eee89
> Link: https://syzkaller.appspot.com/ai_job?id=0b59ccd5-8820-460d-84d3-94df6307bd6a
> Signed-off-by: Alexander Potapenko <glider@google.com>
>
> ---
> v2:
> - Restrict the warning exemption to the in-kernel PIC case.
> - Remove the pr_err_ratelimited() logging.
> - Preserve the WARN_ON_ONCE() for non-PIC interrupt sources.
>
> v1:
> https://lore.kernel.org/all/345e9d6c-d7d9-4bab-adb3-d6a7bd27599f@mail.kernel.org/T/
> ---
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 0550359ed..f1681aa9f 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -10857,7 +10857,9 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
>                 if (r) {
>                         int irq = kvm_cpu_get_interrupt(vcpu);
>
> -                       if (!WARN_ON_ONCE(irq == -1)) {
> +                       WARN_ON_ONCE(irq == -1 && !pic_in_kernel(vcpu->kvm));
> +
> +                       if (irq != -1) {

Hmm, no, that looks weird.
Sorry for the noise, please ignore.


>                                 kvm_queue_interrupt(vcpu, irq, false);
>                                 kvm_x86_call(inject_irq)(vcpu, false);
>                                 WARN_ON(kvm_x86_call(interrupt_allowed)(vcpu, true) < 0);
>
>
> base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
> --
> See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
> You can comment on the patch as usual, syzbot will try to address
> the comments and send a new version of the patch if necessary.
> syzbot engineers can be reached at syzkaller@googlegroups.com.
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning
  2026-06-25 22:34 ` Aleksandr Nogikh
@ 2026-06-25 22:38   ` Sean Christopherson
  0 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2026-06-25 22:38 UTC (permalink / raw)
  To: Aleksandr Nogikh
  Cc: syzbot, syzkaller-bugs, Borislav Petkov, Dave Hansen, kvm,
	Ingo Molnar, Paolo Bonzini, Thomas Gleixner, x86, hpa,
	linux-kernel, syzbot

On Fri, Jun 26, 2026, Aleksandr Nogikh wrote:
> On Thu, Jun 25, 2026 at 11:10 PM 'syzbot' via syzkaller-bugs
> > https://lore.kernel.org/all/345e9d6c-d7d9-4bab-adb3-d6a7bd27599f@mail.kernel.org/T/
> > ---
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index 0550359ed..f1681aa9f 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -10857,7 +10857,9 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
> >                 if (r) {
> >                         int irq = kvm_cpu_get_interrupt(vcpu);
> >
> > -                       if (!WARN_ON_ONCE(irq == -1)) {
> > +                       WARN_ON_ONCE(irq == -1 && !pic_in_kernel(vcpu->kvm));
> > +
> > +                       if (irq != -1) {
> 
> Hmm, no, that looks weird.
> Sorry for the noise, please ignore.

Looks right to me?  FWIW, this is what I had thrown together locally:

---
Author:     Sean Christopherson <seanjc@google.com>
AuthorDate: Thu Jun 25 08:46:48 2026 -0700
Commit:     Sean Christopherson <seanjc@google.com>
CommitDate: Thu Jun 25 09:00:49 2026 -0700

    KVM: x86: Don't WARN if IRQ disappears because it was cleared from the PIC
    
    When getting a to-be-injected IRQ, don't WARN if the IRQ disappeared and
    the VM has an in-kernel PIC, as the ExtINT handling that's routed through
    KVM's virtual PIC is tracked per-VM, not per-vCPU.  If another vCPU grabs
    the IRQ, or deasserts the interrupt (which is level-triggered), then it's
    both expected and "fine" for a
    
    Keep the assert for split IRQCHIP VMs to help detect KVM bugs, as userspace
    is responsible for routing ExtINT to the intended vCPU, i.e. once an ExtINT
    is pending, it can't be cleared without holding the vCPU's mutex, and thus
    false positives are impossible.
    
    Fixes: bf672720e83c ("KVM: x86: check the kvm_cpu_get_interrupt result before using it")
    Debugged-by: Alexander Potapenko <glider@google.com>
    Reported-by: syzbot+dd769db18693736eee89@syzkaller.appspotmail.com
    Closes: https://syzkaller.appspot.com/bug?extid=dd769db18693736eee89
    Closes: https://lore.kernel.org/all/6a360fdf.871e809a.2d6dda.0000.GAE@google.com
    Signed-off-by: Sean Christopherson <seanjc@google.com>

diff --git arch/x86/kvm/x86.c arch/x86/kvm/x86.c
index 0626e835e9eb..7feddeeb819d 100644
--- arch/x86/kvm/x86.c
+++ arch/x86/kvm/x86.c
@@ -7686,10 +7686,12 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
                if (r) {
                        int irq = kvm_cpu_get_interrupt(vcpu);
 
-                       if (!WARN_ON_ONCE(irq == -1)) {
+                       if (likely(irq != -1)) {
                                kvm_queue_interrupt(vcpu, irq, false);
                                kvm_x86_call(inject_irq)(vcpu, false);
                                WARN_ON(kvm_x86_call(interrupt_allowed)(vcpu, true) < 0);
+                       } else {
+                               WARN_ON_ONCE(!pic_in_kernel(vcpu->kvm));
                        }
                }
                if (kvm_cpu_has_injectable_intr(vcpu))

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-06-25 22:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-25 21:10 [PATCH v2] KVM: x86: Exempt in-kernel PIC from "disappearing" interrupt warning syzbot
2026-06-25 21:20 ` sashiko-bot
2026-06-25 22:34 ` Aleksandr Nogikh
2026-06-25 22:38   ` Sean Christopherson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox