[PATCH v2] scsi: megaraid_mbox: validate numstatus and completed[] from firmware

Shipei Qu
2025-12-16T06:02:45Z

Hi,

resending with a properly formatted diff (the previous email had a malformed
patch header). The patch is otherwise unchanged.

The legacy megaraid_mbox driver trusts the mailbox fields numstatus and
completed[] that are written by the firmware.

In megaraid_ack_sequence():

- numstatus is used as the loop bound when filling a fixed-size stack array
completed[MBOX_MAX_FIRMWARE_STATUS] without checking that it is <=
MBOX_MAX_FIRMWARE_STATUS;
- each completed[i] is then used as an index into adapter->kscb_list[] /
adapter->uscb_list[] without validating that it is within the combined SCB
pool (MBOX_MAX_SCSI_CMDS + MBOX_MAX_USER_CMDS).

A misbehaving or buggy firmware can therefore cause stack and heap
out-of-bounds accesses and crashes.

In practice, this can also be triggered by a malicious PCIe or
Thunderbolt-attached device that emulates a supported controller and returns
crafted mailbox state.

This driver is still built by default in several distributions (e.g. Ubuntu),
so such firmware behaviour can affect stock installations. The same pattern is
present in current mainline kernels.

This issue was first reported via security@kernel.org. The kernel security team
considered it a normal robustness bug (controllers are assumed to be trusted
from the host's point of view) and asked us to send fixes to the relevant
development lists, so this patch follows that request. Below is a small
defensive fix.

Reported-by: DARKNAVY (@DarkNavyOrg) <vr@darknavy.com>
Signed-off-by: Shipei Qu <qu@darknavy.com>
---
drivers/scsi/megaraid/megaraid_mbox.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index b610cad83..c5922c3fd 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -2073,6 +2073,13 @@ megaraid_ack_sequence(adapter_t *adapter)
}
mbox->numstatus = 0xFF;

+ if (nstatus > MBOX_MAX_FIRMWARE_STATUS) {
+ con_log(CL_ANN, (KERN_ERR
+ "megaraid: firmware reported %u status entries (max %d)\n",
+ nstatus, MBOX_MAX_FIRMWARE_STATUS));
+ nstatus = MBOX_MAX_FIRMWARE_STATUS;
+ }
+
adapter->outstanding_cmds -= nstatus;

for (i = 0; i < nstatus; i++) {
@@ -2093,6 +2100,12 @@ megaraid_ack_sequence(adapter_t *adapter)
continue;
}

+ if (completed[i] >= MBOX_MAX_SCSI_CMDS + MBOX_MAX_USER_CMDS) {
+ con_log(CL_ANN, (KERN_ERR
+ "megaraid: invalid command id %u\n", completed[i]));
+ continue;
+ }
+
// Get SCB associated with this command id
if (completed[i] >= MBOX_MAX_SCSI_CMDS) {
// a cmm command
--
2.45.1