We need to validate that get_device() succeeded, otherwise
we'll end up working with invalid devices.

Signed-off-by: Hannes Reinecke <[email protected]>
---
 drivers/scsi/scsi_scan.c | 14 ++++++++++++--
 drivers/scsi/sd.c        |  8 +++++---
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index be5e919..18edfd7 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -245,6 +245,10 @@ static struct scsi_device *scsi_alloc_sdev(struct 
scsi_target *starget,
        INIT_WORK(&sdev->requeue_work, scsi_requeue_run_queue);
 
        sdev->sdev_gendev.parent = get_device(&starget->dev);
+       if (!sdev->sdev_gendev.parent) {
+               kfree(sdev);
+               return NULL;
+       }
        sdev->sdev_target = starget;
 
        /* usually NULL and set by ->slave_alloc instead */
@@ -366,7 +370,8 @@ static struct scsi_target *__scsi_find_target(struct device 
*parent,
                }
        }
        if (found_starget)
-               get_device(&found_starget->dev);
+               if (!get_device(&found_starget->dev))
+                       found_starget = NULL;
 
        return found_starget;
 }
@@ -436,6 +441,10 @@ static struct scsi_target *scsi_alloc_target(struct device 
*parent,
        device_initialize(dev);
        kref_init(&starget->reap_ref);
        dev->parent = get_device(parent);
+       if (!dev->parent) {
+               kfree(starget);
+               return NULL;
+       }
        dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
        dev->bus = &scsi_bus_type;
        dev->type = &scsi_target_type;
@@ -469,7 +478,8 @@ static struct scsi_target *scsi_alloc_target(struct device 
*parent,
                        return NULL;
                }
        }
-       get_device(dev);
+       /* No good way to recover here; keep fingers crossed */
+       WARN_ON(!get_device(dev));
 
        return starget;
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 228b0b62..abbab17 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -619,10 +619,12 @@ static struct scsi_disk *scsi_disk_get(struct gendisk 
*disk)
 
        if (disk->private_data) {
                sdkp = scsi_disk(disk);
-               if (scsi_device_get(sdkp->device) == 0)
-                       get_device(&sdkp->dev);
-               else
+               if (scsi_device_get(sdkp->device))
+                       sdkp = NULL;
+               else if (!get_device(&sdkp->dev)) {
+                       scsi_device_put(sdkp->device);
                        sdkp = NULL;
+               }
        }
        mutex_unlock(&sd_ref_mutex);
        return sdkp;
-- 
1.8.5.6

Reply via email to