mtd: fix memory leak in mtd_dataflash
authorH Hartley Sweeten <hartleys@visionengravers.com>
Wed, 7 Oct 2009 21:08:08 +0000 (17:08 -0400)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Sat, 17 Oct 2009 14:41:11 +0000 (15:41 +0100)
Fix a potential memory leak in mtd_dataflash driver.

The private data that is allocated when registering a DataFlash
device with the MTD subsystem is not released if an error occurs
when add_mtd_partitions() or add_mtd_device() is called.  Fix this
by adding an error path.  The memory is already released during a
remove.

Also, add a dev_set_drvdata(&spi->dev, NULL) before the kfree() so
that the spi device does not reference invalid data.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/mtd/devices/mtd_dataflash.c

index 93e3627be74c76a37117f13883e74d0bd1607f11..19817404ce7d9e6f240e27cf299b3b724b005268 100644 (file)
@@ -636,6 +636,7 @@ add_dataflash_otp(struct spi_device *spi, char *name,
        struct mtd_info                 *device;
        struct flash_platform_data      *pdata = spi->dev.platform_data;
        char                            *otp_tag = "";
+       int                             err = 0;
 
        priv = kzalloc(sizeof *priv, GFP_KERNEL);
        if (!priv)
@@ -693,13 +694,23 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 
                if (nr_parts > 0) {
                        priv->partitioned = 1;
-                       return add_mtd_partitions(device, parts, nr_parts);
+                       err = add_mtd_partitions(device, parts, nr_parts);
+                       goto out;
                }
        } else if (pdata && pdata->nr_parts)
                dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
                                pdata->nr_parts, device->name);
 
-       return add_mtd_device(device) == 1 ? -ENODEV : 0;
+       if (add_mtd_device(device) == 1)
+               err = -ENODEV;
+
+out:
+       if (!err)
+               return 0;
+
+       dev_set_drvdata(&spi->dev, NULL);
+       kfree(priv);
+       return err;
 }
 
 static inline int __devinit
@@ -932,8 +943,10 @@ static int __devexit dataflash_remove(struct spi_device *spi)
                status = del_mtd_partitions(&flash->mtd);
        else
                status = del_mtd_device(&flash->mtd);
-       if (status == 0)
+       if (status == 0) {
+               dev_set_drvdata(&spi->dev, NULL);
                kfree(flash);
+       }
        return status;
 }