Thread (11 messages) 11 messages, 6 authors, 2021-01-04

Re: [PATCH 2/3] scsi: megaraid_sas: check user-provided offsets

From: Arnd Bergmann <arnd@kernel.org>
Date: 2021-01-03 16:27:43
Also in: linux-scsi, lkml

On Thu, Dec 31, 2020 at 1:15 AM Phil Oester [off-list ref] wrote:
On Tue, Sep 08, 2020 at 11:36:22PM +0200, Arnd Bergmann wrote:
quoted
It sounds unwise to let user space pass an unchecked 32-bit
offset into a kernel structure in an ioctl. This is an unsigned
variable, so checking the upper bound for the size of the structure
it points into is sufficient to avoid data corruption, but as
the pointer might also be unaligned, it has to be written carefully
as well.

While I stumbled over this problem by reading the code, I did not
continue checking the function for further problems like it.
Sorry for replying to an ancient thread, but this patch just recently
made it into 5.10.3 and has caused unintended consequences.  On Dell
servers with PERC RAID controllers, booting 5.10.3+ with this patch
causes a PCI parity error.  Specifically:

Event Message: A PCI parity error was detected on a component at bus 0 device 5 function 0.
Severity: Critical
Message ID: PCI1308

I reverted this single patch and the errors went away.

Thoughts?
Thank you for the report and bisecting the issue, and sorry this broke
your system!

Fortunately, the patch is fairly small, so there are only a limited number
of things that could go wrong. I haven't tried to analyze that message,
but I have two ideas:

a) The added ioc->sense_off check gets triggered and the code relies
  on the data being written outside of the structure

b) the address actually needs to always be written as a 64-bit value
    regardless of the instance->consistent_mask_64bit flag, as the
   driver did before. This looked like it was done in error.

Can you try the patch below instead of the revert and see if that
resolves the regression, and if it triggers the warning message I
add?

       Arnd
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c
b/drivers/scsi/megaraid/megaraid_sas_base.c
index 6e4bf05c6d77..248063a4148b 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -8194,8 +8194,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
                /* make sure the pointer is part of the frame */
                if (ioc->sense_off >
                    (sizeof(union megasas_frame) - sizeof(__le64))) {
-                       error = -EINVAL;
-                       goto out;
+                       pr_warn("possible out of bounds access offset
%d\n", ioc->sense_off);
                }

                sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
@@ -8209,7 +8208,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
                if (instance->consistent_mask_64bit)
                        put_unaligned_le64(sense_handle, sense_ptr);
                else
-                       put_unaligned_le32(sense_handle, sense_ptr);
+                       put_unaligned_le64(sense_handle, sense_ptr);
        }

        /*
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help