[SCSI] sg.c: Fix bad error handling in
I got a NULL derefrence in cdev_del+1 when called from sg_remove. By looking at the code of sg_add, sg_alloc and sg_remove (all in drivers/scsi/sg.c) I found out that sg_add is calling sg_alloc but if it fails afterwards it does not deallocate the space that was allocated in sg_alloc and the redundant entry has NULL in cdev. When sg_remove is being called, it tries to perform cdev_del to this NULL cdev and fails. Signed-off-by: Ishai Rabinovitz <ishai@mellanox.co.il> Acked-by: Douglas Gilbert <dougg@torque.net> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
committed by
James Bottomley
parent
0f13fc09db
commit
454e8957eb
@@ -1402,6 +1402,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
|
|||||||
Sg_device *sdp = NULL;
|
Sg_device *sdp = NULL;
|
||||||
struct cdev * cdev = NULL;
|
struct cdev * cdev = NULL;
|
||||||
int error, k;
|
int error, k;
|
||||||
|
unsigned long iflags;
|
||||||
|
|
||||||
disk = alloc_disk(1);
|
disk = alloc_disk(1);
|
||||||
if (!disk) {
|
if (!disk) {
|
||||||
@@ -1429,7 +1430,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
|
|||||||
|
|
||||||
error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1);
|
error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto cdev_add_err;
|
||||||
|
|
||||||
sdp->cdev = cdev;
|
sdp->cdev = cdev;
|
||||||
if (sg_sysfs_valid) {
|
if (sg_sysfs_valid) {
|
||||||
@@ -1456,6 +1457,13 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
cdev_add_err:
|
||||||
|
write_lock_irqsave(&sg_dev_arr_lock, iflags);
|
||||||
|
kfree(sg_dev_arr[k]);
|
||||||
|
sg_dev_arr[k] = NULL;
|
||||||
|
sg_nr_dev--;
|
||||||
|
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
put_disk(disk);
|
put_disk(disk);
|
||||||
if (cdev)
|
if (cdev)
|
||||||
|
Reference in New Issue
Block a user