From: Carlos López Date: Wed, 15 Jul 2026 10:51:38 +0000 (+0200) Subject: KVM: arm64: vgic: Mitigate potential LPI registration failure X-Git-Tag: v7.2-rc6~37^2~5^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21f12496fdd357ad4e1fcdd07dc80ab7378f7d24;p=thirdparty%2Flinux.git KVM: arm64: vgic: Mitigate potential LPI registration failure Mitigate a potential failure when inserting a new LPI into the VGIC LPI xarray. When vgic_add_lpi() is preparing to register a new LPI, it pre-allocates an xarray entry using xa_reserve_irq(), so that it can later perform the insertion under the xarray lock without allocating. However, since xa_reserve_irq() is called before acquiring such lock, there is a potential race where xa_reserve_irq() observes a populated entry, thus not performing the allocation, and another CPU removes that entry before the xarray lock is grabbed to perform the insertion. CPU0 (Adding new LPI) CPU1 (Releasing LPI) ===================== =================== vgic_add_lpi() /* Entry populated, does not allocate */ xa_reserve_irq(.., intid, ..) vgic_release_deleted_lpis() xa_lock_irqsave() vgic_release_lpi_locked() xarray node freed --> __xa_erase(.., intid) xa_unlock_irqrestore() xa_lock_irqsave() xa_load(.., intid) == NULL vgic_try_get_irq_ref(NULL) == false __xa_store(.., intid, irq, 0) <-- xarray node was freed, gfp=0 cannot allocate, returns -ENOMEM This can happen e.g. if the guest issues a DISCARD while the LPI is still referenced from a vCPU's active-pending list (ap_list), and the same INTID is re-mapped via MAPTI. Mitigate this by passing GFP_NOWAIT to __xa_store(), so that the allocation can happen under the lock in the rare case that this condition is hit. Add __GFP_ACCOUNT as well to match xa_reserve_irq()'s flags. Reported-by: Sashiko Fixes: 1d6f83f60f79 ("KVM: arm64: vgic: Store LPIs in an xarray") Signed-off-by: Carlos López Link: https://patch.msgid.link/20260715105137.3973823-5-clopez@suse.de Signed-off-by: Marc Zyngier --- diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 5c5d1772147d..36ab3e492915 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -121,7 +121,8 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, * from the deferred release path, pending cleanup by * vgic_release_deleted_lpis(). Evict and free it if present. */ - oldirq = __xa_store(&dist->lpi_xa, intid, irq, 0); + oldirq = __xa_store(&dist->lpi_xa, intid, irq, + GFP_NOWAIT | __GFP_ACCOUNT); ret = xa_err(oldirq); if (ret) { xa_unlock_irqrestore(&dist->lpi_xa, flags);