[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