mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load
@ 2026-06-23  7:09 w15303746062
  2026-06-23  7:16 ` Greg KH
  0 siblings, 1 reply; 6+ messages in thread
From: w15303746062 @ 2026-06-23  7:09 UTC (permalink / raw)
  To: arnd, gregkh; +Cc: linux-kernel, kees, Mingyu Wang, stable

From: Mingyu Wang <25181214217@stu.xidian.edu.cn>

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@vger.kernel.org
Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
---
 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


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load
  2026-06-23  7:09 [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load w15303746062
@ 2026-06-23  7:16 ` Greg KH
  2026-06-23 11:40   ` [PATCH v2] misc: ibmasm: Fix static and dynamic out-of-bounds MMIO accesses w15303746062
  2026-06-23 11:47   ` [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load Mingyu Wang
  0 siblings, 2 replies; 6+ messages in thread
From: Greg KH @ 2026-06-23  7:16 UTC (permalink / raw)
  To: w15303746062; +Cc: arnd, linux-kernel, kees, Mingyu Wang, stable

On Tue, Jun 23, 2026 at 03:09:09PM +0800, w15303746062@163.com wrote:
> From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
> 
> 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.

The kernel trusts the hardware to not do foolish things like this :)

> 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.

Are you sure this is the only code path for this type of issue for this
device/driver?  Why just worry about this one?


thanks,

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] misc: ibmasm: Fix static and dynamic out-of-bounds MMIO accesses
  2026-06-23  7:16 ` Greg KH
@ 2026-06-23 11:40   ` w15303746062
  2026-06-23 11:53     ` Greg KH
  2026-06-23 11:47   ` [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load Mingyu Wang
  1 sibling, 1 reply; 6+ messages in thread
From: w15303746062 @ 2026-06-23 11:40 UTC (permalink / raw)
  To: arnd, gregkh; +Cc: linux-kernel, kees, stable, Mingyu Wang

From: Mingyu Wang <25181214217@stu.xidian.edu.cn>

The ibmasm driver maps PCI BAR 0 without verifying if the hardware-provided
resource length is sufficient.

When evaluating the driver against emulated hardware or during virtual
device fuzzing, a malformed device may expose a significantly undersized
BAR 0. This leads to two distinct out-of-bounds (OOB) MMIO access vectors:

1. Static OOB: The driver hardcodes access to INTR_CONTROL_REGISTER
   (offset 0x13A4) during probe.
2. Dynamic OOB: The driver reads dynamic Message Frame Addresses (MFA)
   from hardware queues and uses them directly as offsets to dereference
   I2O messages via get_i2o_message(). A malicious MFA can cause the
   driver to access memory far beyond the mapped BAR.

If an OOB access triggers a #PF during module probe while holding the
idempotent_init_module() lock, it leaves the module loading subsystem
in a corrupted state, leading to a cascading global soft lockup.

Fix this comprehensively by:
- Storing the mapped resource size in 'struct service_processor'.
- Ensuring the BAR size covers the highest statically accessed register
  (INTR_CONTROL_REGISTER) during probe.
- Validating all dynamic MFA offsets against the mapped size before
  dereferencing to prevent dynamic OOB accesses.

Fixes: bdbeed75b288 ("pci: use pci_ioremap_bar() in drivers/misc")
Cc: stable@vger.kernel.org
Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
---
Changes in v2:
 - Added dynamic MFA bounds checking in get_i2o_message() to prevent runtime OOB (prompted by Greg KH).
 - Implemented hardware mailbox deadlock prevention by releasing MFA if bounds check fails.
 - Fixed potential unsigned integer underflow in bounds check arithmetic.

 drivers/misc/ibmasm/ibmasm.h   |  1 +
 drivers/misc/ibmasm/lowlevel.c | 19 +++++++++++++++----
 drivers/misc/ibmasm/lowlevel.h | 27 +++++++++++++++++++++++++--
 drivers/misc/ibmasm/module.c   | 13 +++++++++++++
 4 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index a5ced88ca923..8d69198bf10f 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -140,6 +140,7 @@ struct service_processor {
 	struct list_head	node;
 	spinlock_t		lock;
 	void __iomem		*base_address;
+	resource_size_t		mapped_size;
 	unsigned int		irq;
 	struct command		*current_command;
 	struct command		*heartbeat;
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index 5313230f36ad..db84e5f827cb 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -9,7 +9,6 @@
 
 #include "ibmasm.h"
 #include "lowlevel.h"
-#include "i2o.h"
 #include "dot_command.h"
 #include "remote.h"
 
@@ -34,7 +33,14 @@ int ibmasm_send_i2o_message(struct service_processor *sp)
 		return 1;
 
 	header.message_size = outgoing_message_size((unsigned int)command_size);
-	message = get_i2o_message(sp->base_address, mfa);
+	message = get_i2o_message(sp->base_address, sp->mapped_size, mfa);
+	if (!message) {
+		/* MFA was reserved for us; must release it to avoid
+		 * deadlocking the hardware mailbox.
+		 */
+		set_mfa_inbound(sp->base_address, mfa);
+		return 1;
+	}
 
 	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
 	memcpy_toio(&message->data, command->buffer, command_size);
@@ -63,8 +69,13 @@ irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id)
 
 	mfa = get_mfa_outbound(base_address);
 	if (valid_mfa(mfa)) {
-		struct i2o_message *msg = get_i2o_message(base_address, mfa);
-		ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg));
+		struct i2o_message *msg = get_i2o_message(base_address,
+							  sp->mapped_size, mfa);
+		if (msg)
+			ibmasm_receive_message(sp, &msg->data,
+					       incoming_data_size(msg));
+		else
+			dbg("received mfa out of bounds\n");
 	} else
 		dbg("didn't get a valid MFA\n");
 
diff --git a/drivers/misc/ibmasm/lowlevel.h b/drivers/misc/ibmasm/lowlevel.h
index 25f1ed07c3c5..8c9700fc70bb 100644
--- a/drivers/misc/ibmasm/lowlevel.h
+++ b/drivers/misc/ibmasm/lowlevel.h
@@ -13,6 +13,9 @@
 #define __IBMASM_CONDOR_H__
 
 #include <asm/io.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include "i2o.h"
 
 #define VENDORID_IBM	0x1014
 #define DEVICEID_RSA	0x010F
@@ -33,6 +36,9 @@
 #define INTR_STATUS_REGISTER   0x13A0
 #define INTR_CONTROL_REGISTER  0x13A4
 
+/* Highest statically accessed register offset */
+#define IBMASM_MAX_REG_OFFSET	INTR_CONTROL_REGISTER
+
 #define SCOUT_COM_A_BASE         0x0000
 #define SCOUT_COM_B_BASE         0x0100
 #define SCOUT_COM_C_BASE         0x0200
@@ -115,9 +121,26 @@ static inline void set_mfa_inbound(void __iomem *base_address, u32 mfa)
 	writel(mfa, base_address + INBOUND_QUEUE_PORT);
 }
 
-static inline struct i2o_message *get_i2o_message(void __iomem *base_address, u32 mfa)
+/**
+ * get_i2o_message - Convert MFA to i2o_message pointer with bounds check
+ * @base_address: BAR 0 virtual address
+ * @mapped_size:  actual size of BAR 0 mapping
+ * @mfa:          Message Frame Address from hardware
+ *
+ * Returns NULL if the offset derived from @mfa does not fit within
+ * the mapped BAR (including the i2o_message header).
+ */
+static inline struct i2o_message *get_i2o_message(void __iomem *base_address,
+						  resource_size_t mapped_size,
+						  u32 mfa)
 {
-	return (struct i2o_message *)(GET_MFA_ADDR(mfa) + base_address);
+	u32 offset = GET_MFA_ADDR(mfa);
+
+	/* Prevent read/write beyond the ioremap region */
+	if (unlikely(offset + sizeof(struct i2o_message) > mapped_size))
+		return NULL;
+
+	return (struct i2o_message *)(offset + base_address);
 }
 
 #endif /* __IBMASM_CONDOR_H__ */
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 4509c15a76a8..87d4d698a5ff 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -93,6 +93,19 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	}
 
 	sp->irq = pdev->irq;
+	sp->mapped_size = pci_resource_len(pdev, 0);
+
+	/*
+	 * Ensure BAR 0 is large enough to cover the highest statically
+	 * accessed hardware register (IBMASM_MAX_REG_OFFSET).
+	 */
+	if (sp->mapped_size < IBMASM_MAX_REG_OFFSET + 4) {
+		dev_err(sp->dev, "PCI BAR0 too small, need at least %zu bytes\n",
+			(size_t)(IBMASM_MAX_REG_OFFSET + 4));
+		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


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load
  2026-06-23  7:16 ` Greg KH
  2026-06-23 11:40   ` [PATCH v2] misc: ibmasm: Fix static and dynamic out-of-bounds MMIO accesses w15303746062
@ 2026-06-23 11:47   ` Mingyu Wang
  1 sibling, 0 replies; 6+ messages in thread
From: Mingyu Wang @ 2026-06-23 11:47 UTC (permalink / raw)
  To: Greg KH, w15303746062; +Cc: arnd, linux-kernel, kees, stable

Hi Greg,

> The kernel trusts the hardware to not do foolish things like this 🙂
>> 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.
> Are you sure this is the only code path for this type of issue for this
> device/driver?  Why just worry about this one?

You were absolutely right to ask. Prompted by your question, I did a full
audit of the MMIO access paths in this driver.

I found that the dynamic MFA (Message Frame Address) reads from the 
hardware
queues, which are used directly as offsets in `get_i2o_message()`, are also
highly vulnerable to OOB accesses if the fuzzed hardware returns malicious
offsets during runtime.

I have just submitted a v2 patch in this thread that comprehensively fixes
both the static OOB during probe and the dynamic OOB during runtime.

Thank you very much for catching this and pointing me in the right 
direction!

Best regards,
Mingyu Wang


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] misc: ibmasm: Fix static and dynamic out-of-bounds MMIO accesses
  2026-06-23 11:40   ` [PATCH v2] misc: ibmasm: Fix static and dynamic out-of-bounds MMIO accesses w15303746062
@ 2026-06-23 11:53     ` Greg KH
  2026-06-23 12:00       ` Mingyu Wang
  0 siblings, 1 reply; 6+ messages in thread
From: Greg KH @ 2026-06-23 11:53 UTC (permalink / raw)
  To: w15303746062; +Cc: arnd, linux-kernel, kees, stable, Mingyu Wang

On Tue, Jun 23, 2026 at 07:40:46PM +0800, w15303746062@163.com wrote:
> From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
> 
> The ibmasm driver maps PCI BAR 0 without verifying if the hardware-provided
> resource length is sufficient.
> 
> When evaluating the driver against emulated hardware or during virtual
> device fuzzing, a malformed device may expose a significantly undersized
> BAR 0. This leads to two distinct out-of-bounds (OOB) MMIO access vectors:
> 
> 1. Static OOB: The driver hardcodes access to INTR_CONTROL_REGISTER
>    (offset 0x13A4) during probe.
> 2. Dynamic OOB: The driver reads dynamic Message Frame Addresses (MFA)
>    from hardware queues and uses them directly as offsets to dereference
>    I2O messages via get_i2o_message(). A malicious MFA can cause the
>    driver to access memory far beyond the mapped BAR.
> 
> If an OOB access triggers a #PF during module probe while holding the
> idempotent_init_module() lock, it leaves the module loading subsystem
> in a corrupted state, leading to a cascading global soft lockup.
> 
> Fix this comprehensively by:
> - Storing the mapped resource size in 'struct service_processor'.
> - Ensuring the BAR size covers the highest statically accessed register
>   (INTR_CONTROL_REGISTER) during probe.
> - Validating all dynamic MFA offsets against the mapped size before
>   dereferencing to prevent dynamic OOB accesses.
> 
> Fixes: bdbeed75b288 ("pci: use pci_ioremap_bar() in drivers/misc")
> Cc: stable@vger.kernel.org
> Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
> ---
> Changes in v2:
>  - Added dynamic MFA bounds checking in get_i2o_message() to prevent runtime OOB (prompted by Greg KH).
>  - Implemented hardware mailbox deadlock prevention by releasing MFA if bounds check fails.
>  - Fixed potential unsigned integer underflow in bounds check arithmetic.

That's a lot of different things all at once here.  Please split this up
into a patch series, doing only one logical thing per patch so it is
easier to review and apply.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] misc: ibmasm: Fix static and dynamic out-of-bounds MMIO accesses
  2026-06-23 11:53     ` Greg KH
@ 2026-06-23 12:00       ` Mingyu Wang
  0 siblings, 0 replies; 6+ messages in thread
From: Mingyu Wang @ 2026-06-23 12:00 UTC (permalink / raw)
  To: Greg KH, w15303746062; +Cc: arnd, linux-kernel, kees, stable

> That's a lot of different things all at once here.  Please split this up
> into a patch series, doing only one logical thing per patch so it is
> easier to review and apply.

Understood. I will split this into a 2-patch series (v3) as suggested 
and send it out shortly.


Best regards,


Mingyu Wang


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-06-23 12:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-23  7:09 [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load w15303746062
2026-06-23  7:16 ` Greg KH
2026-06-23 11:40   ` [PATCH v2] misc: ibmasm: Fix static and dynamic out-of-bounds MMIO accesses w15303746062
2026-06-23 11:53     ` Greg KH
2026-06-23 12:00       ` Mingyu Wang
2026-06-23 11:47   ` [PATCH] misc: ibmasm: Fix out-of-bounds MMIO access during module load Mingyu Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox