]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: ufs: core: scsi_get_lba() error fix
authorPeter Wang <peter.wang@mediatek.com>
Mon, 7 Mar 2022 11:17:52 +0000 (19:17 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 9 Mar 2022 03:52:09 +0000 (22:52 -0500)
When ufs initializes without scmd->device->sector_size set, scsi_get_lba()
will get a wrong shift number and trigger an ubsan error.  The shift
exponent 4294967286 is too large for the 64-bit type 'sector_t' (aka
'unsigned long long').

Call scsi_get_lba() only when opcode is READ_10/WRITE_10/UNMAP.

Link: https://lore.kernel.org/r/20220307111752.10465-1-peter.wang@mediatek.com
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/ufs/ufshcd.c

index 59c5135dcf9405683667bc0e66c81c2bae907c2c..0899d5b8cdad6a49faafa34720533ddfdfc92715 100644 (file)
@@ -365,7 +365,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];
@@ -382,7 +382,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) {
                /*
@@ -390,6 +389,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) {
@@ -397,6 +397,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);