This bug causes the wrong command to have its sense pointer overwritten,
which sometimes leads to a NULL pointer deref. Fix this by checking which
command is being requeued before restoring the scsi_eh_save data.

It turns out that some targets will disconnect a REQUEST SENSE command.
The autosense algorithm doesn't anticipate this. Hence multiple commands
can end up undergoing autosense simultaneously, and they will all try to
use the same scsi_eh_save struct, which won't work. Defer autosense when
the scsi_eh_save storage is in use by another command.

Fixes: f27db8eb98a1 ("ncr5380: Fix autosense bugs")
Reported-and-tested-by: Michael Schmitz <schmitz...@gmail.com>
Signed-off-by: Finn Thain <fth...@telegraphics.com.au>

---
 drivers/scsi/NCR5380.c       |    4 ++--
 drivers/scsi/atari_NCR5380.c |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

Index: linux/drivers/scsi/NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/NCR5380.c   2016-02-23 10:07:01.000000000 +1100
+++ linux/drivers/scsi/NCR5380.c        2016-02-23 10:07:02.000000000 +1100
@@ -760,7 +760,7 @@ static struct scsi_cmnd *dequeue_next_cm
        struct NCR5380_cmd *ncmd;
        struct scsi_cmnd *cmd;
 
-       if (list_empty(&hostdata->autosense)) {
+       if (hostdata->sensing || list_empty(&hostdata->autosense)) {
                list_for_each_entry(ncmd, &hostdata->unissued, list) {
                        cmd = NCR5380_to_scmd(ncmd);
                        dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p 
target=%d busy=0x%02x lun=%llu\n",
@@ -793,7 +793,7 @@ static void requeue_cmd(struct Scsi_Host
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
        struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
 
-       if (hostdata->sensing) {
+       if (hostdata->sensing == cmd) {
                scsi_eh_restore_cmnd(cmd, &hostdata->ses);
                list_add(&ncmd->list, &hostdata->autosense);
                hostdata->sensing = NULL;
Index: linux/drivers/scsi/atari_NCR5380.c
===================================================================
--- linux.orig/drivers/scsi/atari_NCR5380.c     2016-02-23 10:07:01.000000000 
+1100
+++ linux/drivers/scsi/atari_NCR5380.c  2016-02-23 10:07:02.000000000 +1100
@@ -862,7 +862,7 @@ static struct scsi_cmnd *dequeue_next_cm
        struct NCR5380_cmd *ncmd;
        struct scsi_cmnd *cmd;
 
-       if (list_empty(&hostdata->autosense)) {
+       if (hostdata->sensing || list_empty(&hostdata->autosense)) {
                list_for_each_entry(ncmd, &hostdata->unissued, list) {
                        cmd = NCR5380_to_scmd(ncmd);
                        dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p 
target=%d busy=0x%02x lun=%llu\n",
@@ -901,7 +901,7 @@ static void requeue_cmd(struct Scsi_Host
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
        struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
 
-       if (hostdata->sensing) {
+       if (hostdata->sensing == cmd) {
                scsi_eh_restore_cmnd(cmd, &hostdata->ses);
                list_add(&ncmd->list, &hostdata->autosense);
                hostdata->sensing = NULL;


Reply via email to