ahc_lookup_scb() may return a null pointer and further lead to
null-pointer-dereference in case DATA_OVERRUN. Fix this by adding
a null check.

Signed-off-by: Dinghao Liu <dinghao....@zju.edu.cn>
---
 drivers/scsi/aic7xxx/aic7xxx_core.c | 72 +++++++++++++++--------------
 1 file changed, 37 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c 
b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 4b04ab8908f8..3a1cd6a0334e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -1382,43 +1382,45 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                u_int i;
 
                scb = ahc_lookup_scb(ahc, scbindex);
-               for (i = 0; i < num_phases; i++) {
-                       if (lastphase == ahc_phase_table[i].phase)
-                               break;
-               }
-               ahc_print_path(ahc, scb);
-               printk("data overrun detected %s."
-                      "  Tag == 0x%x.\n",
-                      ahc_phase_table[i].phasemsg,
-                      scb->hscb->tag);
-               ahc_print_path(ahc, scb);
-               printk("%s seen Data Phase.  Length = %ld.  NumSGs = %d.\n",
-                      ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
-                      ahc_get_transfer_length(scb), scb->sg_count);
-               if (scb->sg_count > 0) {
-                       for (i = 0; i < scb->sg_count; i++) {
-
-                               printk("sg[%d] - Addr 0x%x%x : Length %d\n",
-                                      i,
-                                      (ahc_le32toh(scb->sg_list[i].len) >> 24
-                                       & SG_HIGH_ADDR_BITS),
-                                      ahc_le32toh(scb->sg_list[i].addr),
-                                      ahc_le32toh(scb->sg_list[i].len)
-                                      & AHC_SG_LEN_MASK);
+               if (scb != NULL) {
+                       for (i = 0; i < num_phases; i++) {
+                               if (lastphase == ahc_phase_table[i].phase)
+                                       break;
                        }
+                       ahc_print_path(ahc, scb);
+                       printk("data overrun detected %s."
+                               "  Tag == 0x%x.\n",
+                               ahc_phase_table[i].phasemsg,
+                               scb->hscb->tag);
+                       ahc_print_path(ahc, scb);
+                       printk("%s seen Data Phase.  Length = %ld.  NumSGs = 
%d.\n",
+                               ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : 
"Haven't",
+                               ahc_get_transfer_length(scb), scb->sg_count);
+                       if (scb->sg_count > 0) {
+                               for (i = 0; i < scb->sg_count; i++) {
+
+                                       printk("sg[%d] - Addr 0x%x%x : Length 
%d\n",
+                                               i,
+                                               
(ahc_le32toh(scb->sg_list[i].len) >> 24
+                                               & SG_HIGH_ADDR_BITS),
+                                               
ahc_le32toh(scb->sg_list[i].addr),
+                                               ahc_le32toh(scb->sg_list[i].len)
+                                               & AHC_SG_LEN_MASK);
+                               }
+                       }
+                       /*
+                       * Set this and it will take effect when the
+                       * target does a command complete.
+                       */
+                       ahc_freeze_devq(ahc, scb);
+                       if ((scb->flags & SCB_SENSE) == 0) {
+                               ahc_set_transaction_status(scb, 
CAM_DATA_RUN_ERR);
+                       } else {
+                               scb->flags &= ~SCB_SENSE;
+                               ahc_set_transaction_status(scb, 
CAM_AUTOSENSE_FAIL);
+                       }
+                       ahc_freeze_scb(scb);
                }
-               /*
-                * Set this and it will take effect when the
-                * target does a command complete.
-                */
-               ahc_freeze_devq(ahc, scb);
-               if ((scb->flags & SCB_SENSE) == 0) {
-                       ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
-               } else {
-                       scb->flags &= ~SCB_SENSE;
-                       ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
-               }
-               ahc_freeze_scb(scb);
 
                if ((ahc->features & AHC_ULTRA2) != 0) {
                        /*
-- 
2.17.1

Reply via email to