mtd: Check add_mtd_device() ret code
authorBoris Brezillon <bbrezillon@kernel.org>
Wed, 2 Jan 2019 14:36:54 +0000 (15:36 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Dec 2019 14:35:06 +0000 (15:35 +0100)
[ Upstream commit 2b6f0090a3335b7bdd03ca520c35591159463041 ]

add_mtd_device() can fail. We should always check its return value
and gracefully handle the failure case. Fix the call sites where this
not done (in mtdpart.c) and add a __must_check attribute to the
prototype to avoid this kind of mistakes.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/mtd/mtdcore.h
drivers/mtd/mtdpart.c

index 55fdb8e..488b652 100644 (file)
@@ -6,7 +6,7 @@
 extern struct mutex mtd_table_mutex;
 
 struct mtd_info *__mtd_next_device(int i);
-int add_mtd_device(struct mtd_info *mtd);
+int __must_check add_mtd_device(struct mtd_info *mtd);
 int del_mtd_device(struct mtd_info *mtd);
 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
 int del_mtd_partitions(struct mtd_info *);
index fccdd49..70e476c 100644 (file)
@@ -648,10 +648,22 @@ int mtd_add_partition(struct mtd_info *master, const char *name,
        list_add(&new->list, &mtd_partitions);
        mutex_unlock(&mtd_partitions_mutex);
 
-       add_mtd_device(&new->mtd);
+       ret = add_mtd_device(&new->mtd);
+       if (ret)
+               goto err_remove_part;
 
        mtd_add_partition_attrs(new);
 
+       return 0;
+
+err_remove_part:
+       mutex_lock(&mtd_partitions_mutex);
+       list_del(&new->list);
+       mutex_unlock(&mtd_partitions_mutex);
+
+       free_partition(new);
+       pr_info("%s:%i\n", __func__, __LINE__);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_add_partition);
@@ -696,28 +708,42 @@ int add_mtd_partitions(struct mtd_info *master,
 {
        struct mtd_part *slave;
        uint64_t cur_offset = 0;
-       int i;
+       int i, ret;
 
        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 
        for (i = 0; i < nbparts; i++) {
                slave = allocate_partition(master, parts + i, i, cur_offset);
                if (IS_ERR(slave)) {
-                       del_mtd_partitions(master);
-                       return PTR_ERR(slave);
+                       ret = PTR_ERR(slave);
+                       goto err_del_partitions;
                }
 
                mutex_lock(&mtd_partitions_mutex);
                list_add(&slave->list, &mtd_partitions);
                mutex_unlock(&mtd_partitions_mutex);
 
-               add_mtd_device(&slave->mtd);
+               ret = add_mtd_device(&slave->mtd);
+               if (ret) {
+                       mutex_lock(&mtd_partitions_mutex);
+                       list_del(&slave->list);
+                       mutex_unlock(&mtd_partitions_mutex);
+
+                       free_partition(slave);
+                       goto err_del_partitions;
+               }
+
                mtd_add_partition_attrs(slave);
 
                cur_offset = slave->offset + slave->mtd.size;
        }
 
        return 0;
+
+err_del_partitions:
+       del_mtd_partitions(master);
+
+       return ret;
 }
 
 static DEFINE_SPINLOCK(part_parser_lock);