From: Thijs Raymakers Date: Mon, 4 Aug 2025 06:44:05 +0000 (+0200) Subject: KVM: x86: use array_index_nospec with indices that come from guest X-Git-Tag: v5.4.298~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72777fc31aa7ab2ce00f44bfa3929c6eabbeaf48;p=thirdparty%2Fkernel%2Fstable.git KVM: x86: use array_index_nospec with indices that come from guest commit c87bd4dd43a624109c3cc42d843138378a7f4548 upstream. min and dest_id are guest-controlled indices. Using array_index_nospec() after the bounds checks clamps these values to mitigate speculative execution side-channels. Signed-off-by: Thijs Raymakers Cc: stable@vger.kernel.org Cc: Sean Christopherson Cc: Paolo Bonzini Cc: Greg Kroah-Hartman Fixes: 715062970f37 ("KVM: X86: Implement PV sched yield hypercall") Fixes: bdf7ffc89922 ("KVM: LAPIC: Fix pv ipis out-of-bounds access") Fixes: 4180bf1b655a ("KVM: X86: Implement "send IPI" hypercall") Link: https://lore.kernel.org/r/20250804064405.4802-1-thijs@raymakers.nl Signed-off-by: Sean Christopherson Signed-off-by: Greg Kroah-Hartman --- diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 319ed873a1111..257fba652aa56 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -589,6 +589,9 @@ int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low, if (min > map->max_apic_id) goto out; + + min = array_index_nospec(min, map->max_apic_id + 1); + /* Bits above cluster_size are masked in the caller. */ for_each_set_bit(i, &ipi_bitmap_low, min((u32)BITS_PER_LONG, (map->max_apic_id - min + 1))) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 07154cae7a153..b50d0da06b599 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7506,8 +7506,11 @@ static void kvm_sched_yield(struct kvm *kvm, unsigned long dest_id) rcu_read_lock(); map = rcu_dereference(kvm->arch.apic_map); - if (likely(map) && dest_id <= map->max_apic_id && map->phys_map[dest_id]) - target = map->phys_map[dest_id]->vcpu; + if (likely(map) && dest_id <= map->max_apic_id) { + dest_id = array_index_nospec(dest_id, map->max_apic_id + 1); + if (map->phys_map[dest_id]) + target = map->phys_map[dest_id]->vcpu; + } rcu_read_unlock();