]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: vgic: Mitigate potential LPI registration failure
authorCarlos López <clopez@suse.de>
Wed, 15 Jul 2026 10:51:38 +0000 (12:51 +0200)
committerMarc Zyngier <maz@kernel.org>
Thu, 23 Jul 2026 08:56:57 +0000 (09:56 +0100)
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>
arch/arm64/kvm/vgic/vgic-its.c

index 5c5d1772147d5a54fef05baf8b41bbfa10803ac6..36ab3e4929154165fa91ac3091576d969d91f8c2 100644 (file)
@@ -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);