Re: [PATCH] scsi: mpi3mr: make SAS port PHY masks 64-bit safe

[email protected] Tue, 04 Aug 2026 15:29:11 +0000
Newsgroups gmane.linux.scsi
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 3 potential issue(=
s) to consider:

New issues:
- [High] The newly introduced `mpi3mr_sas_phy_bit` function uses `WARN_ON_O=
NCE` to validate firmware-provided PHY identifiers, which creates a kernel =
panic vector if `panic_on_warn` is enabled.

Pre-existing issues:
- [High] Incorrect casting of `u64` bitmask to `unsigned long *` for `for_e=
ach_set_bit()` causes incorrect PHY IDs on 32-bit big-endian architectures,=
 leading to array out-of-bounds access.
- [High] A malicious or compromised firmware can trigger a heap buffer over=
flow in `mpi3mr_refresh_sas_ports()` by providing a `num_phys` value greate=
r than 64.
--

--- Patch [1]: [PATCH] scsi: mpi3mr: make SAS port PHY masks 64-bit safe ---
commit ceebecd676e904ef112074dffb72b70397933c87
Author: Ilya Khomyakov <[email protected]>

scsi: mpi3mr: make SAS port PHY masks 64-bit safe
   =20
This patch fixes 64-bit PHY-mask handling in the Broadcom MPI3 Storage
Controller driver under drivers/scsi/mpi3mr/. It introduces helpers to avoid
undefined behavior when constructing 64-bit PHY masks using signed 32-bit s=
hift
operations.

> diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr=
/mpi3mr_transport.c
> index 240f67a8e2e3b..d6492dddf7352 100644
> --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c
> +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c
> @@ -11,6 +11,42 @@
> =20
>  #include "mpi3mr.h"
> =20
> +/**
> + * mpi3mr_sas_phy_bit - build a bit for a firmware PHY identifier
> + * @phy_id: Firmware PHY identifier to represent in a 64-bit port mask
> + *
> + * The port mask is a u64, so every shift must be performed in a 64-bit
> + * unsigned type. Reject identifiers that cannot be represented before t=
he
> + * shift to avoid undefined behavior.
> + *
> + * Return: BIT_ULL(@phy_id) for a representable identifier, otherwise ze=
ro.
> + */
> +static u64 mpi3mr_sas_phy_bit(u8 phy_id)
> +{
> +	if (WARN_ON_ONCE(phy_id >=3D sizeof(u64) * 8))
> +		return 0;

[Severity: High]
Can this allow malicious or buggy firmware to trigger a kernel panic?

The phy_id originates from the device firmware. If a compromised or buggy
device provides a num_phys >=3D 64, the driver iterates through these and p=
asses
them to mpi3mr_sas_phy_bit(), triggering WARN_ON_ONCE().

Kernel guidelines prohibit using WARN_ON macros to validate external or
hardware-provided data because it allows an external entity to crash the
system via a Denial of Service if panic_on_warn is enabled.

[ ... ]
> @@ -1765,7 +1805,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
>  		port_idx =3D host_port_count;
>  		h_port[port_idx].sas_address =3D le64_to_cpu(sasinf->sas_address);
>  		h_port[port_idx].handle =3D attached_handle;
> -		h_port[port_idx].phy_mask =3D (1 << i);
> +		h_port[port_idx].phy_mask =3D mpi3mr_sas_phy_bit(i);
>  		h_port[port_idx].iounit_port_id =3D sas_io_unit_pg0->phy_data[i].io_un=
it_port;
>  		h_port[port_idx].lowest_phy =3D sasinf->phy_num;
>  		h_port[port_idx].used =3D 0;
>  		host_port_count++;

[Severity: High]
This isn't a bug introduced by this patch, but can a malicious or compromis=
ed
firmware trigger a heap buffer overflow here by providing a num_phys value
greater than 64?

Earlier in mpi3mr_refresh_sas_ports(), h_port is allocated with a hardcoded
size of 64 elements on the heap:

    h_port =3D kzalloc_objs(struct host_port, 64);

The loop that populates it iterates up to mrioc->sas_hba.num_phys, which is
parsed directly from the firmware's SAS IO Unit Page 0 (as an 8-bit value,
allowing up to 255).

If the firmware reports more than 64 phys and provides distinct attached
handles for them, host_port_count (tracked via port_idx) will exceed 63.
This directly results in unconstrained out-of-bounds heap writes when
initializing fields like h_port[port_idx].sas_address.

[Severity: High]
This is a pre-existing issue, but does the incorrect casting in
mpi3mr_update_mr_sas_port() cause array out-of-bounds access on 32-bit
big-endian architectures?

drivers/scsi/mpi3mr/mpi3mr_transport.c:mpi3mr_update_mr_sas_port() {
    ...
    for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
        mr_sas_phy =3D &mrioc->sas_hba.phy[i];
    ...
}

In mpi3mr_update_mr_sas_port(), phys_to_be_added is a u64 bitmask. On 32-bit
big-endian systems, unsigned long is 32 bits, and the cast points to the
most significant 32 bits (bits 32-63) of the u64.

for_each_set_bit() processes this as bits 0-31, effectively swapping the
lower and upper halves of the 64-bit mask. If a PHY ID < 32 is set, it
will be interpreted as PHY ID >=3D 32, which causes out-of-bounds access
to dynamically allocated arrays like mrioc->sas_hba.phy.

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260804142831.4365=
[email protected]?part=3D1