Bug 199417

Summary: out-of-bound access in ext4_ext_drop_refs() when operating on a crafted ext4 image
Product: File System Reporter: Wen Xu (wen.xu)
Component: ext4Assignee: fs_ext4 (fs_ext4)
Status: RESOLVED CODE_FIX    
Severity: normal CC: tytso, wen.xu
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 4.16, 4.17 Subsystem:
Regression: No Bisected commit-id:
Attachments: The crafted image which causes kernel panic
poc.c

Description Wen Xu 2018-04-16 20:15:09 UTC
Created attachment 275407 [details]
The crafted image which causes kernel panic

- Overview
out-of-bound access in ext4_ext_drop_refs() when operating on a crafted ext4 image

- Reproduce
# mkdir mnt
# mount -t ext4 91.img mnt
# gcc -o poc poc.c
# ./poc ./mnt

I reproduced it on both ext4 dev branch (4.16) and upstream kernel (4.17).

- Reason
https://elixir.bootlin.com/linux/latest/source/fs/ext4/extents.c#L711

void ext4_ext_drop_refs(struct ext4_ext_path *path)
{
	int depth, i;

	if (!path)
		return;
	depth = path->p_depth;
	for (i = 0; i <= depth; i++, path++)
		if (path->p_bh) {
			brelse(path->p_bh);
			path->p_bh = NULL;
		}
}
Here it seems kernel lacks sanitary checks on depth, which makes the pointer path move out of its boundary.

- Kernel Message
[  237.005192] EXT4-fs (loop0): warning: checktime reached, running e2fsck is recommended
[  237.048673] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null)
[  240.488058] EXT4-fs error (device loop0): ext4_find_extent:903: inode #5: comm poc: pblk 0 bad header/extent: invalid magic - magic 0, entries 0, max 0(0), depth 0(4294967294)
[  240.525640] Aborting journal on device loop0-8.
[  240.547657] EXT4-fs (loop0): Remounting filesystem read-only
[  240.548579] ==================================================================
[  240.549942] BUG: KASAN: slab-out-of-bounds in ext4_ext_drop_refs+0x33/0x70
[  240.551051] Read of size 8 at addr ffff880115ec94d8 by task poc/1350

[  240.552272] CPU: 0 PID: 1350 Comm: poc Not tainted 4.16.0-rc1+ #3
[  240.552276] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[  240.552279] Call Trace:
[  240.552302]  dump_stack+0x63/0x8d
[  240.552317]  print_address_description+0x70/0x290
[  240.552323]  kasan_report+0x290/0x390
[  240.552329]  ? ext4_ext_drop_refs+0x33/0x70
[  240.552338]  __asan_load8+0x54/0x90
[  240.552344]  ext4_ext_drop_refs+0x33/0x70
[  240.552350]  ext4_find_extent+0x259/0x450
[  240.552357]  ext4_ext_map_blocks+0x144/0x1f60
[  240.552363]  ? save_stack+0x46/0xd0
[  240.552370]  ? kasan_kmalloc+0xad/0xe0
[  240.552377]  ? ext4_iget+0xf8/0x16e0
[  240.552383]  ? ext4_find_delalloc_cluster+0x60/0x60
[  240.552397]  ? generic_permission+0x192/0x1e0
[  240.552402]  ? may_open+0xd9/0x150
[  240.552409]  ? path_openat+0x47f/0x1e30
[  240.552415]  ? do_filp_open+0x12b/0x1d0
[  240.552421]  ? do_sys_open+0x17c/0x2c0
[  240.552426]  ? SyS_open+0x1e/0x20
[  240.552438]  ? do_syscall_64+0xf2/0x1f0
[  240.552450]  ? entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.552463]  ? update_stack_state+0x27c/0x3e0
[  240.552470]  ? __read_once_size_nocheck.constprop.7+0x20/0x20
[  240.552478]  ? __save_stack_trace+0x5e/0x100
[  240.552488]  ? mark_page_accessed+0x133/0x200
[  240.552496]  ? __find_get_block+0xf8/0x3c0
[  240.552506]  ? map_id_range_down+0x195/0x1c0
[  240.552513]  ? ext4_es_lookup_extent+0xfc/0x2f0
[  240.552518]  ext4_map_blocks+0x683/0xa50
[  240.552525]  ? kasan_kmalloc+0xad/0xe0
[  240.552531]  ? ext4_issue_zeroout+0xa0/0xa0
[  240.552540]  ? wake_atomic_t_function+0xa0/0xa0
[  240.552547]  ? inode_sb_list_add+0x93/0xc0
[  240.552554]  ? inode_set_flags+0x2b/0x50
[  240.552559]  ext4_getblk+0xa6/0x2a0
[  240.552564]  ? ext4_iget+0x135e/0x16e0
[  240.552569]  ? ext4_iomap_begin+0x7a0/0x7a0
[  240.552576]  ext4_bread_batch+0x5c/0x1c0
[  240.552588]  ext4_xattr_inode_read+0x1d1/0x2f0
[  240.552596]  ? ext4_xattr_inode_free_quota.part.28+0x90/0x90
[  240.552602]  ? kasan_kmalloc+0xad/0xe0
[  240.552607]  ? __kmalloc+0x109/0x230
[  240.552613]  ? ext4_get_acl+0x63/0x2d0
[  240.552620]  ? get_acl+0xa3/0x140
[  240.552626]  ? generic_permission+0x192/0x1e0
[  240.552631]  ? inode_permission+0x46/0x1f0
[  240.552636]  ? may_open+0xd9/0x150
[  240.552642]  ? path_openat+0x47f/0x1e30
[  240.552649]  ? _cond_resched+0x1a/0x50
[  240.552656]  ? up_write+0x16/0x40
[  240.552661]  ? ext4_xattr_inode_iget+0xd2/0x200
[  240.552668]  ext4_xattr_inode_get+0x13a/0x430
[  240.552674]  ? ext4_xattr_release_block+0x3d0/0x3d0
[  240.552680]  ? mb_cache_entry_create+0x180/0x2c0
[  240.552684]  ? kasan_slab_free+0xe/0x10
[  240.552690]  ? kmem_cache_free+0x7c/0x1f0
[  240.552697]  ? strlen+0xf/0x40
[  240.552702]  ? xattr_find_entry+0xb0/0x140
[  240.552708]  ext4_xattr_get+0x4b6/0x4d0
[  240.552715]  ? ext4_xattr_ibody_get+0x320/0x320
[  240.552721]  ? __kmalloc+0x109/0x230
[  240.552726]  ext4_get_acl+0x8e/0x2d0
[  240.552732]  ? __d_rehash+0x89/0xb0
[  240.552737]  get_acl+0xa3/0x140
[  240.552744]  generic_permission+0x192/0x1e0
[  240.552750]  inode_permission+0x46/0x1f0
[  240.552756]  may_open+0xd9/0x150
[  240.552762]  path_openat+0x47f/0x1e30
[  240.552767]  ? __save_stack_trace+0x92/0x100
[  240.552775]  ? vfs_link+0x4e0/0x4e0
[  240.552781]  ? kasan_kmalloc+0xad/0xe0
[  240.552787]  ? kmem_cache_alloc+0xbb/0x1d0
[  240.552792]  ? getname_flags+0x76/0x2c0
[  240.552798]  ? getname+0x12/0x20
[  240.552802]  ? do_sys_open+0x14b/0x2c0
[  240.552807]  ? SyS_open+0x1e/0x20
[  240.552812]  ? do_syscall_64+0xf2/0x1f0
[  240.552818]  ? entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.552823]  ? exit_to_usermode_loop+0xf2/0x100
[  240.552828]  ? do_syscall_64+0x1c0/0x1f0
[  240.552834]  ? entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.552842]  ? __ext4_journal_stop+0xa0/0x100
[  240.552849]  do_filp_open+0x12b/0x1d0
[  240.552855]  ? may_open_dev+0x50/0x50
[  240.552862]  ? kasan_kmalloc+0xad/0xe0
[  240.552869]  do_sys_open+0x17c/0x2c0
[  240.552874]  ? do_sys_open+0x17c/0x2c0
[  240.552879]  ? filp_open+0x60/0x60
[  240.552885]  ? mem_cgroup_handle_over_high+0x21/0xd0
[  240.552890]  ? do_sys_open+0x2c0/0x2c0
[  240.552895]  SyS_open+0x1e/0x20
[  240.552900]  do_syscall_64+0xf2/0x1f0
[  240.552907]  entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.552912] RIP: 0033:0x7f979d764040
[  240.552914] RSP: 002b:00007ffc945a5f88 EFLAGS: 00000246 ORIG_RAX: 0000000000000002
[  240.552925] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f979d764040
[  240.552928] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000002143080
[  240.552931] RBP: 00007ffc945a60f0 R08: 00007f979da31bd8 R09: 0000000000000001
[  240.552934] R10: 000000000000069d R11: 0000000000000246 R12: 0000000000400c20
[  240.552937] R13: 00007ffc945a61f0 R14: 0000000000000000 R15: 0000000000000000

[  240.553197] Allocated by task 1350:
[  240.553749]  save_stack+0x46/0xd0
[  240.553754]  kasan_kmalloc+0xad/0xe0
[  240.553759]  __kmalloc+0x109/0x230
[  240.553764]  ext4_find_extent+0x3cf/0x450
[  240.553770]  ext4_ext_map_blocks+0x144/0x1f60
[  240.553774]  ext4_map_blocks+0x683/0xa50
[  240.553778]  ext4_getblk+0xa6/0x2a0
[  240.553782]  ext4_bread_batch+0x5c/0x1c0
[  240.553787]  ext4_xattr_inode_read+0x1d1/0x2f0
[  240.553792]  ext4_xattr_inode_get+0x13a/0x430
[  240.553797]  ext4_xattr_get+0x4b6/0x4d0
[  240.553802]  ext4_get_acl+0x8e/0x2d0
[  240.553806]  get_acl+0xa3/0x140
[  240.553812]  generic_permission+0x192/0x1e0
[  240.553817]  inode_permission+0x46/0x1f0
[  240.553822]  may_open+0xd9/0x150
[  240.553827]  path_openat+0x47f/0x1e30
[  240.553832]  do_filp_open+0x12b/0x1d0
[  240.553836]  do_sys_open+0x17c/0x2c0
[  240.553840]  SyS_open+0x1e/0x20
[  240.553845]  do_syscall_64+0xf2/0x1f0
[  240.553851]  entry_SYSCALL_64_after_hwframe+0x21/0x86

[  240.554099] Freed by task 1157:
[  240.554611]  save_stack+0x46/0xd0
[  240.554618]  __kasan_slab_free+0x13e/0x1a0
[  240.554621]  kasan_slab_free+0xe/0x10
[  240.554626]  kfree+0x90/0x1b0
[  240.554635]  kernfs_put_open_node.isra.10+0xc2/0xf0
[  240.554641]  kernfs_fop_release+0x6c/0x120
[  240.554646]  __fput+0x17a/0x350
[  240.554651]  ____fput+0xe/0x10
[  240.554658]  task_work_run+0xba/0xe0
[  240.554663]  exit_to_usermode_loop+0xf2/0x100
[  240.554668]  do_syscall_64+0x1c0/0x1f0
[  240.554673]  entry_SYSCALL_64_after_hwframe+0x21/0x86

[  240.554924] The buggy address belongs to the object at ffff880115ec9480
                which belongs to the cache kmalloc-64 of size 64
[  240.556787] The buggy address is located 24 bytes to the right of
                64-byte region [ffff880115ec9480, ffff880115ec94c0)
[  240.558619] The buggy address belongs to the page:
[  240.559366] page:ffffea000457b240 count:1 mapcount:0 mapping:          (null) index:0x0
[  240.560591] flags: 0x2ffff0000000100(slab)
[  240.561235] raw: 02ffff0000000100 0000000000000000 0000000000000000 00000001802a002a
[  240.562432] raw: ffffea0004548d00 0000000d0000000d ffff88011ac01700 0000000000000000
[  240.563599] page dumped because: kasan: bad access detected

[  240.564693] Memory state around the buggy address:
[  240.565428]  ffff880115ec9380: 00 00 07 fc fc fc fc fc fb fb fb fb fb fb fb fb
[  240.566531]  ffff880115ec9400: fc fc fc fc fb fb fb fb fb fb fb fb fc fc fc fc
[  240.567628] >ffff880115ec9480: 00 00 00 00 00 00 fc fc fc fc fc fc fb fb fb fb
[  240.568729]                                                     ^
[  240.569661]  ffff880115ec9500: fb fb fb fb fc fc fc fc fb fb fb fb fb fb fb fb
[  240.570764]  ffff880115ec9580: fc fc fc fc fb fb fb fb fb fb fb fb fc fc fc fc
[  240.571868] ==================================================================
[  240.572970] Disabling lock debugging due to kernel taint
[  240.573040] general protection fault: 0000 [#1] SMP KASAN PTI
[  240.573934] Modules linked in: snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd i2c_piix4 soundcore mac_hid ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi autofs4 btrfs zstd_decompress zstd_compress xxhash raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq raid1 raid0 multipath linear 8139too qxl drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm crct10dif_pclmul crc32_pclmul aesni_intel aes_x86_64 crypto_simd cryptd 8139cp glue_helper floppy mii pata_acpi
[  240.582372] CPU: 0 PID: 1350 Comm: poc Tainted: G    B            4.16.0-rc1+ #3
[  240.583499] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[  240.584940] RIP: 0010:__brelse+0x16/0x40
[  240.585552] RSP: 0018:ffff88011392f190 EFLAGS: 00010296
[  240.586367] RAX: 0000000000000000 RBX: 6f6602030000000c RCX: ffffffff934081b6
[  240.587448] RDX: 0000000000000000 RSI: 0000000000000004 RDI: 6f6602030000006c
[  240.588533] RBP: ffff88011392f198 R08: fffffbfff2a80459 R09: ffffffff954022fc
[  240.589617] R10: 000000000000000b R11: fffffbfff2a80458 R12: 0000000000000002
[  240.590717] R13: 000000000000ffff R14: 000000000000ffff R15: ffffffffffffff8b
[  240.591812] FS:  00007f979dc52700(0000) GS:ffff88011b000000(0000) knlGS:0000000000000000
[  240.593044] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  240.593924] CR2: 000000000214b158 CR3: 00000001132fa000 CR4: 00000000000006f0
[  240.595030] Call Trace:
[  240.595424]  ext4_ext_drop_refs+0x40/0x70
[  240.596054]  ext4_find_extent+0x259/0x450
[  240.596682]  ext4_ext_map_blocks+0x144/0x1f60
[  240.597369]  ? save_stack+0x46/0xd0
[  240.597919]  ? kasan_kmalloc+0xad/0xe0
[  240.598517]  ? ext4_iget+0xf8/0x16e0
[  240.599083]  ? ext4_find_delalloc_cluster+0x60/0x60
[  240.599845]  ? generic_permission+0x192/0x1e0
[  240.600526]  ? may_open+0xd9/0x150
[  240.601065]  ? path_openat+0x47f/0x1e30
[  240.601664]  ? do_filp_open+0x12b/0x1d0
[  240.602274]  ? do_sys_open+0x17c/0x2c0
[  240.602858]  ? SyS_open+0x1e/0x20
[  240.603378]  ? do_syscall_64+0xf2/0x1f0
[  240.603973]  ? entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.604781]  ? update_stack_state+0x27c/0x3e0
[  240.605459]  ? __read_once_size_nocheck.constprop.7+0x20/0x20
[  240.606351]  ? __save_stack_trace+0x5e/0x100
[  240.607011]  ? mark_page_accessed+0x133/0x200
[  240.607685]  ? __find_get_block+0xf8/0x3c0
[  240.608318]  ? map_id_range_down+0x195/0x1c0
[  240.608977]  ? ext4_es_lookup_extent+0xfc/0x2f0
[  240.609672]  ext4_map_blocks+0x683/0xa50
[  240.610313]  ? kasan_kmalloc+0xad/0xe0
[  240.610899]  ? ext4_issue_zeroout+0xa0/0xa0
[  240.611548]  ? wake_atomic_t_function+0xa0/0xa0
[  240.612250]  ? inode_sb_list_add+0x93/0xc0
[  240.612888]  ? inode_set_flags+0x2b/0x50
[  240.613499]  ext4_getblk+0xa6/0x2a0
[  240.614045]  ? ext4_iget+0x135e/0x16e0
[  240.614642]  ? ext4_iomap_begin+0x7a0/0x7a0
[  240.615291]  ext4_bread_batch+0x5c/0x1c0
[  240.615904]  ext4_xattr_inode_read+0x1d1/0x2f0
[  240.616593]  ? ext4_xattr_inode_free_quota.part.28+0x90/0x90
[  240.617465]  ? kasan_kmalloc+0xad/0xe0
[  240.618050]  ? __kmalloc+0x109/0x230
[  240.618619]  ? ext4_get_acl+0x63/0x2d0
[  240.619204]  ? get_acl+0xa3/0x140
[  240.619727]  ? generic_permission+0x192/0x1e0
[  240.620403]  ? inode_permission+0x46/0x1f0
[  240.621040]  ? may_open+0xd9/0x150
[  240.621575]  ? path_openat+0x47f/0x1e30
[  240.622177]  ? _cond_resched+0x1a/0x50
[  240.622775]  ? up_write+0x16/0x40
[  240.623301]  ? ext4_xattr_inode_iget+0xd2/0x200
[  240.624008]  ext4_xattr_inode_get+0x13a/0x430
[  240.624684]  ? ext4_xattr_release_block+0x3d0/0x3d0
[  240.625442]  ? mb_cache_entry_create+0x180/0x2c0
[  240.626158]  ? kasan_slab_free+0xe/0x10
[  240.626770]  ? kmem_cache_free+0x7c/0x1f0
[  240.627400]  ? strlen+0xf/0x40
[  240.627886]  ? xattr_find_entry+0xb0/0x140
[  240.628531]  ext4_xattr_get+0x4b6/0x4d0
[  240.629136]  ? ext4_xattr_ibody_get+0x320/0x320
[  240.629844]  ? __kmalloc+0x109/0x230
[  240.630421]  ext4_get_acl+0x8e/0x2d0
[  240.630985]  ? __d_rehash+0x89/0xb0
[  240.631538]  get_acl+0xa3/0x140
[  240.632037]  generic_permission+0x192/0x1e0
[  240.632697]  inode_permission+0x46/0x1f0
[  240.633315]  may_open+0xd9/0x150
[  240.633828]  path_openat+0x47f/0x1e30
[  240.634416]  ? __save_stack_trace+0x92/0x100
[  240.635082]  ? vfs_link+0x4e0/0x4e0
[  240.635632]  ? kasan_kmalloc+0xad/0xe0
[  240.636219]  ? kmem_cache_alloc+0xbb/0x1d0
[  240.636859]  ? getname_flags+0x76/0x2c0
[  240.637458]  ? getname+0x12/0x20
[  240.637993]  ? do_sys_open+0x14b/0x2c0
[  240.638592]  ? SyS_open+0x1e/0x20
[  240.639116]  ? do_syscall_64+0xf2/0x1f0
[  240.639721]  ? entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.640533]  ? exit_to_usermode_loop+0xf2/0x100
[  240.641238]  ? do_syscall_64+0x1c0/0x1f0
[  240.641854]  ? entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.642676]  ? __ext4_journal_stop+0xa0/0x100
[  240.643357]  do_filp_open+0x12b/0x1d0
[  240.643933]  ? may_open_dev+0x50/0x50
[  240.644511]  ? kasan_kmalloc+0xad/0xe0
[  240.645101]  do_sys_open+0x17c/0x2c0
[  240.645664]  ? do_sys_open+0x17c/0x2c0
[  240.646263]  ? filp_open+0x60/0x60
[  240.646801]  ? mem_cgroup_handle_over_high+0x21/0xd0
[  240.647572]  ? do_sys_open+0x2c0/0x2c0
[  240.648175]  SyS_open+0x1e/0x20
[  240.648695]  do_syscall_64+0xf2/0x1f0
[  240.649287]  entry_SYSCALL_64_after_hwframe+0x21/0x86
[  240.650066] RIP: 0033:0x7f979d764040
[  240.650636] RSP: 002b:00007ffc945a5f88 EFLAGS: 00000246 ORIG_RAX: 0000000000000002
[  240.651791] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f979d764040
[  240.652878] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000002143080
[  240.653960] RBP: 00007ffc945a60f0 R08: 00007f979da31bd8 R09: 0000000000000001
[  240.655053] R10: 000000000000069d R11: 0000000000000246 R12: 0000000000400c20
[  240.656136] R13: 00007ffc945a61f0 R14: 0000000000000000 R15: 0000000000000000
[  240.657220] Code: ff ff ff 31 c0 5d c3 0f 1f 40 00 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 53 48 89 fb 48 83 c7 60 e8 5a 63 f6 ff <8b> 43 60 85 c0 74 07 3e ff 4b 60 5b 5d c3 48 c7 c7 a0 21 51 94 
[  240.660183] RIP: __brelse+0x16/0x40 RSP: ffff88011392f190
[  240.661063] ---[ end trace b32f37694f699b71 ]---

Reported by Wen Xu at SSlab, Gatech
Comment 1 Wen Xu 2018-04-16 20:15:24 UTC
Created attachment 275409 [details]
poc.c
Comment 2 Theodore Tso 2018-06-14 21:09:16 UTC
*** Bug 199989 has been marked as a duplicate of this bug. ***
Comment 3 Wen Xu 2018-06-14 22:03:21 UTC
(In reply to Theodore Tso from comment #2)
> *** Bug 199989 has been marked as a duplicate of this bug. ***

Hi Ted,

Could you CC the patch of "ext4: verify the depth of extent tree in ext4_find_extent()" to me? I could not find this as you mentioned under bug 199989.

Thanks,
Wen
Comment 4 Theodore Tso 2018-06-14 23:12:25 UTC
Yeah, sorry, I hadn't sent it out yet.  I've been trying to send out fixes in batches, but then I made the mistake of trying to tackle #200015, which has been a real mess to analyze.
Comment 5 Theodore Tso 2018-06-14 23:46:35 UTC
Fix is here: http://patchwork.ozlabs.org/patch/929744/
Comment 6 Theodore Tso 2018-07-02 15:59:36 UTC
This issue has been assigned CVE-2018-10877

Red Hat Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1596795