Re: [PATCH] btrfs: fix out-of-bounds access in property handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 6.06.19 г. 10:49 ч., Naohiro Aota wrote:
> xattr value is not NULL-terminated string. When you specify "lz" as the
> property value, strncmp("lzo", value, 3) will try to read one byte after
> the value buffer, causing the following OOB access. Fix this out-of-bound
> by explicitly check the required length.
> 
> [ 1519.998589] ==================================================================
> [ 1520.007505] BUG: KASAN: slab-out-of-bounds in strncmp+0xab/0xc0
> [ 1520.015116] Read of size 1 at addr ffff8886daec16c2 by task btrfs/15317
> 
> [ 1520.026628] CPU: 4 PID: 15317 Comm: btrfs Not tainted 5.1.0-rc7+ #3
> [ 1520.034635] Hardware name: Supermicro X10SLL-F/X10SLL-F, BIOS 3.0 04/24/2015
> [ 1520.043416] Call Trace:
> [ 1520.047562]  dump_stack+0x71/0xa0
> [ 1520.052584]  print_address_description+0x65/0x229
> [ 1520.058997]  ? strncmp+0xab/0xc0
> [ 1520.063929]  ? strncmp+0xab/0xc0
> [ 1520.068834]  kasan_report.cold+0x1a/0x38
> [ 1520.074439]  ? strncmp+0xab/0xc0
> [ 1520.079343]  strncmp+0xab/0xc0
> [ 1520.084110]  prop_compression_validate+0x22/0x70 [btrfs]
> [ 1520.091135]  btrfs_xattr_handler_set_prop+0x6c/0x1f0 [btrfs]
> [ 1520.098452]  __vfs_setxattr+0xd8/0x130
> [ 1520.103821]  ? xattr_resolve_name+0x3e0/0x3e0
> [ 1520.109812]  __vfs_setxattr_noperm+0xeb/0x3b0
> [ 1520.115790]  vfs_setxattr+0xa3/0xd0
> [ 1520.120898]  setxattr+0x17a/0x2c0
> [ 1520.125824]  ? vfs_setxattr+0xd0/0xd0
> [ 1520.131102]  ? __pmd_alloc+0x560/0x560
> [ 1520.136452]  ? __do_sys_newfstat+0xd3/0xe0
> [ 1520.142123]  ? __ia32_sys_newfstatat+0xf0/0xf0
> [ 1520.148140]  ? __kasan_slab_free+0x141/0x170
> [ 1520.153955]  ? handle_mm_fault+0x1ae/0x640
> [ 1520.159564]  __x64_sys_fsetxattr+0x1a0/0x220
> [ 1520.165347]  do_syscall_64+0xa0/0x2e0
> [ 1520.170515]  ? page_fault+0x8/0x30
> [ 1520.175408]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> [ 1520.181975] RIP: 0033:0x7f84f257ae6e
> [ 1520.187068] Code: 48 8b 0d 1d 70 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 be 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d ea 6f 0c 00 f7 d8 64 89 01 48
> [ 1520.209083] RSP: 002b:00007fff87996fa8 EFLAGS: 00000246 ORIG_RAX: 00000000000000be
> [ 1520.218336] RAX: ffffffffffffffda RBX: 000000000000000b RCX: 00007f84f257ae6e
> [ 1520.227132] RDX: 00007fff8799798b RSI: 00005561caf83270 RDI: 0000000000000003
> [ 1520.235912] RBP: 00007fff8799798b R08: 0000000000000000 R09: 00005561caf83290
> [ 1520.244691] R10: 0000000000000002 R11: 0000000000000246 R12: 00005561caf83270
> [ 1520.253462] R13: 0000000000000003 R14: 00007fff87997972 R15: 00007fff8799797f
> 
> [ 1520.265443] Allocated by task 15317:
> [ 1520.270697]  __kasan_kmalloc.constprop.0+0xc2/0xd0
> [ 1520.277677]  setxattr+0xe8/0x2c0
> [ 1520.283084]  __x64_sys_fsetxattr+0x1a0/0x220
> [ 1520.289540]  do_syscall_64+0xa0/0x2e0
> [ 1520.295379]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> [ 1520.306288] Freed by task 12227:
> [ 1520.311632]  __kasan_slab_free+0x12c/0x170
> [ 1520.317828]  kfree+0x90/0x1e0
> [ 1520.322891]  btrfs_free_block_groups+0x8a1/0xd80 [btrfs]
> [ 1520.330313]  close_ctree+0x37e/0x650 [btrfs]
> [ 1520.336627]  generic_shutdown_super+0x12e/0x320
> [ 1520.343177]  kill_anon_super+0x36/0x60
> [ 1520.348983]  btrfs_kill_super+0x3d/0x2c0 [btrfs]
> [ 1520.355636]  deactivate_locked_super+0x85/0xd0
> [ 1520.362108]  deactivate_super+0x122/0x140
> [ 1520.368166]  cleanup_mnt+0x9f/0x130
> [ 1520.373699]  task_work_run+0x131/0x1c0
> [ 1520.379490]  exit_to_usermode_loop+0x133/0x160
> [ 1520.386002]  do_syscall_64+0x259/0x2e0
> [ 1520.391796]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> [ 1520.402415] The buggy address belongs to the object at ffff8886daec16c0
>                 which belongs to the cache kmalloc-8 of size 8
> [ 1520.418769] The buggy address is located 2 bytes inside of
>                 8-byte region [ffff8886daec16c0, ffff8886daec16c8)
> [ 1520.434407] The buggy address belongs to the page:
> [ 1520.441358] page:ffffea001b6bb040 count:1 mapcount:0 mapping:ffff8886ff40fb80 index:0x0
> [ 1520.451601] flags: 0x17ffe000000200(slab)
> [ 1520.457868] raw: 0017ffe000000200 ffffea001bedcec0 0000000700000007 ffff8886ff40fb80
> [ 1520.467940] raw: 0000000000000000 0000000080aa00aa 00000001ffffffff 0000000000000000
> [ 1520.478024] page dumped because: kasan: bad access detected
> 
> [ 1520.489795] Memory state around the buggy address:
> [ 1520.496963]  ffff8886daec1580: fc 00 fc fc 00 fc fc 00 fc fc 00 fc fc 00 fc fc
> [ 1520.506621]  ffff8886daec1600: 00 fc fc 04 fc fc fb fc fc fb fc fc fb fc fc fb
> [ 1520.516277] >ffff8886daec1680: fc fc 04 fc fc 00 fc fc 02 fc fc fb fc fc 00 fc
> [ 1520.525915]                                            ^
> [ 1520.533584]  ffff8886daec1700: fc 00 fc fc 00 fc fc 00 fc fc 00 fc fc 04 fc fc
> [ 1520.543137]  ffff8886daec1780: fb fc fc 00 fc fc 00 fc fc 00 fc fc 00 fc fc 00
> [ 1520.552642] ==================================================================
> 
> Fixes: 272e5326c783 ("btrfs: prop: fix vanished compression property after failed set")
> Fixes: 50398fde997f ("btrfs: prop: fix zstd compression parameter validation")
> Cc: stable@xxxxxxxxxxxxxxx # 4.14+: 802a5c69584a: btrfs: prop: use common helper for type to string conversion
> Cc: stable@xxxxxxxxxxxxxxx # 4.14+: 3dcf96c7b9fe: btrfs: drop redundant forward declaration in props.c
> Cc: stable@xxxxxxxxxxxxxxx # 4.14+
> Signed-off-by: Naohiro Aota <naohiro.aota@xxxxxxx>

We caught that one yesterday and were testing various fixes for it
Johannes just sent his version which IMO makes the code a bit more
maintainable.


> ---
>  fs/btrfs/props.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
> index a9e2e66152ee..428141bf545d 100644
> --- a/fs/btrfs/props.c
> +++ b/fs/btrfs/props.c
> @@ -257,11 +257,11 @@ static int prop_compression_validate(const char *value, size_t len)
>  	if (!value)
>  		return 0;
>  
> -	if (!strncmp("lzo", value, 3))
> +	if (len >= 3 && !strncmp("lzo", value, 3))
>  		return 0;
> -	else if (!strncmp("zlib", value, 4))
> +	else if (len >= 4 && !strncmp("zlib", value, 4))
>  		return 0;
> -	else if (!strncmp("zstd", value, 4))
> +	else if (len >= 4 && !strncmp("zstd", value, 4))
>  		return 0;
>  
>  	return -EINVAL;
> @@ -281,12 +281,12 @@ static int prop_compression_apply(struct inode *inode, const char *value,
>  		return 0;
>  	}
>  
> -	if (!strncmp("lzo", value, 3)) {
> +	if (len >= 3 && !strncmp("lzo", value, 3)) {
>  		type = BTRFS_COMPRESS_LZO;
>  		btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
> -	} else if (!strncmp("zlib", value, 4)) {
> +	} else if (len >= 4 && !strncmp("zlib", value, 4)) {
>  		type = BTRFS_COMPRESS_ZLIB;
> -	} else if (!strncmp("zstd", value, 4)) {
> +	} else if (len >= 4 && !strncmp("zstd", value, 4)) {
>  		type = BTRFS_COMPRESS_ZSTD;
>  		btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
>  	} else {

This seems redundant as ->validates is supposed to always be called
before calling ->apply.

> 



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux