* [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel
@ 2026-06-18 18:55 Sean Christopherson
2026-06-19 4:51 ` Huang, Kai
2026-06-24 9:50 ` Paolo Bonzini
0 siblings, 2 replies; 6+ messages in thread
From: Sean Christopherson @ 2026-06-18 18:55 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
If KVM handles an I/O APIC EOI exit request with a bad vector, clamp the
vector to 255 and hope for the best instead of bugging the host. In all
likelihood, a missed EOI is survivable for the guest, and it's most
definitely not remotely fatal to the host, i.e. potentially panicking the
host is completely unjustified. Arbitrarily use 255 for the dummy vector,
the goal is purely to ensure the vector is covered by the bitmap.
Opportunistically ensure the EOI vector isn't negative, as it's a signed
integer, i.e. the "greater than 255" check won't guard against setting the
vector to a negative value (KVM uses -1 to say "no IRQ" in many flows).
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/x86.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d9d51803b7b2..fda09e03b960 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11212,7 +11212,10 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
if (kvm_check_request(KVM_REQ_NMI, vcpu))
process_nmi(vcpu);
if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
- BUG_ON(vcpu->arch.pending_ioapic_eoi > 255);
+ if (WARN_ON_ONCE(vcpu->arch.pending_ioapic_eoi < 0 ||
+ vcpu->arch.pending_ioapic_eoi > 255))
+ vcpu->arch.pending_ioapic_eoi = 255;
+
if (test_bit(vcpu->arch.pending_ioapic_eoi,
vcpu->arch.ioapic_handled_vectors)) {
vcpu->run->exit_reason = KVM_EXIT_IOAPIC_EOI;
base-commit: 9d4853b044beefa21c4ee3e18c40653601a64ced
--
2.55.0.rc0.738.g0c8ab3ebcc-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel
2026-06-18 18:55 [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel Sean Christopherson
@ 2026-06-19 4:51 ` Huang, Kai
2026-06-22 23:55 ` Sean Christopherson
2026-06-24 9:50 ` Paolo Bonzini
1 sibling, 1 reply; 6+ messages in thread
From: Huang, Kai @ 2026-06-19 4:51 UTC (permalink / raw)
To: pbonzini@redhat.com, seanjc@google.com
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org
On Thu, 2026-06-18 at 11:55 -0700, Sean Christopherson wrote:
> If KVM handles an I/O APIC EOI exit request with a bad vector, clamp the
> vector to 255 and hope for the best instead of bugging the host. In all
> likelihood, a missed EOI is survivable for the guest, and it's most
> definitely not remotely fatal to the host, i.e. potentially panicking the
> host is completely unjustified. Arbitrarily use 255 for the dummy vector,
> the goal is purely to ensure the vector is covered by the bitmap.
255 is a valid vector. How about use a CPU reserved one instead (e.g., vector
0) and hope for the best?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel
2026-06-19 4:51 ` Huang, Kai
@ 2026-06-22 23:55 ` Sean Christopherson
2026-06-23 10:29 ` Huang, Kai
0 siblings, 1 reply; 6+ messages in thread
From: Sean Christopherson @ 2026-06-22 23:55 UTC (permalink / raw)
To: Kai Huang
Cc: pbonzini@redhat.com, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org
On Fri, Jun 19, 2026, Kai Huang wrote:
> On Thu, 2026-06-18 at 11:55 -0700, Sean Christopherson wrote:
> > If KVM handles an I/O APIC EOI exit request with a bad vector, clamp the
> > vector to 255 and hope for the best instead of bugging the host. In all
> > likelihood, a missed EOI is survivable for the guest, and it's most
> > definitely not remotely fatal to the host, i.e. potentially panicking the
> > host is completely unjustified. Arbitrarily use 255 for the dummy vector,
> > the goal is purely to ensure the vector is covered by the bitmap.
>
> 255 is a valid vector. How about use a CPU reserved one instead (e.g., vector
> 0) and hope for the best?
I was thinking it would be better to err on the side of spuriously exiting to
userspace, versus suppressing an exit? And I wanted to keep the vector legal,
in case something else in KVM cares about legal vectors? Hmm, but using 255 is
bad because it likely never be cleared, and thus will block other EOI exits due
to 255 being the highest priority vector.
Ah, and the field is never explicitly initialized beyond the structutre being,
so it's starting state is '0' as well. My only hesitation with zero is that in
the unlikely case bit 0 is set in ioapic_handled_vectors, userspace will be extra
confused. But that's easy enough to deal with, just skip the check.
This?
if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
if (WARN_ON_ONCE(vcpu->arch.pending_ioapic_eoi < 0 ||
vcpu->arch.pending_ioapic_eoi > 255))
vcpu->arch.pending_ioapic_eoi = 0;
else if (test_bit(vcpu->arch.pending_ioapic_eoi,
vcpu->arch.ioapic_handled_vectors)) {
vcpu->run->exit_reason = KVM_EXIT_IOAPIC_EOI;
vcpu->run->eoi.vector =
vcpu->arch.pending_ioapic_eoi;
r = 0;
goto out;
}
}
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel
2026-06-22 23:55 ` Sean Christopherson
@ 2026-06-23 10:29 ` Huang, Kai
0 siblings, 0 replies; 6+ messages in thread
From: Huang, Kai @ 2026-06-23 10:29 UTC (permalink / raw)
To: seanjc@google.com
Cc: kvm@vger.kernel.org, pbonzini@redhat.com,
linux-kernel@vger.kernel.org
On Mon, 2026-06-22 at 16:55 -0700, Sean Christopherson wrote:
> On Fri, Jun 19, 2026, Kai Huang wrote:
> > On Thu, 2026-06-18 at 11:55 -0700, Sean Christopherson wrote:
> > > If KVM handles an I/O APIC EOI exit request with a bad vector, clamp the
> > > vector to 255 and hope for the best instead of bugging the host. In all
> > > likelihood, a missed EOI is survivable for the guest, and it's most
> > > definitely not remotely fatal to the host, i.e. potentially panicking the
> > > host is completely unjustified. Arbitrarily use 255 for the dummy vector,
> > > the goal is purely to ensure the vector is covered by the bitmap.
> >
> > 255 is a valid vector. How about use a CPU reserved one instead (e.g., vector
> > 0) and hope for the best?
>
> I was thinking it would be better to err on the side of spuriously exiting to
> userspace, versus suppressing an exit? And I wanted to keep the vector legal,
> in case something else in KVM cares about legal vectors? Hmm, but using 255 is
> bad because it likely never be cleared, and thus will block other EOI exits due
> to 255 being the highest priority vector.
>
> Ah, and the field is never explicitly initialized beyond the structutre being,
> so it's starting state is '0' as well. My only hesitation with zero is that in
> the unlikely case bit 0 is set in ioapic_handled_vectors, userspace will be extra
> confused.
>
I was actually thinking 0 may be less confusing than 255. A sane userspace
should just know 0 is a bad vector thus should report an error to admin, if not
kill the guest. On the other hand, 255 is a valid vector so userspace may
wrongly EOI an incorrect IRQ, which could be more confusing to the guest or
userspace itself in the end?
Btw, I think killing the guest should be acceptable if such bug happens? The
existing behaviour is to panic the host anyway ..
> But that's easy enough to deal with, just skip the check.
I am not sure ignoring the IOAPIC EOI exit (in case of this bug) is better than
reporting a invalid vector to userspace. I guess it's fine, since the worst
case is userspace loses the EOI for an IRQ AFAICT, but I am not sure this is
better?
>
> This?
>
> if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
> if (WARN_ON_ONCE(vcpu->arch.pending_ioapic_eoi < 0 ||
> vcpu->arch.pending_ioapic_eoi > 255))
> vcpu->arch.pending_ioapic_eoi = 0;
> else if (test_bit(vcpu->arch.pending_ioapic_eoi,
> vcpu->arch.ioapic_handled_vectors)) {
> vcpu->run->exit_reason = KVM_EXIT_IOAPIC_EOI;
> vcpu->run->eoi.vector =
> vcpu->arch.pending_ioapic_eoi;
> r = 0;
> goto out;
> }
> }
Either way works for me. I am starting to think we care about this too much --
it's definitely better than BUG_ON() for sure :-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel
2026-06-18 18:55 [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel Sean Christopherson
2026-06-19 4:51 ` Huang, Kai
@ 2026-06-24 9:50 ` Paolo Bonzini
2026-06-24 13:18 ` Sean Christopherson
1 sibling, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2026-06-24 9:50 UTC (permalink / raw)
To: Sean Christopherson; +Cc: kvm, linux-kernel
On 6/18/26 20:55, Sean Christopherson wrote:
> If KVM handles an I/O APIC EOI exit request with a bad vector, clamp the
> vector to 255 and hope for the best instead of bugging the host. In all
> likelihood, a missed EOI is survivable for the guest, and it's most
> definitely not remotely fatal to the host, i.e. potentially panicking the
> host is completely unjustified. Arbitrarily use 255 for the dummy vector,
> the goal is purely to ensure the vector is covered by the bitmap.
>
> Opportunistically ensure the EOI vector isn't negative, as it's a signed
> integer, i.e. the "greater than 255" check won't guard against setting the
> vector to a negative value (KVM uses -1 to say "no IRQ" in many flows).
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> arch/x86/kvm/x86.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index d9d51803b7b2..fda09e03b960 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -11212,7 +11212,10 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
> if (kvm_check_request(KVM_REQ_NMI, vcpu))
> process_nmi(vcpu);
> if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
> - BUG_ON(vcpu->arch.pending_ioapic_eoi > 255);
> + if (WARN_ON_ONCE(vcpu->arch.pending_ioapic_eoi < 0 ||
> + vcpu->arch.pending_ioapic_eoi > 255))
> + vcpu->arch.pending_ioapic_eoi = 255;
> +
Yay, it's my turn to say "why?!?" I'm not going to go full Linus on
it :) but I've been waiting for the moment for years!
If this happens we have a much bigger problem: the vector is set in
kvm_ioapic_send_eoi() and ultimately comes from apic_find_highest_isr().
It is simply not going to happen.
Unlike pending_external_vector or highest_stale_pending_ioapic_eoi, this
cannot even be -1...255 so make it u8 and call it a day?
Something like this:
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index eee473717c0e..9c444dfa7342 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1082,7 +1082,7 @@ struct kvm_vcpu_arch {
bool pv_unhalted;
} pv;
- int pending_ioapic_eoi;
+ u8 pending_ioapic_eoi;
int pending_external_vector;
int highest_stale_pending_ioapic_eoi;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 9d2df8623f6d..fca9be6e536d 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1541,7 +1541,7 @@ static bool kvm_ioapic_handles_vector(struct kvm_lapic *apic, int vector)
return test_bit(vector, apic->vcpu->arch.ioapic_handled_vectors);
}
-static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector)
+static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, u8 vector)
{
int __maybe_unused trigger_mode;
@@ -1611,7 +1611,7 @@ static int apic_set_eoi(struct kvm_lapic *apic)
* this interface assumes a trap-like exit, which has already finished
* desired side effect including vISR and vPPR update.
*/
-void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector)
+void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, u8 vector)
{
struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index a1a5edb39a7e..57333d7bb32c 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -5866,7 +5866,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu)
static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
{
unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
- int vector = exit_qualification & 0xff;
+ u8 vector = exit_qualification & 0xff;
/* EOI-induced VM exit is trap-like and thus no need to adjust IP */
kvm_apic_set_eoi_accelerated(vcpu, vector);
and then obviously the BUG_ON goes away.
Paolo
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel
2026-06-24 9:50 ` Paolo Bonzini
@ 2026-06-24 13:18 ` Sean Christopherson
0 siblings, 0 replies; 6+ messages in thread
From: Sean Christopherson @ 2026-06-24 13:18 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: kvm, linux-kernel
On Wed, Jun 24, 2026, Paolo Bonzini wrote:
> On 6/18/26 20:55, Sean Christopherson wrote:
> > If KVM handles an I/O APIC EOI exit request with a bad vector, clamp the
> > vector to 255 and hope for the best instead of bugging the host. In all
> > likelihood, a missed EOI is survivable for the guest, and it's most
> > definitely not remotely fatal to the host, i.e. potentially panicking the
> > host is completely unjustified. Arbitrarily use 255 for the dummy vector,
> > the goal is purely to ensure the vector is covered by the bitmap.
> >
> > Opportunistically ensure the EOI vector isn't negative, as it's a signed
> > integer, i.e. the "greater than 255" check won't guard against setting the
> > vector to a negative value (KVM uses -1 to say "no IRQ" in many flows).
> >
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > ---
> > arch/x86/kvm/x86.c | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index d9d51803b7b2..fda09e03b960 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -11212,7 +11212,10 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
> > if (kvm_check_request(KVM_REQ_NMI, vcpu))
> > process_nmi(vcpu);
> > if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
> > - BUG_ON(vcpu->arch.pending_ioapic_eoi > 255);
> > + if (WARN_ON_ONCE(vcpu->arch.pending_ioapic_eoi < 0 ||
> > + vcpu->arch.pending_ioapic_eoi > 255))
> > + vcpu->arch.pending_ioapic_eoi = 255;
> > +
>
> Yay, it's my turn to say "why?!?" I'm not going to go full Linus on
> it :) but I've been waiting for the moment for years!
LOL. Well, well, well, if it isn't the consequences of my own actions.
> If this happens we have a much bigger problem: the vector is set in
> kvm_ioapic_send_eoi() and ultimately comes from apic_find_highest_isr().
> It is simply not going to happen.
>
> Unlike pending_external_vector or highest_stale_pending_ioapic_eoi, this
> cannot even be -1...255 so make it u8 and call it a day?
Ya, that's waaay better, especially since pending_ioapic_eoi defaults to '0'
anyways.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-24 13:18 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18 18:55 [PATCH] KVM: x86: Clamp the EOI vector if its OOB instead of bugging the kernel Sean Christopherson
2026-06-19 4:51 ` Huang, Kai
2026-06-22 23:55 ` Sean Christopherson
2026-06-23 10:29 ` Huang, Kai
2026-06-24 9:50 ` Paolo Bonzini
2026-06-24 13:18 ` Sean Christopherson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.