Message ID | 20210111095927.1830311-1-jaegeuk@kernel.org |
---|---|
State | New |
Headers | show |
Series | [v3] scsi: ufs: WB is only available on LUN #0 to #7 | expand |
> > > From: Jaegeuk Kim <jaegeuk@google.com> > > Kernel stack violation when getting unit_descriptor/wb_buf_alloc_units from > rpmb lun. The reason is the unit descriptor length is different per LU. > > The lengh of Normal LU is 45, while the one of rpmb LU is 35. > > int ufshcd_read_desc_param(struct ufs_hba *hba, ...) > { > param_offset=41; > param_size=4; > buff_len=45; > ... > buff_len=35 by rpmb LU; > > if (is_kmalloc) { > /* Make sure we don't copy more data than available */ > if (param_offset + param_size > buff_len) > param_size = buff_len - param_offset; > --> param_size = 250; > memcpy(param_read_buf, &desc_buf[param_offset], param_size); > --> memcpy(param_read_buf, desc_buf+41, 250); > > [ 141.868974][ T9174] Kernel panic - not syncing: stack-protector: Kernel > stack is corrupted in: wb_buf_alloc_units_show+0x11c/0x11c > } > } > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Reviewed-by: Avri Altman <avri.altman@wdc.com>
On Mon, 11 Jan 2021 01:59:27 -0800, Jaegeuk Kim wrote: > Kernel stack violation when getting unit_descriptor/wb_buf_alloc_units from > rpmb lun. The reason is the unit descriptor length is different per LU. > > The lengh of Normal LU is 45, while the one of rpmb LU is 35. > > int ufshcd_read_desc_param(struct ufs_hba *hba, ...) > { > param_offset=41; > param_size=4; > buff_len=45; > ... > buff_len=35 by rpmb LU; > > [...] Applied to 5.12/scsi-queue, thanks! [1/1] scsi: ufs: WB is only available on LUN #0 to #7 https://git.kernel.org/mkp/scsi/c/a2fca52ee640 -- Martin K. Petersen Oracle Linux Engineering
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 08e72b7eef6a..50e90416262b 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -792,7 +792,8 @@ static ssize_t _pname##_show(struct device *dev, \ struct scsi_device *sdev = to_scsi_device(dev); \ struct ufs_hba *hba = shost_priv(sdev->host); \ u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); \ - if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun)) \ + if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun, \ + _duname##_DESC_PARAM##_puname)) \ return -EINVAL; \ return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \ lun, _duname##_DESC_PARAM##_puname, buf, _size); \ diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 14dfda735adf..580aa56965d0 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -552,13 +552,15 @@ struct ufs_dev_info { * @return: true if the lun has a matching unit descriptor, false otherwise */ static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info, - u8 lun) + u8 lun, u8 param_offset) { if (!dev_info || !dev_info->max_lu_supported) { pr_err("Max General LU supported by UFS isn't initialized\n"); return false; } - + /* WB is available only for the logical unit from 0 to 7 */ + if (param_offset == UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS) + return lun < UFS_UPIU_MAX_WB_LUN_ID; return lun == UFS_UPIU_RPMB_WLUN || (lun < dev_info->max_lu_supported); } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2a715f13fe1d..48cbd4f294dd 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3425,7 +3425,7 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, * Unit descriptors are only available for general purpose LUs (LUN id * from 0 to 7) and RPMB Well known LU. */ - if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun)) + if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun, param_offset)) return -EOPNOTSUPP; return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,