When rootfs is a ramfs, for example with root= on the command line, its superblock carries a struct ramfs_fs_info from ramfs_init_fs_context(). ramfs_kill_sb() frees it, but rootfs_fs_type uses kill_anon_super(). Before commit 576ee5dfd459 ("fs: add immutable rootfs") rootfs could not be unmounted. Since then prepare_namespace() pivots into the real root and unmounts rootfs. When the superblock is destroyed, the structure is leaked. kmemleak on an SH7785LCR board: unreferenced object 0x8100a720 (size 32): comm "swapper/0", pid 0, jiffies 4294892299 backtrace (crc c8bfd23b): ... ramfs_init_fs_context+0x16/0x48 rootfs_init_fs_context+0x16/0x2c alloc_fs_context+0x98/0x114 fs_context_for_mount+0x16/0x24 ... Call ramfs_kill_sb() when rootfs is a ramfs. tmpfs frees its own data in put_super and keeps kill_anon_super(). Fixes: 576ee5dfd459 ("fs: add immutable rootfs") Reported-by: John Paul Adrian Glaubitz Assisted-by: LLM Signed-off-by: Karl Mehltretter --- Test: kernels with DEBUG_KMEMLEAK that mount root=/dev/sda themselves, no initramfs. kmemleak reports the object without the patch and nothing with it, on - the custom QEMU model of the SH7785LCR (sh for-next plus unmerged sh patches; 32-byte leaked allocation), and - user-mode Linux (v7.3-rc5, um defconfig; 8-byte leaked allocation). On the model, rootfstype=ext2,tmpfs makes rootfs a tmpfs. kmemleak reports nothing there, with or without the patch. The report only shows up after init reopens /dev/console. The console that the kernel opens for init is on rootfs and keeps it alive. --- init/do_mounts.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/init/do_mounts.c b/init/do_mounts.c index 95e0b3a0f711..b088021b1546 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -503,10 +503,18 @@ static int rootfs_init_fs_context(struct fs_context *fc) return ramfs_init_fs_context(fc); } +static void rootfs_kill_sb(struct super_block *sb) +{ + if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs) + kill_anon_super(sb); + else + ramfs_kill_sb(sb); +} + struct file_system_type rootfs_fs_type = { .name = "rootfs", .init_fs_context = rootfs_init_fs_context, - .kill_sb = kill_anon_super, + .kill_sb = rootfs_kill_sb, }; void __init init_rootfs(void) base-commit: 72d3fcf802c45d00b300f25b848a93c3a2bd7c7e -- 2.53.0