Bug 199849
Summary: | Invalid pointer dereference in io_ctl_map_page() when mounting and operating a crafted btrfs image | ||
---|---|---|---|
Product: | File System | Reporter: | Wen Xu (wen.xu) |
Component: | btrfs | Assignee: | BTRFS virtual assignee (fs_btrfs) |
Status: | RESOLVED CODE_FIX | ||
Severity: | normal | CC: | 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
poc.c |
Created attachment 276217 [details]
poc.c
|
Created attachment 276215 [details] The (compressed) crafted image which causes crash - Overview Invalid pointer dereference in io_ctl_map_page() when mounting and operating a crafted btrfs image - Reproduce (4.17-rc5) # mkdir mnt # mount -t btrfs 6.img mnt # gcc -o poc poc.c # ./poc ./mnt - Kernel message [ 190.329292] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 [ 190.330849] PGD 80000001e7843067 P4D 80000001e7843067 PUD 1e8278067 PMD 0 [ 190.332422] Oops: 0000 [#1] SMP KASAN PTI [ 190.333354] Modules linked in: snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd mac_hid soundcore i2c_piix4 ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi autofs4 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx raid1 raid0 multipath linear 8139too crct10dif_pclmul qxl crc32_pclmul drm_kms_helper aesni_intel syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm aes_x86_64 crypto_simd cryptd glue_helper pata_acpi 8139cp floppy mii [ 190.343124] CPU: 0 PID: 1308 Comm: btrfs-transacti Tainted: G B W 4.17.0-rc5+ #6 [ 190.344786] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 [ 190.346638] RIP: 0010:io_ctl_map_page+0x40/0xc0 [ 190.347530] RSP: 0018:ffff8801f3497a38 EFLAGS: 00010282 [ 190.348558] RAX: 0000000000000000 RBX: ffff8801e60f29e8 RCX: 0000000000000000 [ 190.349962] RDX: 0000000000000000 RSI: 0000000000000297 RDI: 0000000000000297 [ 190.351342] RBP: ffff8801f3497a50 R08: ffffed003ee03ebb R09: ffffed003ee03ebb [ 190.352727] R10: 0000000000000001 R11: ffffed003ee03eba R12: 0000000000000010 [ 190.354109] R13: 0000000000000001 R14: ffff8801cb60c348 R15: ffff8801df3c3b80 [ 190.355495] FS: 0000000000000000(0000) GS:ffff8801f7000000(0000) knlGS:0000000000000000 [ 190.357080] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 190.358205] CR2: 0000000000000010 CR3: 00000001e0c84000 CR4: 00000000000006f0 [ 190.359586] Call Trace: [ 190.360088] __btrfs_write_out_cache+0x361/0x820 [ 190.361024] ? io_ctl_init+0x1c0/0x1c0 [ 190.361765] ? _atomic_dec_and_lock+0x1f/0x70 [ 190.362622] ? iput+0xc2/0x300 [ 190.363234] ? _raw_spin_lock+0x17/0x40 [ 190.363993] ? cache_save_setup+0x1fc/0x5c0 [ 190.364836] ? kasan_check_write+0x14/0x20 [ 190.365648] ? __iget+0x1e/0x30 [ 190.366275] ? igrab+0x3b/0x70 [ 190.366888] ? lookup_free_space_inode+0x49/0x170 [ 190.367811] btrfs_write_out_cache+0xc9/0x130 [ 190.368682] btrfs_start_dirty_block_groups+0x42e/0x7c0 [ 190.369717] ? btrfs_force_chunk_alloc+0x40/0x40 [ 190.370633] btrfs_commit_transaction+0x19f/0xfa0 [ 190.371565] ? kasan_check_write+0x14/0x20 [ 190.372380] ? join_transaction+0x645/0x6a0 [ 190.373236] ? btrfs_record_root_in_trans+0x24/0xb0 [ 190.374202] ? btrfs_apply_pending_changes+0xa0/0xa0 [ 190.375185] ? start_transaction+0x153/0x640 [ 190.376039] transaction_kthread+0x225/0x250 [ 190.376907] kthread+0x180/0x1d0 [ 190.377561] ? btrfs_cleanup_transaction+0xac0/0xac0 [ 190.378548] ? kthread_associate_blkcg+0x150/0x150 [ 190.379501] ret_from_fork+0x35/0x40 [ 190.380218] Code: 41 89 f5 e8 43 cf ba ff 48 8d 7b 38 4c 8b 63 18 e8 36 ce ba ff 48 63 43 38 4d 8d 24 c4 8d 50 01 4c 89 e7 89 53 38 e8 20 cf ba ff <4d> 8b 24 24 48 8d 7b 10 e8 a3 cf ba ff 4c 89 63 10 48 c7 c7 f0 [ 190.383954] RIP: io_ctl_map_page+0x40/0xc0 RSP: ffff8801f3497a38 [ 190.385157] CR2: 0000000000000010 [ 190.385821] ---[ end trace 1297a390ba7e0a67 ]--- - Reason static void io_ctl_map_page(struct btrfs_io_ctl *io_ctl, int clear) { ASSERT(io_ctl->index < io_ctl->num_pages); io_ctl->page = io_ctl->pages[io_ctl->index++]; io_ctl->cur = page_address(io_ctl->page); io_ctl->orig = io_ctl->cur; io_ctl->size = PAGE_SIZE; if (clear) clear_page(io_ctl->cur); } io_ctl->pages is not properly initialized. - Credit Found by Wen Xu and Po-Ning Tseng from SSLab, Gatech.