summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorCarlos López <clopez@suse.de>2026-07-15 12:51:38 +0200
committerMarc Zyngier <maz@kernel.org>2026-07-23 09:56:57 +0100
commit21f12496fdd357ad4e1fcdd07dc80ab7378f7d24 (patch)
tree44af4ecdeb444104540d7a603c4ff2381deaefe8 /arch
parentcbfe2b24a1ea9de35032dbdd100fdc700f5be92d (diff)
downloadlinux-next-21f12496fdd357ad4e1fcdd07dc80ab7378f7d24.tar.gz
linux-next-21f12496fdd357ad4e1fcdd07dc80ab7378f7d24.zip
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 <sashiko-bot@kernel.org> Fixes: 1d6f83f60f79 ("KVM: arm64: vgic: Store LPIs in an xarray") Signed-off-by: Carlos López <clopez@suse.de> Link: https://patch.msgid.link/20260715105137.3973823-5-clopez@suse.de Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/kvm/vgic/vgic-its.c3
1 files changed, 2 insertions, 1 deletions
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);