Skip to content

Commit ec952aa

Browse files
committed
mtd: key superblock by device number
The mtd driver has similar problems than the one that was fixed in commit dc3216b ("super: ensure valid info"). The kill_mtd_super() helper calls shuts the superblock down but leaves the superblock on fs_supers as the devices are still in use but puts the mtd device and cleans out the superblock's s_mtd field. This means another mounter can find the superblock on the list accessing its s_mtd field while it is curently in the process of being freed or already freed. Prevent that from happening by keying superblock by dev_t just as we do in the generic code. Link: https://lore.kernel.org/linux-fsdevel/20230829-weitab-lauwarm-49c40fc85863@brauner Acked-by: Richard Weinberger <richard@nod.at> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Christoph Hellwig <hch@lst.de> Message-Id: <20230829-vfs-super-mtd-v1-2-fecb572e5df3@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 69881be commit ec952aa

File tree

1 file changed

+11
-34
lines changed

1 file changed

+11
-34
lines changed

drivers/mtd/mtdsuper.c

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,6 @@
1919
#include <linux/fs_context.h>
2020
#include "mtdcore.h"
2121

22-
/*
23-
* compare superblocks to see if they're equivalent
24-
* - they are if the underlying MTD device is the same
25-
*/
26-
static int mtd_test_super(struct super_block *sb, struct fs_context *fc)
27-
{
28-
struct mtd_info *mtd = fc->sget_key;
29-
30-
if (sb->s_mtd == fc->sget_key) {
31-
pr_debug("MTDSB: Match on device %d (\"%s\")\n",
32-
mtd->index, mtd->name);
33-
return 1;
34-
}
35-
36-
pr_debug("MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
37-
sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
38-
return 0;
39-
}
40-
41-
/*
42-
* mark the superblock by the MTD device it is using
43-
* - set the device number to be the correct MTD block device for pesuperstence
44-
* of NFS exports
45-
*/
46-
static int mtd_set_super(struct super_block *sb, struct fs_context *fc)
47-
{
48-
sb->s_mtd = fc->sget_key;
49-
sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);
50-
sb->s_bdi = bdi_get(mtd_bdi);
51-
return 0;
52-
}
53-
5422
/*
5523
* get a superblock on an MTD-backed filesystem
5624
*/
@@ -62,8 +30,7 @@ static int mtd_get_sb(struct fs_context *fc,
6230
struct super_block *sb;
6331
int ret;
6432

65-
fc->sget_key = mtd;
66-
sb = sget_fc(fc, mtd_test_super, mtd_set_super);
33+
sb = sget_dev(fc, MKDEV(MTD_BLOCK_MAJOR, mtd->index));
6734
if (IS_ERR(sb))
6835
return PTR_ERR(sb);
6936

@@ -77,6 +44,16 @@ static int mtd_get_sb(struct fs_context *fc,
7744
pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
7845
mtd->index, mtd->name);
7946

47+
/*
48+
* Would usually have been set with @sb_lock held but in
49+
* contrast to sb->s_bdev that's checked with only
50+
* @sb_lock held, nothing checks sb->s_mtd without also
51+
* holding sb->s_umount and we're holding sb->s_umount
52+
* here.
53+
*/
54+
sb->s_mtd = mtd;
55+
sb->s_bdi = bdi_get(mtd_bdi);
56+
8057
ret = fill_super(sb, fc);
8158
if (ret < 0)
8259
goto error_sb;

0 commit comments

Comments
 (0)