[PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load

From: w15303746062

Date: Tue Jun 23 2026 - 03:11:24 EST


From: Mingyu Wang <25181214217@xxxxxxxxxxxxxxxxx>

The ibmasm driver maps PCI BAR 0 without verifying if the hardware-provided
resource length is sufficient. The driver statically accesses the
INTR_CONTROL_REGISTER at offset 0x13A4.

When evaluating the driver against emulated hardware or during virtual
device fuzzing, a malformed device may expose a significantly undersized
BAR 0 (e.g., 4KB). In this scenario, the readl() in enable_sp_interrupts()
crosses the mapped page boundary into unmapped memory, causing a page fault
during probe.

Because this crash happens while holding the idempotent_init_module() lock,
it leaves the module loading subsystem in a corrupted state, leading to a
cascading global soft lockup when other threads attempt to load modules:

BUG: unable to handle page fault for address: ffffc900018433a4
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
...
RIP: 0010:readl arch/x86/include/asm/io.h:59 [inline] [ibmasm]
RIP: 0010:ibmasm_enable_interrupts drivers/misc/ibmasm/lowlevel.h:54 [inline] [ibmasm]
RIP: 0010:enable_sp_interrupts drivers/misc/ibmasm/lowlevel.h:65 [inline] [ibmasm]
...
watchdog: BUG: soft lockup - CPU#1 stuck for 266s! [systemd-udevd:182]
...
RIP: 0010:queued_spin_lock_slowpath+0x243/0xbf0 kernel/locking/qspinlock.c:141

Fix this by ensuring the BAR size is at least INTR_CONTROL_REGISTER + 4
before calling pci_ioremap_bar().

Fixes: bdbeed75b288 ("pci: use pci_ioremap_bar() in drivers/misc")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Mingyu Wang <25181214217@xxxxxxxxxxxxxxxxx>
---
drivers/misc/ibmasm/module.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 4509c15a76a8..47daef731778 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -93,6 +93,17 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}

sp->irq = pdev->irq;
+
+ /*
+ * Ensure BAR 0 is large enough to cover the highest statically
+ * accessed hardware register (INTR_CONTROL_REGISTER at 0x13A4).
+ */
+ if (pci_resource_len(pdev, 0) < INTR_CONTROL_REGISTER + 4) {
+ dev_err(sp->dev, "PCI BAR0 is too small\n");
+ result = -ENODEV;
+ goto error_ioremap;
+ }
+
sp->base_address = pci_ioremap_bar(pdev, 0);
if (!sp->base_address) {
dev_err(sp->dev, "Failed to ioremap pci memory\n");
--
2.34.1