Skip to content

Commit e9714c2

Browse files
ausyskinmiquelraynal
authored andcommitted
mtd: fix use-after-free in mtd release
I case of partition device_unregister() in mtd_device_release() calls mtd_release() which frees mtd_info structure for partition. All code after device_unregister in mtd_device_release thus uses already freed memory. Move part of code to mtd_release() and restict mtd->dev cleanup to non-partion object. For partition object such cleanup have no sense as partition mtd_info is removed. Cc: Miquel Raynal <miquel.raynal@bootlin.com> Cc: Zhang Xiaoxu <zhangxiaoxu5@huawei.com> Fixes: 19bfa9e ("mtd: use refcount to prevent corruption") Reviewed-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20230731115836.542747-1-alexander.usyskin@intel.com
1 parent d2236f6 commit e9714c2

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

drivers/mtd/mtdcore.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ static void mtd_release(struct device *dev)
9393
struct mtd_info *mtd = dev_get_drvdata(dev);
9494
dev_t index = MTD_DEVT(mtd->index);
9595

96+
idr_remove(&mtd_idr, mtd->index);
97+
of_node_put(mtd_get_of_node(mtd));
98+
9699
if (mtd_is_partition(mtd))
97100
release_mtd_partition(mtd);
98101

@@ -103,6 +106,7 @@ static void mtd_release(struct device *dev)
103106
static void mtd_device_release(struct kref *kref)
104107
{
105108
struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt);
109+
bool is_partition = mtd_is_partition(mtd);
106110

107111
debugfs_remove_recursive(mtd->dbg.dfs_dir);
108112

@@ -111,11 +115,13 @@ static void mtd_device_release(struct kref *kref)
111115

112116
device_unregister(&mtd->dev);
113117

114-
/* Clear dev so mtd can be safely re-registered later if desired */
115-
memset(&mtd->dev, 0, sizeof(mtd->dev));
116-
117-
idr_remove(&mtd_idr, mtd->index);
118-
of_node_put(mtd_get_of_node(mtd));
118+
/*
119+
* Clear dev so mtd can be safely re-registered later if desired.
120+
* Should not be done for partition,
121+
* as it was already destroyed in device_unregister().
122+
*/
123+
if (!is_partition)
124+
memset(&mtd->dev, 0, sizeof(mtd->dev));
119125

120126
module_put(THIS_MODULE);
121127
}

0 commit comments

Comments
 (0)