]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs/ntfs3: fix ntfs_mount_options leak in ntfs_fill_super()
authorBaokun Li <libaokun1@huawei.com>
Tue, 9 Dec 2025 07:21:41 +0000 (15:21 +0800)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Fri, 19 Dec 2025 18:04:02 +0000 (19:04 +0100)
In ntfs_fill_super(), the fc->fs_private pointer is set to NULL without
first freeing the memory it points to. This causes the subsequent call to
ntfs_fs_free() to skip freeing the ntfs_mount_options structure.

This results in a kmemleak report:

  unreferenced object 0xff1100015378b800 (size 32):
    comm "mount", pid 582, jiffies 4294890685
    hex dump (first 32 bytes):
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
      00 00 00 00 00 00 00 00 ed ff ed ff 00 04 00 00  ................
    backtrace (crc ed541d8c):
      __kmalloc_cache_noprof+0x424/0x5a0
      __ntfs_init_fs_context+0x47/0x590
      alloc_fs_context+0x5d8/0x960
      __x64_sys_fsopen+0xb1/0x190
      do_syscall_64+0x50/0x1f0
      entry_SYSCALL_64_after_hwframe+0x76/0x7e

This issue can be reproduced using the following commands:
        fallocate -l 100M test.file
        mount test.file /tmp/test

Since sbi->options is duplicated from fc->fs_private and does not
directly use the memory allocated for fs_private, it is unnecessary to
set fc->fs_private to NULL.

Additionally, this patch simplifies the code by utilizing the helper
function put_mount_options() instead of open-coding the cleanup logic.

Reported-by: syzbot+23aee7afc440fe803545@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=23aee7afc440fe803545
Fixes: aee4d5a521e9 ("ntfs3: fix double free of sbi->options->nls and clarify ownership of fc->fs_private")
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/super.c

index 1acc685625f73c97601588a41ac8b282fef1744f..df65877f172c122573a0faf454e67e67f37cbc10 100644 (file)
@@ -705,9 +705,7 @@ static void ntfs_put_super(struct super_block *sb)
        ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
 
        if (sbi->options) {
-               unload_nls(sbi->options->nls);
-               kfree(sbi->options->nls_name);
-               kfree(sbi->options);
+               put_mount_options(sbi->options);
                sbi->options = NULL;
        }
 
@@ -1253,7 +1251,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
                }
        }
        sbi->options = options;
-       fc->fs_private = NULL;
        sb->s_flags |= SB_NODIRATIME;
        sb->s_magic = 0x7366746e; // "ntfs"
        sb->s_op = &ntfs_sops;
@@ -1677,9 +1674,7 @@ put_inode_out:
 out:
        /* sbi->options == options */
        if (options) {
-               unload_nls(options->nls);
-               kfree(options->nls_name);
-               kfree(options);
+               put_mount_options(sbi->options);
                sbi->options = NULL;
        }