@@ -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;
@@ -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;
We need to validate that get_device() succeeded, otherwise we'll end up working with invalid devices. Signed-off-by: Hannes Reinecke <hare@suse.com> --- drivers/scsi/scsi_scan.c | 14 ++++++++++++-- drivers/scsi/sd.c | 8 +++++--- 2 files changed, 17 insertions(+), 5 deletions(-)