[PATCH 2/7] s390/pci: fix use-after-free race in zpci floating interrupt cleanup

From: Tobias Schumacher

Date: Wed Aug 19 2026 - 04:52:31 EST


The interrupt handler reads zpci_ibv[si] without synchronization while
concurrent teardown can release this memory, creating a race:
- handler reads the pointer,
- then teardown frees memory,
- then handler uses the freed pointer.
Fix by protecting array access with RCU synchronization.

Fixes: f770950a4709 ("s390/pci: Migrate s390 IRQ logic to IRQ domain API")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Tobias Schumacher <ts@xxxxxxxxxxxxx>
---
arch/s390/pci/pci_irq.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c
index c9520a16ca75..94b03d16006b 100644
--- a/arch/s390/pci/pci_irq.c
+++ b/arch/s390/pci/pci_irq.c
@@ -278,8 +278,14 @@ static void zpci_floating_irq_handler(struct airq_struct *airq,
continue;
}

+ rcu_read_lock();
+
/* Scan the adapter interrupt vector for this device. */
- aibv = zpci_ibv[si];
+ aibv = rcu_dereference(zpci_ibv[si]);
+ if (!aibv) {
+ rcu_read_unlock();
+ continue;
+ }
for (ai = 0;;) {
ai = airq_iv_scan(aibv, ai, airq_iv_end(aibv));
if (ai == -1UL)
@@ -291,6 +297,7 @@ static void zpci_floating_irq_handler(struct airq_struct *airq,
generic_handle_domain_irq(msi_domain, hwirq);
airq_iv_unlock(aibv, ai);
}
+ rcu_read_unlock();
}
}

@@ -346,9 +353,12 @@ static void zpci_msi_teardown_directed(struct zpci_dev *zdev)

static void zpci_msi_teardown_floating(struct zpci_dev *zdev)
{
+ airq_iv_free_bit(zpci_sbv, zdev->aisb);
+ zpci_ibv[zdev->aisb] = NULL;
+ synchronize_rcu();
+
airq_iv_release(zdev->aibv);
zdev->aibv = NULL;
- airq_iv_free_bit(zpci_sbv, zdev->aisb);
zdev->aisb = -1UL;
zdev->msi_first_bit = -1U;
zdev->msi_nr_irqs = 0;

--
2.53.0