All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Haotian Zhang" <vulab@iscas.ac.cn>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH] scsi: hpsa: fix divide-by-zero in hpsa_scsi_ioaccel_raid_map
Date: Fri, 14 Aug 2026 09:42:28 +0000	[thread overview]
Message-ID: <20260814094229.42DF31F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260814090015.10207-1-vulab@iscas.ac.cn>

Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:

New issues:
- [High] The patch introduces a Time-Of-Check to Time-Of-Use (TOCTOU) vulnerability due to a double fetch of `map->strip_size`, which defeats the newly added divide-by-zero check.
- [Low] The patch calls an undeclared and undefined function `hpsa_turn_off_ioaccel_for_device()`, which will cause a build and linker failure.

Pre-existing issues:
- [Critical] The block address parsing for SCSI `READ_6` and `WRITE_6` commands ignores the top 5 bits of the 21-bit LBA, leading to silent data corruption.
- [High] The controller-provided `map->row_cnt` field is used as a modulo divisor without being validated against zero, leading to a divide-by-zero panic.
- [High] A 32-bit integer overflow when calculating `stripesize` can result in a divisor of 0, bypassing safety checks and leading to a divide-by-zero crash.
- [High] The driver blindly trusts controller-supplied values to enforce safety using multiple `BUG_ON()` assertions, creating trivial vectors where malformed firmware data can panic the host.
- [High] In `hpsa_figure_phys_disk_ptrs`, a signed integer overflow when computing `nraid_map_entries` can bypass the upper-bound array check, leading to a NULL pointer dereference on subsequent I/O.
--

--- Patch [1]: [PATCH] scsi: hpsa: fix divide-by-zero in hpsa_scsi_ioaccel_raid_map ---
commit 3421092ab4fbde9690cdb0b8f3136415015aac53
Author: Haotian Zhang <vulab@iscas.ac.cn>

scsi: hpsa: fix divide-by-zero in hpsa_scsi_ioaccel_raid_map

hpsa_scsi_ioaccel_raid_map() divides by blocks_per_row, the product of
data_disks_per_row and strip_size, two controller-supplied RAID map
fields that are never validated.  If either field is zero, the
unguarded division raises a divide-by-zero exception on every I/O to an
offload-enabled logical volume.

Check blocks_per_row for zero as soon as it is computed.  If it is
zero, turn off ioaccel for the device and return IO_ACCEL_INELIGIBLE.

> --- a/drivers/scsi/hpsa.c
> +++ b/drivers/scsi/hpsa.c
> @@ -4444,6 +4444,10 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
>  	/* calculate stripe information for the request */
>  	blocks_per_row = le16_to_cpu(map->data_disks_per_row) *
>  				le16_to_cpu(map->strip_size);
> +	if (blocks_per_row == 0) {
> +		hpsa_turn_off_ioaccel_for_device(dev);

[Severity: Low]
Does this break the build? The function hpsa_turn_off_ioaccel_for_device does
not appear to be declared or defined anywhere, which could lead to an
implicit function declaration and undefined reference at link time.

> +		return IO_ACCEL_INELIGIBLE;
> +	}
>  	strip_size = le16_to_cpu(map->strip_size);

[Severity: High]
Could this second fetch of map->strip_size reintroduce the divide-by-zero
issue? Since the I/O path executes locklessly with respect to device
configuration updates, a concurrent update could change map->strip_size to
zero right after the blocks_per_row check, causing the subsequent operations
using strip_size to fault.

[ ... ]

While reviewing this area, I noticed a few pre-existing issues in the same
driver that might be worth addressing:

drivers/scsi/hpsa.c:hpsa_scsi_ioaccel_raid_map() {
    ...
    map_row = ((u32)(first_row >> map->parity_rotation_shift)) %
              le16_to_cpu(map->row_cnt);

[Severity: High]
This isn't a bug introduced by this patch, but does this modulo operation
risk a divide-by-zero exception? The controller-provided map->row_cnt field
appears to be used here without being validated against zero.

[ ... ]

drivers/scsi/hpsa.c:hpsa_scsi_ioaccel_raid_map() {
    ...
    r5or6_blocks_per_row =
        le16_to_cpu(map->strip_size) *
        le16_to_cpu(map->data_disks_per_row);
    BUG_ON(r5or6_blocks_per_row == 0);
    stripesize = r5or6_blocks_per_row *
        le16_to_cpu(map->layout_map_count);

[Severity: High]
This is a pre-existing issue, but can this stripesize calculation silently
overflow to zero? Both r5or6_blocks_per_row and layout_map_count are
evaluated as signed 32-bit integers. If the controller provides specific
values (such as strip_size = 16384, data_disks_per_row = 8, and
layout_map_count = 32768), the product evaluates to exactly 2^32. This wraps
to 0 when stored in the u32 stripesize variable, causing a divide-by-zero
crash later.

[ ... ]

drivers/scsi/hpsa.c:hpsa_scsi_ioaccel_raid_map() {
    ...
    case HPSA_RAID_1:
        /* Handles load balance across RAID 1 members.
         * (2-drive R1 and R10 with even # of drives.)
         * Appropriate for SSDs, not optimal for HDDs
         */
        BUG_ON(le16_to_cpu(map->layout_map_count) != 2);

[Severity: High]
This is a pre-existing issue, but is it safe to use BUG_ON() to assert
structural properties of the raid_map? A buggy or compromised controller
could provide a mismatched layout map count, which would trigger this
assertion and panic the host immediately upon processing an I/O instead of
safely falling back to standard non-accelerated I/O.

[ ... ]

drivers/scsi/hpsa.c:hpsa_scsi_ioaccel_raid_map() {
    ...
    switch (cmd->cmnd[0]) {
    case WRITE_6:
        is_write = 1;
    case READ_6:
        first_block =
            (((u64) cmd->cmnd[2]) << 8) |
            cmd->cmnd[3];

[Severity: Critical]
This is a pre-existing issue, but does this LBA reconstruction silently
truncate the address? The standard 6-byte SCSI command format places the
upper 5 bits of the 21-bit LBA into byte 1 (cmd->cmnd[1]). By ignoring
byte 1 entirely, any application issuing a READ_6 or WRITE_6 command to an
offload-enabled device targeting an LBA greater than or equal to 65536 will
have the address truncated, resulting in operations against the wrong disk
region.

[ ... ]

drivers/scsi/hpsa.c:hpsa_figure_phys_disk_ptrs() {
    ...
    int nraid_map_entries = le16_to_cpu(map->row_cnt) *
                            le16_to_cpu(map->layout_map_count) *
                            total_disks_per_row;
    if (nraid_map_entries > RAID_MAP_MAX_ENTRIES) {

[Severity: High]
This isn't a bug introduced by this patch, but can this multiplication
overflow? Evaluated as a signed 32-bit integer, a maliciously crafted RAID
map from the controller could cause this product to exceed INT_MAX and wrap
to a negative value.

This would bypass the upper-bound check against RAID_MAP_MAX_ENTRIES,
leaving elements in the phys_disk array initialized as NULL. During I/O
submission, fetching and dereferencing this NULL pointer to access
ioaccel_handle will result in a kernel panic.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260814090015.10207-1-vulab@iscas.ac.cn?part=1

      reply	other threads:[~2026-08-14  9:42 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-14  9:00 [PATCH] scsi: hpsa: fix divide-by-zero in hpsa_scsi_ioaccel_raid_map Haotian Zhang
2026-08-14  9:42 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260814094229.42DF31F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vulab@iscas.ac.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.