* [PATCH 0/3] scsi: check the whole result in some places
@ 2021-03-19 3:01 Jason Yan
2021-03-19 3:01 ` [PATCH 1/3] scsi: check the whole result for reading write protect flag Jason Yan
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Jason Yan @ 2021-03-19 3:01 UTC (permalink / raw)
To: axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb
Cc: linux-scsi, Jason Yan
Some bugs have been found related to the result of the command been
returned by the driver or the middle layer in some cases. Such as in
scsi_queue_rq() when the device is offline only the host byte is set.
Jason Yan (3):
scsi: check the whole result for reading write protect flag
scsi: only copy data to user when the whole result is good
scsi: switch to use scsi_result_is_good() in
scsi_result_to_blk_status()
block/scsi_ioctl.c | 2 +-
drivers/scsi/scsi_lib.c | 2 +-
drivers/scsi/sd.c | 6 +++---
include/scsi/scsi.h | 13 +++++++++++++
4 files changed, 18 insertions(+), 5 deletions(-)
--
2.25.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/3] scsi: check the whole result for reading write protect flag
2021-03-19 3:01 [PATCH 0/3] scsi: check the whole result in some places Jason Yan
@ 2021-03-19 3:01 ` Jason Yan
2021-03-19 7:55 ` Hannes Reinecke
2021-03-25 2:50 ` Martin K. Petersen
2021-03-19 3:01 ` [PATCH 2/3] scsi: only copy data to user when the whole result is good Jason Yan
2021-03-19 3:01 ` [PATCH 3/3] scsi: switch to use scsi_result_is_good() in scsi_result_to_blk_status() Jason Yan
2 siblings, 2 replies; 10+ messages in thread
From: Jason Yan @ 2021-03-19 3:01 UTC (permalink / raw)
To: axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb
Cc: linux-scsi, Jason Yan
When the scsi device status is offline, mode sense command will return a
result with only DID_NO_CONNECT set. Then in sd_read_write_protect_flag(),
only status byte of the result is checked, we still consider the command
returned good, and read sdkp->write_prot from the buffer. And because of
bug [1], garbage data is copied to the buffer, the disk sometimes
be set readonly. When the scsi device is set running again, users cannot
write data to the disk.
Fix this by check the whole result returned by the driver.
[1] https://patchwork.kernel.org/project/linux-block/patch/20210318122621.330010-1-yanaijie@huawei.com/
Signed-off-by: Jason Yan <yanaijie@huawei.com>
---
drivers/scsi/sd.c | 6 +++---
include/scsi/scsi.h | 13 +++++++++++++
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ed0b1bb99f08..16f8cd2895fd 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2669,18 +2669,18 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
* 5: Illegal Request, Sense Code 24: Invalid field in
* CDB.
*/
- if (!scsi_status_is_good(res))
+ if (!scsi_result_is_good(res))
res = sd_do_mode_sense(sdkp, 0, 0, buffer, 4, &data, NULL);
/*
* Third attempt: ask 255 bytes, as we did earlier.
*/
- if (!scsi_status_is_good(res))
+ if (!scsi_result_is_good(res))
res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 255,
&data, NULL);
}
- if (!scsi_status_is_good(res)) {
+ if (!scsi_result_is_good(res)) {
sd_first_printk(KERN_WARNING, sdkp,
"Test WP failed, assume Write Enabled\n");
} else {
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index e75cca25338a..db0f346a31b2 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -55,6 +55,19 @@ static inline int scsi_status_is_good(int status)
(status == SAM_STAT_COMMAND_TERMINATED));
}
+/** scsi_result_is_good - check the result return.
+ *
+ * @result: the result passed up from the driver (including host and
+ * driver components)
+ *
+ * Drivers may only set other bytes but not status byte.
+ * This checks both the status byte and other bytes.
+ */
+static inline int scsi_result_is_good(int result)
+{
+ return scsi_status_is_good(result) && (result & ~0xff) == 0;
+}
+
/*
* standard mode-select header prepended to all mode-select commands
--
2.25.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/3] scsi: only copy data to user when the whole result is good
2021-03-19 3:01 [PATCH 0/3] scsi: check the whole result in some places Jason Yan
2021-03-19 3:01 ` [PATCH 1/3] scsi: check the whole result for reading write protect flag Jason Yan
@ 2021-03-19 3:01 ` Jason Yan
2021-03-19 7:56 ` Hannes Reinecke
2021-03-19 3:01 ` [PATCH 3/3] scsi: switch to use scsi_result_is_good() in scsi_result_to_blk_status() Jason Yan
2 siblings, 1 reply; 10+ messages in thread
From: Jason Yan @ 2021-03-19 3:01 UTC (permalink / raw)
To: axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb
Cc: linux-scsi, Jason Yan
When the scsi device status is offline, mode sense command will return a
result with only DID_NO_CONNECT set. Then in sg_scsi_ioctl(),
only status byte of the result is checked, and because of
bug [1], garbage data is copied to the userspace.
Only copy the buffer to userspace when the whole result is good.
[1] https://patchwork.kernel.org/project/linux-block/patch/20210318122621.330010-1-yanaijie@huawei.com/
Signed-off-by: Jason Yan <yanaijie@huawei.com>
---
block/scsi_ioctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 6599bac0a78c..359bf0003af4 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -503,7 +503,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
if (copy_to_user(sic->data, req->sense, bytes))
err = -EFAULT;
}
- } else {
+ } else if (scsi_result_is_good(req->result)) {
if (copy_to_user(sic->data, buffer, out_len))
err = -EFAULT;
}
--
2.25.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/3] scsi: switch to use scsi_result_is_good() in scsi_result_to_blk_status()
2021-03-19 3:01 [PATCH 0/3] scsi: check the whole result in some places Jason Yan
2021-03-19 3:01 ` [PATCH 1/3] scsi: check the whole result for reading write protect flag Jason Yan
2021-03-19 3:01 ` [PATCH 2/3] scsi: only copy data to user when the whole result is good Jason Yan
@ 2021-03-19 3:01 ` Jason Yan
2021-03-19 7:56 ` Hannes Reinecke
2 siblings, 1 reply; 10+ messages in thread
From: Jason Yan @ 2021-03-19 3:01 UTC (permalink / raw)
To: axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb
Cc: linux-scsi, Jason Yan
Use scsi_result_is_good() to simplify the code.
Signed-off-by: Jason Yan <yanaijie@huawei.com>
---
drivers/scsi/scsi_lib.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7d52a11e1b61..d1ec9f6a93f0 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -626,7 +626,7 @@ static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
* to handle the case when a SCSI LLD sets result to
* DRIVER_SENSE << 24 without setting SAM_STAT_CHECK_CONDITION.
*/
- if (scsi_status_is_good(result) && (result & ~0xff) == 0)
+ if (scsi_result_is_good(result))
return BLK_STS_OK;
return BLK_STS_IOERR;
case DID_TRANSPORT_FAILFAST:
--
2.25.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] scsi: check the whole result for reading write protect flag
2021-03-19 3:01 ` [PATCH 1/3] scsi: check the whole result for reading write protect flag Jason Yan
@ 2021-03-19 7:55 ` Hannes Reinecke
2021-03-25 2:50 ` Martin K. Petersen
1 sibling, 0 replies; 10+ messages in thread
From: Hannes Reinecke @ 2021-03-19 7:55 UTC (permalink / raw)
To: Jason Yan, axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb
Cc: linux-scsi
On 3/19/21 4:01 AM, Jason Yan wrote:
> When the scsi device status is offline, mode sense command will return a
> result with only DID_NO_CONNECT set. Then in sd_read_write_protect_flag(),
> only status byte of the result is checked, we still consider the command
> returned good, and read sdkp->write_prot from the buffer. And because of
> bug [1], garbage data is copied to the buffer, the disk sometimes
> be set readonly. When the scsi device is set running again, users cannot
> write data to the disk.
>
> Fix this by check the whole result returned by the driver.
>
> [1] https://patchwork.kernel.org/project/linux-block/patch/20210318122621.330010-1-yanaijie@huawei.com/
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> ---
> drivers/scsi/sd.c | 6 +++---
> include/scsi/scsi.h | 13 +++++++++++++
> 2 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index ed0b1bb99f08..16f8cd2895fd 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -2669,18 +2669,18 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
> * 5: Illegal Request, Sense Code 24: Invalid field in
> * CDB.
> */
> - if (!scsi_status_is_good(res))
> + if (!scsi_result_is_good(res))
> res = sd_do_mode_sense(sdkp, 0, 0, buffer, 4, &data, NULL);
>
> /*
> * Third attempt: ask 255 bytes, as we did earlier.
> */
> - if (!scsi_status_is_good(res))
> + if (!scsi_result_is_good(res))
> res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 255,
> &data, NULL);
> }
>
> - if (!scsi_status_is_good(res)) {
> + if (!scsi_result_is_good(res)) {
> sd_first_printk(KERN_WARNING, sdkp,
> "Test WP failed, assume Write Enabled\n");
> } else {
> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
> index e75cca25338a..db0f346a31b2 100644
> --- a/include/scsi/scsi.h
> +++ b/include/scsi/scsi.h
> @@ -55,6 +55,19 @@ static inline int scsi_status_is_good(int status)
> (status == SAM_STAT_COMMAND_TERMINATED));
> }
>
> +/** scsi_result_is_good - check the result return.
> + *
> + * @result: the result passed up from the driver (including host and
> + * driver components)
> + *
> + * Drivers may only set other bytes but not status byte.
> + * This checks both the status byte and other bytes.
> + */
> +static inline int scsi_result_is_good(int result)
> +{
> + return scsi_status_is_good(result) && (result & ~0xff) == 0;
> +}
> +
>
> /*
> * standard mode-select header prepended to all mode-select commands
>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] scsi: only copy data to user when the whole result is good
2021-03-19 3:01 ` [PATCH 2/3] scsi: only copy data to user when the whole result is good Jason Yan
@ 2021-03-19 7:56 ` Hannes Reinecke
2021-03-19 8:22 ` Jason Yan
0 siblings, 1 reply; 10+ messages in thread
From: Hannes Reinecke @ 2021-03-19 7:56 UTC (permalink / raw)
To: Jason Yan, axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb
Cc: linux-scsi
On 3/19/21 4:01 AM, Jason Yan wrote:
> When the scsi device status is offline, mode sense command will return a
> result with only DID_NO_CONNECT set. Then in sg_scsi_ioctl(),
> only status byte of the result is checked, and because of
> bug [1], garbage data is copied to the userspace.
>
> Only copy the buffer to userspace when the whole result is good.
>
> [1] https://patchwork.kernel.org/project/linux-block/patch/20210318122621.330010-1-yanaijie@huawei.com/
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> ---
> block/scsi_ioctl.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
> index 6599bac0a78c..359bf0003af4 100644
> --- a/block/scsi_ioctl.c
> +++ b/block/scsi_ioctl.c
> @@ -503,7 +503,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
> if (copy_to_user(sic->data, req->sense, bytes))
> err = -EFAULT;
> }
> - } else {
> + } else if (scsi_result_is_good(req->result)) {
> if (copy_to_user(sic->data, buffer, out_len))
> err = -EFAULT;
> }
>
Hmm. Not sure about this one.
The prime motivator behind sg is to get _precisely_ all flags of the
command, and not do in-kernel error handling.
So one could argue that this behaviour is intentional, and would break
existing use-cases.
Doug?
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] scsi: switch to use scsi_result_is_good() in scsi_result_to_blk_status()
2021-03-19 3:01 ` [PATCH 3/3] scsi: switch to use scsi_result_is_good() in scsi_result_to_blk_status() Jason Yan
@ 2021-03-19 7:56 ` Hannes Reinecke
0 siblings, 0 replies; 10+ messages in thread
From: Hannes Reinecke @ 2021-03-19 7:56 UTC (permalink / raw)
To: Jason Yan, axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb
Cc: linux-scsi
On 3/19/21 4:01 AM, Jason Yan wrote:
> Use scsi_result_is_good() to simplify the code.
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> ---
> drivers/scsi/scsi_lib.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index 7d52a11e1b61..d1ec9f6a93f0 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -626,7 +626,7 @@ static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
> * to handle the case when a SCSI LLD sets result to
> * DRIVER_SENSE << 24 without setting SAM_STAT_CHECK_CONDITION.
> */
> - if (scsi_status_is_good(result) && (result & ~0xff) == 0)
> + if (scsi_result_is_good(result))
> return BLK_STS_OK;
> return BLK_STS_IOERR;
> case DID_TRANSPORT_FAILFAST:
>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] scsi: only copy data to user when the whole result is good
2021-03-19 7:56 ` Hannes Reinecke
@ 2021-03-19 8:22 ` Jason Yan
0 siblings, 0 replies; 10+ messages in thread
From: Jason Yan @ 2021-03-19 8:22 UTC (permalink / raw)
To: Hannes Reinecke, axboe, ming.lei, hch, keescook, kbusch,
linux-block, martin.petersen, jejb
Cc: linux-scsi
Hi Hannes,
在 2021/3/19 15:56, Hannes Reinecke 写道:
> On 3/19/21 4:01 AM, Jason Yan wrote:
>> When the scsi device status is offline, mode sense command will return a
>> result with only DID_NO_CONNECT set. Then in sg_scsi_ioctl(),
>> only status byte of the result is checked, and because of
>> bug [1], garbage data is copied to the userspace.
>>
>> Only copy the buffer to userspace when the whole result is good.
>>
>> [1]
>> https://patchwork.kernel.org/project/linux-block/patch/20210318122621.330010-1-yanaijie@huawei.com/
>>
>>
>> Signed-off-by: Jason Yan <yanaijie@huawei.com>
>> ---
>> block/scsi_ioctl.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
>> index 6599bac0a78c..359bf0003af4 100644
>> --- a/block/scsi_ioctl.c
>> +++ b/block/scsi_ioctl.c
>> @@ -503,7 +503,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct
>> gendisk *disk, fmode_t mode,
>> if (copy_to_user(sic->data, req->sense, bytes))
>> err = -EFAULT;
>> }
>> - } else {
>> + } else if (scsi_result_is_good(req->result)) {
>> if (copy_to_user(sic->data, buffer, out_len))
>> err = -EFAULT;
>> }
>>
> Hmm. Not sure about this one.
> The prime motivator behind sg is to get _precisely_ all flags of the
> command, and not do in-kernel error handling.
> So one could argue that this behaviour is intentional, and would break
> existing use-cases.
>
Thanks for the review.
The existing usersapce can do nothing with the uninitialized data. Or
the driver or disk may fill some data and at the same time set host_byte
or driver_byte to non-zero? I'm not sure about this. And the return
value of sg_scsi_ioctl() just get the status byte(only 8 bit), how can
the users know about this situation?
Thanks,
Jason
> Doug?
>
> Cheers,
>
> Hannes
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] scsi: check the whole result for reading write protect flag
2021-03-19 3:01 ` [PATCH 1/3] scsi: check the whole result for reading write protect flag Jason Yan
2021-03-19 7:55 ` Hannes Reinecke
@ 2021-03-25 2:50 ` Martin K. Petersen
2021-03-27 6:57 ` Jason Yan
1 sibling, 1 reply; 10+ messages in thread
From: Martin K. Petersen @ 2021-03-25 2:50 UTC (permalink / raw)
To: Jason Yan
Cc: axboe, ming.lei, hch, keescook, kbusch, linux-block,
martin.petersen, jejb, linux-scsi
Hi Jason!
> @@ -55,6 +55,19 @@ static inline int scsi_status_is_good(int status)
> (status == SAM_STAT_COMMAND_TERMINATED));
> }
>
> +/** scsi_result_is_good - check the result return.
> + *
> + * @result: the result passed up from the driver (including host and
> + * driver components)
> + *
> + * Drivers may only set other bytes but not status byte.
> + * This checks both the status byte and other bytes.
> + */
> +static inline int scsi_result_is_good(int result)
> +{
> + return scsi_status_is_good(result) && (result & ~0xff) == 0;
> +}
> +
>
> /*
> * standard mode-select header prepended to all mode-select commands
Instead of introducing a "don't be broken" variant of
scsi_status_is_good(), I'd prefer you to fix the latter to do the right
thing wrt. offline devices.
There aren't a ton of scsi_result_is_good() call sites to check. And I
suspect that most of them wouldn't actually consider the DID_NO_CONNECT
scenario to be "good".
--
Martin K. Petersen Oracle Linux Engineering
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] scsi: check the whole result for reading write protect flag
2021-03-25 2:50 ` Martin K. Petersen
@ 2021-03-27 6:57 ` Jason Yan
0 siblings, 0 replies; 10+ messages in thread
From: Jason Yan @ 2021-03-27 6:57 UTC (permalink / raw)
To: Martin K. Petersen
Cc: axboe, ming.lei, hch, keescook, kbusch, linux-block, jejb, linux-scsi
Hi Martin,
在 2021/3/25 10:50, Martin K. Petersen 写道:
>
> Hi Jason!
>
>> @@ -55,6 +55,19 @@ static inline int scsi_status_is_good(int status)
>> (status == SAM_STAT_COMMAND_TERMINATED));
>> }
>>
>> +/** scsi_result_is_good - check the result return.
>> + *
>> + * @result: the result passed up from the driver (including host and
>> + * driver components)
>> + *
>> + * Drivers may only set other bytes but not status byte.
>> + * This checks both the status byte and other bytes.
>> + */
>> +static inline int scsi_result_is_good(int result)
>> +{
>> + return scsi_status_is_good(result) && (result & ~0xff) == 0;
>> +}
>> +
>>
>> /*
>> * standard mode-select header prepended to all mode-select commands
>
> Instead of introducing a "don't be broken" variant of
> scsi_status_is_good(), I'd prefer you to fix the latter to do the right
> thing wrt. offline devices.
>
> There aren't a ton of scsi_result_is_good() call sites to check. And I
> suspect that most of them wouldn't actually consider the DID_NO_CONNECT
> scenario to be "good".
>
OK, I'll have a try and check if it works for most of the call sites.
Thanks,
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2021-03-27 6:58 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-19 3:01 [PATCH 0/3] scsi: check the whole result in some places Jason Yan
2021-03-19 3:01 ` [PATCH 1/3] scsi: check the whole result for reading write protect flag Jason Yan
2021-03-19 7:55 ` Hannes Reinecke
2021-03-25 2:50 ` Martin K. Petersen
2021-03-27 6:57 ` Jason Yan
2021-03-19 3:01 ` [PATCH 2/3] scsi: only copy data to user when the whole result is good Jason Yan
2021-03-19 7:56 ` Hannes Reinecke
2021-03-19 8:22 ` Jason Yan
2021-03-19 3:01 ` [PATCH 3/3] scsi: switch to use scsi_result_is_good() in scsi_result_to_blk_status() Jason Yan
2021-03-19 7:56 ` Hannes Reinecke
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.