From: Yingjie Wang SCSI_IOCTL_SEND_COMMAND copies sense or command data to userspace while the completed request still occupies its queue tag. A fault that needs the same queue can therefore wait for a resource held by the ioctl. Save the command status and the compatibility-limited sense data, then release the request before copying to userspace. The data buffer is a separate allocation and remains valid until the existing buffer cleanup. Keep the positive SCSI status and -EFAULT return conventions unchanged. This complements the SG_IO fix by covering the legacy SCSI_IOCTL_SEND_COMMAND path. Fixes: d285203cf647 ("scsi: add support for a blk-mq based I/O path.") Link: https://lore.kernel.org/r/20261022.scsi-copyback-review.31b8d6a70f4c@outlook.com Cc: stable@vger.kernel.org Signed-off-by: Yingjie Wang --- drivers/scsi/scsi_ioctl.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index b588aa9059e3..4f97516c795c 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -538,6 +538,8 @@ static int sg_scsi_ioctl(struct request_queue *q, bool open_for_write, struct scsi_ioctl_command __user *sic) { struct request *rq; + u8 sense_buffer[16]; + unsigned int sense_len = 0; int err; unsigned int in_len, out_len, bytes, opcode, cmdlen; struct scsi_cmnd *scmd; @@ -626,17 +628,21 @@ static int sg_scsi_ioctl(struct request_queue *q, bool open_for_write, blk_execute_rq(rq, false); err = scmd->result & 0xff; /* only 8 bit SCSI status */ + if (err && scmd->sense_len && scmd->sense_buffer) { + /* limit sense len for backward compatibility */ + sense_len = min(scmd->sense_len, sizeof(sense_buffer)); + memcpy(sense_buffer, scmd->sense_buffer, sense_len); + } + blk_mq_free_request(rq); + if (err) { - if (scmd->sense_len && scmd->sense_buffer) { - /* limit sense len for backward compatibility */ - if (copy_to_user(sic->data, scmd->sense_buffer, - min(scmd->sense_len, 16U))) - err = -EFAULT; - } + if (sense_len && copy_to_user(sic->data, sense_buffer, sense_len)) + err = -EFAULT; } else { if (copy_to_user(sic->data, buffer, out_len)) err = -EFAULT; } + goto error_free_buffer; error: blk_mq_free_request(rq); -- 2.43.0