Skip to content

Commit

Permalink
scsi: megaraid_sas: Check user-provided offsets
Browse files Browse the repository at this point in the history
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.

Link: https://lore.kernel.org/r/[email protected]
Fixes: c4a3e0a ("[SCSI] MegaRAID SAS RAID: new driver")
Cc: <[email protected]> # v2.6.15+
Reviewed-by: Christoph Hellwig <[email protected]>
Signed-off-by: Arnd Bergmann <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
arndb authored and martinkpetersen committed Nov 5, 2020
1 parent 0770542 commit 381d34e
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions drivers/scsi/megaraid/megaraid_sas_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -8134,7 +8134,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
int error = 0, i;
void *sense = NULL;
dma_addr_t sense_handle;
unsigned long *sense_ptr;
void *sense_ptr;
u32 opcode = 0;
int ret = DCMD_SUCCESS;

Expand Down Expand Up @@ -8257,19 +8257,25 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
}

if (ioc->sense_len) {
/* make sure the pointer is part of the frame */
if (ioc->sense_off >
(sizeof(union megasas_frame) - sizeof(__le64))) {
error = -EINVAL;
goto out;
}

sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
&sense_handle, GFP_KERNEL);
if (!sense) {
error = -ENOMEM;
goto out;
}

sense_ptr =
(unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
sense_ptr = (void *)cmd->frame + ioc->sense_off;
if (instance->consistent_mask_64bit)
*sense_ptr = cpu_to_le64(sense_handle);
put_unaligned_le64(sense_handle, sense_ptr);
else
*sense_ptr = cpu_to_le32(sense_handle);
put_unaligned_le32(sense_handle, sense_ptr);
}

/*
Expand Down

0 comments on commit 381d34e

Please sign in to comment.