scsi: ufs: scsi_get_lba error fix by check cmd opcode
Subsystems (2)
PATCH 1/1 scsi: ufs: scsi_get_lba error fix by check cmd opcode
From: Peter Wang <[email protected]>
When ufs init without scmd->device->sector_size set, scsi_get_lba will get a wrong shift number and ubsan error. shift exponent 4294967286 is too large for 64-bit type 'sector_t' (aka 'unsigned long long')
Call scsi_get_lba only when opcode is READ_10/WRITE_10/UNMAP.
--- drivers/scsi/ufs/ufshcd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/scsi/ufs/ufshcd.c +3 -2
@@ -367,7 +367,7 @@ static void ufshcd_add_uic_command_trace(struct ufs_hba *hba,static void ufshcd_add_command_trace (struct ufs_hba *hba,unsigned int tag,enum ufs_trace_str_t str_t) { -u64 lba; +u64 lba =0 ;u8 opcode =0 , group_id =0 ;u32 intr, doorbell;struct ufshcd_lrb *lrbp = &hba->lrb[tag];
@@ -384,7 +384,6 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,return ; opcode = cmd->cmnd[0 ]; - lba =scsi_get_lba (cmd);if (opcode ==READ_10 || opcode ==WRITE_10 ) {/*
@@ -392,6 +391,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,*/ transfer_len =be32_to_cpu (lrbp->ucd_req_ptr->sc.exp_data_transfer_len); + lba =scsi_get_lba (cmd);if (opcode ==WRITE_10 ) group_id = lrbp->cmd->cmnd[6 ]; }else if (opcode ==UNMAP ) {
@@ -399,6 +399,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,* The number of Bytes to be unmapped beginning with the lba. */ transfer_len =blk_rq_bytes (rq); + lba =scsi_get_lba (cmd); } intr =ufshcd_readl (hba,REG_INTERRUPT_STATUS );
Signature · 7 lines
2.18.0 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
Quoted 5 lines · On 3/7/22 03:17, [email protected] wrote:
When ufs init without
scmd->device->sector_sizeset,scsi_get_lbawill get a wrong shift number and ubsan error. shift exponent 4294967286 is too large for 64-bit type 'sector_t' (aka 'unsigned long long')
Callscsi_get_lbaonly when opcode is READ_10/WRITE_10/UNMAP.
Hmm ... how can it happen that sector_size has not been set? I think that can only happen for LUNs of type SCSI DISK if sd_read_capacity() fails? If sd_read_capacity() fails I think the sd driver is expected to set the capacity to zero?
rq->__sector == -1 for flush requests and the type of that member (sector_t) is unsigned. I think that it is allowed for a shift left of an unsigned type to overflow. From the C standard: "The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2 , reduced modulo one more than the maximum value representable in the result type."
Thanks,
Bart.
Hi Bart,
When scsi scan in scsi_probe_lun function, there have much INQUIRY(0x12) command with sector_size is 0.
unsigned int shift will get 4294967286 (signed -10) and an sector_t type is 64 bit. Shift 64bit right 4294967286 will have ubsan error because ubsan think shift number should be wrong and return 0 always.
BTW, we only need the lba information when read/write/unmap. Other command such as INQUIRY is useless.
static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd)
{
unsigned int shift = ilog2(scmd->device->sector_size) - SECTOR_SHIFT; <= shift is 4294967286 (-1-9=-10)
return blk_rq_pos(scsi_cmd_to_rq(scmd)) >> shift; <= sector_t type >> 4294967286 will always get 0. }
Quoted 9 lines · Bart Van Assche
Hmm ... how can it happen that
sector_sizehas not been set? I think that can only happen for LUNs of type SCSI DISK ifsd_read_capacity()fails? Ifsd_read_capacity()fails I think the sd driver is expected to set the capacity to zero?
rq->__sector== -1 for flush requests and the type of that member (sector_t) is unsigned. I think that it is allowed for a shift left of an unsigned type to overflow. From the C standard: "The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2 , reduced modulo one more than the maximum value representable in the result type."Thanks,
Bart.
Quoted 5 lines · On 3/7/22 03:17, [email protected] wrote:
When ufs init without
scmd->device->sector_sizeset,scsi_get_lbawill get a wrong shift number and ubsan error. shift exponent 4294967286 is too large for 64-bit type 'sector_t' (aka 'unsigned long long')
Callscsi_get_lbaonly when opcode is READ_10/WRITE_10/UNMAP.
Martin K. Petersen
AppliedQuoted 5 lines
When ufs init without
scmd->device->sector_sizeset,scsi_get_lbawill get a wrong shift number and ubsan error. shift exponent 4294967286 is too large for 64-bit type 'sector_t' (aka 'unsigned long long') Callscsi_get_lbaonly when opcode is READ_10/WRITE_10/UNMAP.
Applied to 5.18/scsi-staging, thanks!
Signature · 6 lines
Martin K. Petersen Oracle Linux Engineering _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
Martin K. Petersen
AppliedQuoted 9 lines · On Mon, 7 Mar 2022 19:17:52 +0800, [email protected] wrote:
From: Peter Wang <[email protected]>
When ufs init without
scmd->device->sector_sizeset,scsi_get_lbawill get a wrong shift number and ubsan error. shift exponent 4294967286 is too large for 64-bit type 'sector_t' (aka 'unsigned long long')
Callscsi_get_lbaonly when opcode is READ_10/WRITE_10/UNMAP.[...]
Applied to 5.18/scsi-queue, thanks!
[1/1] scsi: ufs: scsi_get_lba error fix by check cmd opcode
https://git.kernel.org/mkp/scsi/c/2bd3b6b75946
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering