The Parfait (version 2.1.0) static code analysis tool found the
following NULL pointer dereference problem.

dev_to_shost() in include/scsi/scsi_host.h has the ability to return
NULL if the scsi host device does not have the Scsi_host->parent
field set.  With the possibilty of a NULL pointer being set for
the Scsi_Host->parent field, calls to host_to_us() have to make
sure the return pointer is not null.  Changes were made to check
for a return value of NULL on calls to host_to_us().

Signed-off-by: Joe Moriarty <[email protected]>
Reviewed-by: Steven Sistare <[email protected]>
Acked-by: Hakon Bugge <[email protected]>
---
 drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index c267f2812a04..94af609d49bf 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
 {
        struct us_data *us = host_to_us(sdev->host);
 
+       if (!us)
+               pr_warn("Error in %s: us = NULL\n", __func__);
+
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
         * the extra data and many devices choke if asked for more or
@@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
 {
        struct us_data *us = host_to_us(sdev->host);
 
+       if (!us) {
+               pr_warn("Error in %s: us = NULL\n", __func__);
+               return 0;
+       }
+
        /*
         * Many devices have trouble transferring more than 32KB at a time,
         * while others have trouble with more than 64K. At this time we
@@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
 {
        struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
 
+       if (!us) {
+               pr_warn("Error in %s: us = NULL\n", __func__);
+               return 0;
+       }
+
        /*
         * Some USB drives don't support REPORT LUNS, even though they
         * report a SCSI revision level above 2.  Tell the SCSI layer
@@ -361,6 +374,11 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
 {
        struct us_data *us = host_to_us(srb->device->host);
 
+       if (!us) {
+               pr_warn("Error in %s: us = NULL\n", __func__);
+               return 0;
+       }
+
        /* check for state-transition errors */
        if (us->srb != NULL) {
                printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
@@ -395,6 +413,11 @@ static int command_abort(struct scsi_cmnd *srb)
 {
        struct us_data *us = host_to_us(srb->device->host);
 
+       if (!us) {
+               pr_warn("Error in %s: us = NULL\n", __func__);
+               return FAILED;
+       }
+
        usb_stor_dbg(us, "%s called\n", __func__);
 
        /*
@@ -438,12 +461,17 @@ static int device_reset(struct scsi_cmnd *srb)
        struct us_data *us = host_to_us(srb->device->host);
        int result;
 
-       usb_stor_dbg(us, "%s called\n", __func__);
+       if (us) {
+               usb_stor_dbg(us, "%s called\n", __func__);
 
-       /* lock the device pointers and do the reset */
-       mutex_lock(&(us->dev_mutex));
-       result = us->transport_reset(us);
-       mutex_unlock(&us->dev_mutex);
+               /* lock the device pointers and do the reset */
+               mutex_lock(&(us->dev_mutex));
+               result = us->transport_reset(us);
+               mutex_unlock(&us->dev_mutex);
+       } else {
+               pr_warn("Error in %s: us = NULL\n", __func__);
+               result = -ENXIO;
+       }
 
        return result < 0 ? FAILED : SUCCESS;
 }
@@ -454,9 +482,15 @@ static int bus_reset(struct scsi_cmnd *srb)
        struct us_data *us = host_to_us(srb->device->host);
        int result;
 
-       usb_stor_dbg(us, "%s called\n", __func__);
+       if (us) {
+               usb_stor_dbg(us, "%s called\n", __func__);
+
+               result = usb_stor_port_reset(us);
+       } else {
+               pr_warn("Error in %s: us = NULL\n", __func__);
+               result = -ENXIO;
+       }
 
-       result = usb_stor_port_reset(us);
        return result < 0 ? FAILED : SUCCESS;
 }
 
@@ -506,6 +540,11 @@ static int show_info (struct seq_file *m, struct Scsi_Host 
*host)
        struct us_data *us = host_to_us(host);
        const char *string;
 
+       if (!us) {
+               pr_warn("Error in %s: us = NULL\n", __func__);
+               return 0;
+       }
+
        /* print the controller name */
        seq_printf(m, "   Host scsi%d: usb-storage\n", host->host_no);
 
-- 
2.15.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to