mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Merge patch series "scsi: ufs: Fix UIC result byte and BSG request handling"
Stanley Jhu <stanleyjhu@google.com> says: ufs-bsg fixes for issues found by fuzzing /dev/bsg/ufs-bsg* with syzkaller on QEMU's emulated UFS host controller and in review of v1, plus a fix for peer DME retries. Patch 1 completes failed BSG requests via bsg_job_done() so error paths do not leak the job's device reference and mapped scatterlists. Patch 2 clears the reused reply buffer so replies do not carry bytes from an earlier request. Patch 3 rejects requests shorter than the UFS BSG request structures. Patch 4 rejects UIC commands with a non-zero result byte from userspace. Patch 5 clears the stale UIC result byte and restores argument3 before peer DME retries. Patches 1-2 also address the sashiko review of the bsg reply_len patch: https://lore.kernel.org/all/sashiko-outbox-169843@kernel.org/ Tested on QEMU arm64: the reproducers no longer trigger. Link: https://patch.msgid.link/20261015001855.3450573-1-stanleyjhu@google.com Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
This commit is contained in:
commit
1b39bd7b82
|
|
@ -73,6 +73,9 @@ static int ufs_bsg_exec_advanced_rpmb_req(struct ufs_hba *hba, struct bsg_job *j
|
|||
if (hba->ufs_version < ufshci_version(4, 0) || !hba->dev_info.b_advanced_rpmb_en)
|
||||
return -EINVAL;
|
||||
|
||||
if (job->request_len < sizeof(*rpmb_request))
|
||||
return -EINVAL;
|
||||
|
||||
if (rpmb_request->ehs_req.length != 2 || rpmb_request->ehs_req.ehs_type != 1)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -140,7 +143,12 @@ static int ufs_bsg_request(struct bsg_job *job)
|
|||
int ret;
|
||||
bool rpmb = false;
|
||||
|
||||
bsg_reply->reply_payload_rcv_len = 0;
|
||||
memset(job->reply, 0, job->reply_len);
|
||||
|
||||
if (job->request_len < sizeof(*bsg_request)) {
|
||||
ret = -EINVAL;
|
||||
goto out_complete;
|
||||
}
|
||||
|
||||
ufshcd_rpm_get_sync(hba);
|
||||
|
||||
|
|
@ -171,6 +179,10 @@ static int ufs_bsg_request(struct bsg_job *job)
|
|||
break;
|
||||
case UPIU_TRANSACTION_UIC_CMD:
|
||||
memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE);
|
||||
if (uc.argument2 & MASK_UIC_COMMAND_RESULT) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = ufshcd_send_bsg_uic_cmd(hba, &uc);
|
||||
if (ret)
|
||||
dev_err(hba->dev, "send uic cmd: error code %d\n", ret);
|
||||
|
|
@ -194,15 +206,14 @@ static int ufs_bsg_request(struct bsg_job *job)
|
|||
out:
|
||||
ufshcd_rpm_put_sync(hba);
|
||||
kfree(buff);
|
||||
out_complete:
|
||||
bsg_reply->result = ret;
|
||||
/* complete the job here only if no error */
|
||||
if (ret == 0) {
|
||||
if (ret == 0)
|
||||
job->reply_len = rpmb ? sizeof(struct ufs_rpmb_reply) :
|
||||
sizeof(struct ufs_bsg_reply);
|
||||
bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len);
|
||||
}
|
||||
bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4400,9 +4400,12 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
|
|||
do {
|
||||
/* for peer attributes we retry upon failure */
|
||||
ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_dbg(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
|
||||
set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
|
||||
uic_cmd.argument2 &= ~MASK_UIC_COMMAND_RESULT;
|
||||
uic_cmd.argument3 = mib_val;
|
||||
}
|
||||
} while (ret && peer && --retries);
|
||||
|
||||
if (ret)
|
||||
|
|
@ -4467,9 +4470,11 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
|
|||
do {
|
||||
/* for peer attributes we retry upon failure */
|
||||
ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_dbg(hba->dev, "%s: attr-id 0x%x error code %d\n",
|
||||
get, UIC_GET_ATTR_ID(attr_sel), ret);
|
||||
uic_cmd.argument2 &= ~MASK_UIC_COMMAND_RESULT;
|
||||
}
|
||||
} while (ret && peer && --retries);
|
||||
|
||||
if (ret)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user