summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChenXiaoSong <chenxiaosong2@huawei.com>2021-11-02 22:22:06 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-05-15 19:41:59 +0200
commit8033f109be4a1d5b466284e8ab9119c04f2a334b (patch)
tree3b78cf38812e008caa2855db87f868e78653120d
parent259dfb503b8f4087898403faf0e76dcb8d232e3d (diff)
VFS: Fix memory leak caused by concurrently mounting fs with subtype
If two processes mount same superblock, memory leak occurs: CPU0 | CPU1 do_new_mount | do_new_mount fs_set_subtype | fs_set_subtype kstrdup | | kstrdup memrory leak | The following reproducer triggers the problem: 1. shell command: mount -t ntfs /dev/sda1 /mnt & 2. c program: mount("/dev/sda1", "/mnt", "fuseblk", 0, "...") with kmemleak report being along the lines of unreferenced object 0xffff888235f1a5c0 (size 8): comm "mount.ntfs", pid 2860, jiffies 4295757824 (age 43.423s) hex dump (first 8 bytes): 00 a5 f1 35 82 88 ff ff ...5.... backtrace: [<00000000656e30cc>] __kmalloc_track_caller+0x16e/0x430 [<000000008e591727>] kstrdup+0x3e/0x90 [<000000008430d12b>] do_mount.cold+0x7b/0xd9 [<0000000078d639cd>] ksys_mount+0xb2/0x150 [<000000006015988d>] __x64_sys_mount+0x29/0x40 [<00000000e0a7c118>] do_syscall_64+0xc1/0x1d0 [<00000000bcea7df5>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [<00000000803a4067>] 0xffffffffffffffff Linus's tree already have refactoring patchset [1], one of them can fix this bug: c30da2e981a7 ("fuse: convert to use the new mount API") After refactoring, init super_block->s_subtype in fuse_fill_super. Since we did not merge the refactoring patchset in this branch, I create this patch. This patch fix this by adding a write lock while calling fs_set_subtype. [1] https://patchwork.kernel.org/project/linux-fsdevel/patch/20190903113640.7984-3-mszeredi@redhat.com/ Fixes: 79c0b2df79eb ("add filesystem subtype support") Cc: David Howells <dhowells@redhat.com> Cc: <stable@vger.kernel.org> Signed-off-by: ChenXiaoSong <chenxiaosong2@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/namespace.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 2f3c6a0350a8..396ff1bcfdad 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2490,9 +2490,12 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
return -ENODEV;
mnt = vfs_kern_mount(type, sb_flags, name, data);
- if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
- !mnt->mnt_sb->s_subtype)
- mnt = fs_set_subtype(mnt, fstype);
+ if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE)) {
+ down_write(&mnt->mnt_sb->s_umount);
+ if (!mnt->mnt_sb->s_subtype)
+ mnt = fs_set_subtype(mnt, fstype);
+ up_write(&mnt->mnt_sb->s_umount);
+ }
put_filesystem(type);
if (IS_ERR(mnt))