[PATCH] fmc: Fix memory leak and NULL pointer dereference

From: Anton Vasilyev
Date: Fri Jul 27 2018 - 11:03:15 EST


There is no deallocation of fmc memory, allocated at ff_dev_create()
by kmemdup(), and no check on kmemdup() success.

The patch adds deallocation into ff_dev_release() and adds check on
allocation success.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Anton Vasilyev <vasilyev@xxxxxxxxx>
---
drivers/fmc/fmc-fakedev.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/fmc/fmc-fakedev.c b/drivers/fmc/fmc-fakedev.c
index 941d0930969a..ede589f4e8e5 100644
--- a/drivers/fmc/fmc-fakedev.c
+++ b/drivers/fmc/fmc-fakedev.c
@@ -244,7 +244,10 @@ static struct fmc_operations ff_fmc_operations = {
/* This device is kmalloced: release it */
static void ff_dev_release(struct device *dev)
{
+ int i;
struct ff_dev *ff = container_of(dev, struct ff_dev, dev);
+ for (i = 0; i < ff_nr_dev; i++)
+ kfree(ff->fmc[i]);
kfree(ff);
}

@@ -273,15 +276,17 @@ static struct ff_dev *ff_dev_create(void)
ff->dev.release = ff_dev_release;

ret = device_register(&ff->dev);
- if (ret < 0) {
- put_device(&ff->dev);
- return ERR_PTR(ret);
- }
+ if (ret < 0)
+ goto err;

/* Create fmc structures that refer to this new "hw" device */
for (i = 0; i < ff_nr_dev; i++) {
fmc = kmemdup(&ff_template_fmc, sizeof(ff_template_fmc),
GFP_KERNEL);
+ if (!fmc) {
+ ret = -ENOMEM;
+ goto err;
+ }
fmc->hwdev = &ff->dev;
fmc->carrier_data = ff;
fmc->nr_slots = ff_nr_dev;
@@ -294,6 +299,10 @@ static struct ff_dev *ff_dev_create(void)
ff_template_fmc.device_id++;
}
return ff;
+
+err:
+ put_device(&ff->dev);
+ return ERR_PTR(ret);
}

/* init and exit */
--
2.18.0