Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eae8d825 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: Fix wild memory access in compression level parser



[BUG]
Kernel panic when mounting with "-o compress" mount option.
KASAN will report like:
------
==================================================================
BUG: KASAN: wild-memory-access in strncmp+0x31/0xc0
Read of size 1 at addr d86735fce994f800 by task mount/662
...
Call Trace:
 dump_stack+0xe3/0x175
 kasan_report+0x163/0x370
 __asan_load1+0x47/0x50
 strncmp+0x31/0xc0
 btrfs_compress_str2level+0x20/0x70 [btrfs]
 btrfs_parse_options+0xff4/0x1870 [btrfs]
 open_ctree+0x2679/0x49f0 [btrfs]
 btrfs_mount+0x1b7f/0x1d30 [btrfs]
 mount_fs+0x49/0x190
 vfs_kern_mount.part.29+0xba/0x280
 vfs_kern_mount+0x13/0x20
 btrfs_mount+0x31e/0x1d30 [btrfs]
 mount_fs+0x49/0x190
 vfs_kern_mount.part.29+0xba/0x280
 do_mount+0xaad/0x1a00
 SyS_mount+0x98/0xe0
 entry_SYSCALL_64_fastpath+0x1f/0xbe
------

[Cause]
For 'compress' and 'compress_force' options, its token doesn't expect
any parameter so its args[0] contains uninitialized data.
Accessing args[0] will cause above wild memory access.

[Fix]
For Opt_compress and Opt_compress_force, set compression level to
the default.

Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
[ set the default in advance ]
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent b77000ed
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1529,5 +1529,5 @@ unsigned int btrfs_compress_str2level(const char *str)
	if (str[4] == ':' && '1' <= str[5] && str[5] <= '9' && str[6] == 0)
		return str[5] - '0';

	return 0;
	return BTRFS_ZLIB_DEFAULT_LEVEL;
}
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
/* Maximum size of data before compression */
#define BTRFS_MAX_UNCOMPRESSED		(SZ_128K)

#define	BTRFS_ZLIB_DEFAULT_LEVEL		3

struct compressed_bio {
	/* number of bios pending for this compressed extent */
	refcount_t pending_bios;
+11 −2
Original line number Diff line number Diff line
@@ -507,7 +507,16 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
			    token == Opt_compress_force ||
			    strncmp(args[0].from, "zlib", 4) == 0) {
				compress_type = "zlib";

				info->compress_type = BTRFS_COMPRESS_ZLIB;
				info->compress_level = BTRFS_ZLIB_DEFAULT_LEVEL;
				/*
				 * args[0] contains uninitialized data since
				 * for these tokens we don't expect any
				 * parameter.
				 */
				if (token != Opt_compress &&
				    token != Opt_compress_force)
					info->compress_level =
					  btrfs_compress_str2level(args[0].from);
				btrfs_set_opt(info->mount_opt, COMPRESS);