scsi: ufs: Fix unexpected values get from ufshcd_read_desc_param()
PATCH v2 1/1 scsi: ufs: Fix unexpected values get from ufshcd_read_desc_param()
Since WB feature has been added, WB related sysfs entries can be accessed even when an UFS device does not support WB feature. In that case, the descriptors which are not supported by the UFS device may be wrongly reported when they are accessed from their corrsponding sysfs entries. Fix it by adding a sanity check of parameter offset against the actual decriptor length.
--- drivers/scsi/ufs/ufshcd.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
drivers/scsi/ufs/ufshcd.c +15 -9
@@ -3184,13 +3184,19 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,/* Get the length of descriptor */ ufshcd_map_desc_id_to_length (hba, desc_id, &buff_len);if (!buff_len) { -dev_err (hba->dev,"%s: Failed to get desc length" , __func__); +dev_err (hba->dev,"%s: Failed to get desc length\n" , __func__); +return -EINVAL ; + } + +if (param_offset >= buff_len) { +dev_err (hba->dev,"%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n" , + __func__, param_offset, desc_id, buff_len);return -EINVAL ; }/* Check whether we need temp memory */ if (param_offset !=0 || param_size < buff_len) { - desc_buf =kmalloc (buff_len,GFP_KERNEL ); + desc_buf =kzalloc (buff_len,GFP_KERNEL );if (!desc_buf)return -ENOMEM ; }else {
@@ -3204,14 +3210,14 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, desc_buf, &buff_len);if (ret) { -dev_err (hba->dev,"%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d" , +dev_err (hba->dev,"%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n" , __func__, desc_id, desc_index, param_offset, ret); goto out; }/* Sanity check */ if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET ] != desc_id) { -dev_err (hba->dev,"%s: invalid desc_id %d in descriptor header" , +dev_err (hba->dev,"%s: invalid desc_id %d in descriptor header\n" , __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET ]); ret = -EINVAL ; goto out;
@@ -3221,12 +3227,12 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET ];ufshcd_update_desc_length (hba, desc_id, desc_index, buff_len); -/* Check wherher we will not copy more data, than available */ -if (is_kmalloc && (param_offset + param_size) > buff_len) - param_size = buff_len - param_offset; - -if (is_kmalloc) +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;memcpy (param_read_buf, &desc_buf[param_offset], param_size); + } out:if (is_kmalloc)kfree (desc_buf);
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Quoted 6 lines
Since WB feature has been added, WB related sysfs entries can be accessed even when an UFS device does not support WB feature. In that case, the descriptors which are not supported by the UFS device may be wrongly reported when they are accessed from their corrsponding sysfs entries. Fix it by adding a sanity check of parameter offset against the actual decriptor length.s
This should be a bug fix IMO, and be dealt with similarly like ufshcd_is_wb_attrs or ufshcd_is_wb_flag. Thanks,
Avri
Hi Avri,
Quoted 10 lines · Avri Altman
Quoted 6 lines
Since WB feature has been added, WB related sysfs entries can be accessed even when an UFS device does not support WB feature. In that case, the descriptors which are not supported by the UFS device may be wrongly reported when they are accessed from their corrsponding sysfs entries. Fix it by adding a sanity check of parameter offset against the actual decriptor length.s
This should be a bug fix IMO, and be dealt with similarly like
ufshcd_is_wb_attrsorufshcd_is_wb_flag.
Thanks,
Avri
Could you please elaborate on ufshcd_is_wb_attrs or ufshcd_is_wb_flag? Sorry that I don't quite get it.
Thanks,
Can Guo.
Quoted 9 lines · Avri Altman
Quoted 7 lines
Quoted 7 lines
Since WB feature has been added, WB related sysfs entries can be accessed
even when an UFS device does not support WB feature. In that case, the descriptors which are not supported by the UFS device may be wrongly reported when they are accessed from their corrsponding sysfs entries. Fix it by adding a sanity check of parameter offset against the actual decriptor length.s
Quoted 7 lines
Quoted 4 lines
This should be a bug fix IMO, and be dealt with similarly like
ufshcd_is_wb_attrsorufshcd_is_wb_flag.
Thanks,
AvriCould you please elaborate on
ufshcd_is_wb_attrsorufshcd_is_wb_flag? Sorry that I don't quite get it.
Since this change is only protecting illegal access from sysfs entries, I am suggesting to handle it there, just like ufshcd_is_wb_attrs or ufshcd_is_wb_flag Are doing it for flags and attributes.
Thanks,
Avri
Quoted 15 lines · Avri Altman
Quoted 8 lines · Avri Altman
Quoted 7 lines
Quoted 7 lines
Since WB feature has been added, WB related sysfs entries can be accessed
even when an UFS device does not support WB feature. In that case, the descriptors which are not supported by the UFS device may be wrongly reported when they are accessed from their corrsponding sysfs entries. Fix it by adding a sanity check of parameter offset against the actual decriptor length.sQuoted 7 lines
Quoted 4 lines
This should be a bug fix IMO, and be dealt with similarly like
ufshcd_is_wb_attrsorufshcd_is_wb_flag.
Thanks,
AvriCould you please elaborate on
ufshcd_is_wb_attrsorufshcd_is_wb_flag? Sorry that I don't quite get it.
Quoted 7 lines
Since this change is only protecting illegal access from sysfs entries, I am suggesting to handle it there, just like
ufshcd_is_wb_attrsorufshcd_is_wb_flag
Are doing it for flags and attributes.Thanks,
Avri
This is a general problem - if later we have HPB entries added into sysfs, we will hit it again. We cannot keep adding checks like ufshcd_is_xxx_attrs or ufshcd_is_xxx_flag to block them, right?
Thanks,
Can Guo.
Quoted 9 lines · Can Guo
Since WB feature has been added, WB related sysfs entries can be accessed even when an UFS device does not support WB feature. In that case, the descriptors which are not supported by the UFS device may be wrongly reported when they are accessed from their corrsponding sysfs entries. Fix it by adding a sanity check of parameter offset against the actual decriptor length.
Signed-off-by Can Guo <[email protected]>---
Quoted 65 lines
drivers/scsi/ufs/ufshcd.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)drivers/scsi/ufs/ufshcd.c +15
-9@@ -3184,13 +3184,19 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,/* Get the length of descriptor */ ufshcd_map_desc_id_to_length (hba, desc_id, &buff_len);if (!buff_len) { -dev_err (hba->dev,"%s: Failed to get desc length" , __func__); +dev_err (hba->dev,"%s: Failed to get desc length\n" , __func__); +return -EINVAL ; + } + +if (param_offset >= buff_len) { +dev_err (hba->dev,"%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n" , + __func__, param_offset, desc_id, buff_len);return -EINVAL ; }/* Check whether we need temp memory */ if (param_offset !=0 || param_size < buff_len) { - desc_buf =kmalloc (buff_len,GFP_KERNEL ); + desc_buf =kzalloc (buff_len,GFP_KERNEL );if (!desc_buf)return -ENOMEM ; }else {@@ -3204,14 +3210,14 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, desc_buf, &buff_len);if (ret) { -dev_err (hba->dev,"%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d" , +dev_err (hba->dev,"%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n" , __func__, desc_id, desc_index, param_offset, ret); goto out; }/* Sanity check */ if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET ] != desc_id) { -dev_err (hba->dev,"%s: invalid desc_id %d in descriptor header" , +dev_err (hba->dev,"%s: invalid desc_id %d in descriptor header\n" , __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET ]); ret = -EINVAL ; goto out;@@ -3221,12 +3227,12 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET ];ufshcd_update_desc_length (hba, desc_id, desc_index, buff_len); -/* Check wherher we will not copy more data, than available */ -if (is_kmalloc && (param_offset + param_size) > buff_len) - param_size = buff_len - param_offset; - -if (is_kmalloc) +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;memcpy (param_read_buf, &desc_buf[param_offset], param_size); + } out:if (is_kmalloc)kfree (desc_buf);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, Linux Foundation Collaborative Project
Martin K. Petersen
AppliedQuoted 6 lines · Can Guo
Since WB feature has been added, WB related sysfs entries can be accessed even when an UFS device does not support WB feature. In that case, the descriptors which are not supported by the UFS device may be wrongly reported when they are accessed from their corrsponding sysfs entries. Fix it by adding a sanity check of parameter offset against the actual decriptor length.
Applied to 5.10/scsi-fixes, thanks!
[1/1] scsi: ufs: Fix unexpected values from ufshcd_read_desc_param()
https://git.kernel.org/mkp/scsi/c/1699f980d87f
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering