[PATCH v1] mtd: core/part: trying to delete partition with usecount > 0 corrupt partition

Andreas Oetken ennoerlangen at gmail.com
Fri Nov 15 00:55:13 PST 2024


Check for usecount before deleting debugfs and sysfs entries.
Otherwise deleting the partition a second time leads to a kernel panic.

Signed-off-by: Andreas Oetken <andreas.oetken at siemens-energy.com>
---
 drivers/mtd/mtdcore.c | 25 ++++++++++++++-----------
 drivers/mtd/mtdcore.h |  2 +-
 drivers/mtd/mtdpart.c |  7 +++----
 3 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 1c8c40728678..19ade7e53024 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -714,30 +714,33 @@ int add_mtd_device(struct mtd_info *mtd)
  *	if the requested device does not appear to be present in the list.
  */
 
-int del_mtd_device(struct mtd_info *mtd)
+int del_mtd_device(struct mtd_info *mtd, const struct attribute *mtd_partition_attrs[])
 {
 	int ret;
 	struct mtd_notifier *not;
 
 	mutex_lock(&mtd_table_mutex);
-
-	debugfs_remove_recursive(mtd->dbg.dfs_dir);
-
 	if (idr_find(&mtd_idr, mtd->index) != mtd) {
 		ret = -ENODEV;
 		goto out_error;
 	}
 
-	/* No need to get a refcount on the module containing
-		the notifier, since we hold the mtd_table_mutex */
-	list_for_each_entry(not, &mtd_notifiers, list)
-		not->remove(mtd);
-
 	if (mtd->usecount) {
 		printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
 		       mtd->index, mtd->name, mtd->usecount);
 		ret = -EBUSY;
 	} else {
+		/* No need to get a refcount on the module containing
+		 * the notifier, since we hold the mtd_table_mutex
+		 */
+		debugfs_remove_recursive(mtd->dbg.dfs_dir);
+
+		list_for_each_entry(not, &mtd_notifiers, list)
+			not->remove(mtd);
+
+		if (mtd_partition_attrs != NULL)
+			sysfs_remove_files(&mtd->dev.kobj, mtd_partition_attrs);
+
 		/* Try to remove the NVMEM provider */
 		if (mtd->nvmem)
 			nvmem_unregister(mtd->nvmem);
@@ -852,7 +855,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
 
 out:
 	if (ret && device_is_registered(&mtd->dev))
-		del_mtd_device(mtd);
+		del_mtd_device(mtd, NULL);
 
 	return ret;
 }
@@ -878,7 +881,7 @@ int mtd_device_unregister(struct mtd_info *master)
 	if (!device_is_registered(&master->dev))
 		return 0;
 
-	return del_mtd_device(master);
+	return del_mtd_device(master, NULL);
 }
 EXPORT_SYMBOL_GPL(mtd_device_unregister);
 
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
index b5eefeabf310..0f8e815e99b2 100644
--- a/drivers/mtd/mtdcore.h
+++ b/drivers/mtd/mtdcore.h
@@ -9,7 +9,7 @@ extern struct backing_dev_info *mtd_bdi;
 
 struct mtd_info *__mtd_next_device(int i);
 int __must_check add_mtd_device(struct mtd_info *mtd);
-int del_mtd_device(struct mtd_info *mtd);
+int del_mtd_device(struct mtd_info *mtd, const struct attribute *mtd_partition_attrs[]);
 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
 int del_mtd_partitions(struct mtd_info *);
 
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 5725818fa199..96d4deb4d9b5 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -307,12 +307,11 @@ static int __mtd_del_partition(struct mtd_info *mtd)
 			return err;
 	}
 
-	sysfs_remove_files(&mtd->dev.kobj, mtd_partition_attrs);
-
-	err = del_mtd_device(mtd);
+	err = del_mtd_device(mtd, mtd_partition_attrs);
 	if (err)
 		return err;
 
+
 	list_del(&mtd->part.node);
 	free_partition(mtd);
 
@@ -334,7 +333,7 @@ static int __del_mtd_partitions(struct mtd_info *mtd)
 			__del_mtd_partitions(child);
 
 		pr_info("Deleting %s MTD partition\n", child->name);
-		ret = del_mtd_device(child);
+		ret = del_mtd_device(child, mtd_partition_attrs);
 		if (ret < 0) {
 			pr_err("Error when deleting partition \"%s\" (%d)\n",
 			       child->name, ret);
-- 
2.45.2




More information about the linux-mtd mailing list