Unverified Commit f7edab0c authored by Baokun Li's avatar Baokun Li Committed by Konstantin Komarov
Browse files

fs/ntfs3: fix ntfs_mount_options leak in ntfs_fill_super()



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: default avatar <syzbot+23aee7afc440fe803545@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=23aee7afc440fe803545


Fixes: aee4d5a5 ("ntfs3: fix double free of sbi->options->nls and clarify ownership of fc->fs_private")
Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
Signed-off-by: default avatarKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
parent dffc7f2f
Loading
Loading
Loading
Loading
+2 −7
Original line number Diff line number Diff line
@@ -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 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
out:
	/* sbi->options == options */
	if (options) {
		unload_nls(options->nls);
		kfree(options->nls_name);
		kfree(options);
		put_mount_options(sbi->options);
		sbi->options = NULL;
	}