mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
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: 19bfa9ebeb
("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
This commit is contained in:
parent
d2236f6219
commit
e9714c22c1
@ -93,6 +93,9 @@ static void mtd_release(struct device *dev)
|
||||
struct mtd_info *mtd = dev_get_drvdata(dev);
|
||||
dev_t index = MTD_DEVT(mtd->index);
|
||||
|
||||
idr_remove(&mtd_idr, mtd->index);
|
||||
of_node_put(mtd_get_of_node(mtd));
|
||||
|
||||
if (mtd_is_partition(mtd))
|
||||
release_mtd_partition(mtd);
|
||||
|
||||
@ -103,6 +106,7 @@ static void mtd_release(struct device *dev)
|
||||
static void mtd_device_release(struct kref *kref)
|
||||
{
|
||||
struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt);
|
||||
bool is_partition = mtd_is_partition(mtd);
|
||||
|
||||
debugfs_remove_recursive(mtd->dbg.dfs_dir);
|
||||
|
||||
@ -111,11 +115,13 @@ static void mtd_device_release(struct kref *kref)
|
||||
|
||||
device_unregister(&mtd->dev);
|
||||
|
||||
/* Clear dev so mtd can be safely re-registered later if desired */
|
||||
memset(&mtd->dev, 0, sizeof(mtd->dev));
|
||||
|
||||
idr_remove(&mtd_idr, mtd->index);
|
||||
of_node_put(mtd_get_of_node(mtd));
|
||||
/*
|
||||
* Clear dev so mtd can be safely re-registered later if desired.
|
||||
* Should not be done for partition,
|
||||
* as it was already destroyed in device_unregister().
|
||||
*/
|
||||
if (!is_partition)
|
||||
memset(&mtd->dev, 0, sizeof(mtd->dev));
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user