4.5-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Finn Thain <[email protected]>

commit 8d5dbec3bcb24a7d071962448e0fecaca8c75cc7 upstream.

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 <[email protected]>
Signed-off-by: Finn Thain <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

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

--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -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;
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -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