diff mbox series

[2/3] KVM: arm64: vgic: Check for unallocated PPI/SPI arrays

Message ID 20250206152100.1107909-3-maz@kernel.org (mailing list archive)
State New
Headers show
Series KVM: arm64: Assorted vgic fixes for 6.14 | expand

Commit Message

Marc Zyngier Feb. 6, 2025, 3:20 p.m. UTC
Alexander's fuzzing has exhibited a large variety of races that
all end-up with taking the address of a PPI or SPI structure while
the vgic was torn down (because nuking it is only an ioctl() away,
and syzkaller is amazing at finding holes).

In order to preserve some sanity, always evaluate whether the array
containing the PPI/SPI is allocated.

Suggested-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/vgic/vgic.c | 4 ++++
 1 file changed, 4 insertions(+)

Comments

Alexander Potapenko Feb. 6, 2025, 3:50 p.m. UTC | #1
On Thu, Feb 6, 2025 at 4:21 PM Marc Zyngier <maz@kernel.org> wrote:
>
> Alexander's fuzzing has exhibited a large variety of races that
> all end-up with taking the address of a PPI or SPI structure while
> the vgic was torn down (because nuking it is only an ioctl() away,
> and syzkaller is amazing at finding holes).
>
> In order to preserve some sanity, always evaluate whether the array
> containing the PPI/SPI is allocated.
>
> Suggested-by: Alexander Potapenko <glider@google.com>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
Tested-by: Alexander Potapenko <glider@google.com>
diff mbox series

Patch

diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index cc8c6b9b5dd8b..f454cef59e24b 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -89,6 +89,8 @@  struct vgic_irq *vgic_get_irq(struct kvm *kvm, u32 intid)
 	/* SPIs */
 	if (intid >= VGIC_NR_PRIVATE_IRQS &&
 	    intid < (kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) {
+		if (unlikely(!kvm->arch.vgic.spis))
+			return NULL;
 		intid = array_index_nospec(intid, kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS);
 		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
 	}
@@ -107,6 +109,8 @@  struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
 
 	/* SGIs and PPIs */
 	if (intid < VGIC_NR_PRIVATE_IRQS) {
+		if (unlikely(!vcpu->arch.vgic_cpu.private_irqs))
+			return NULL;
 		intid = array_index_nospec(intid, VGIC_NR_PRIVATE_IRQS);
 		return &vcpu->arch.vgic_cpu.private_irqs[intid];
 	}