Overview
umounting after some operations(with crafted image) can cause use-after-free in ext4_put_super function.
it can be not only local(mount ext4 image in local shell), but also remote(mount corrupted(with crafted ext4 image) USB or other storage)
Target
Linux Kernel ext4 FileSystem
| Linux Version | Availablity |
|---|---|
| 5.0.21 | True |
Reproduce
gcc -o poc poc_2019_19447.c
mkdir mnt
mount poc_2019_19447.img ./mnt
cp poc ./mnt/
cd mnt
./poc
sync
cd ..
umount ./mntRoot cause
fs/ext4/super.c:1022 (link)
static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi)
{
struct list_head *l;
ext4_msg(sb, KERN_ERR, "sb orphan head is %d",
le32_to_cpu(sbi->s_es->s_last_orphan));
printk(KERN_ERR "sb_info orphan list:\n");
list_for_each(l, &sbi->s_orphan) {
struct inode *inode = orphan_list_entry(l);
printk(KERN_ERR " "
[1] "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
inode->i_sb->s_id, inode->i_ino, inode,
inode->i_mode, inode->i_nlink,
NEXT_ORPHAN(inode));
}
}local variable inode is already freed.
it occurs use-after-free in inode->i_mode[1].
Debugger / KASAN
Debugger view:
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
RAX 0x7
RBX 0xffff88805c795500 —▸ 0xffffffff84a52220 (super_blocks) —▸ 0xffff88805e860000 —▸ 0xffff88805e860880 —▸ 0xffff88805e867700 ◂— ...
RCX 0x0
RDX 0xfb
RDI 0xffff888056ca499c ◂— 0x0
RSI 0x8
R8 0xffffed100bdc6061 ◂— 0
R9 0xffffed100bdc6061 ◂— 0
R10 0x228
R11 0xffffed100bdc6060 ◂— 0
R12 0xdffffc0000000000
R13 0xffff888056ca49e0 —▸ 0xffff88805c793d88 ◂— 0xffff888056ca49e0
R14 0xffff88805c793d88 —▸ 0xffff888056ca49e0 ◂— 0xffff88805c793d88
R15 0xffff88805c793b80 ◂— 0x20 /* ' ' */
RBP 0xffff88805866fd10 —▸ 0xffff88805866fd40 —▸ 0xffff88805866fd68 —▸ 0xffff88805866fd88 —▸ 0xffff88805866fe28 ◂— ...
RSP 0xffff88805866fcb0 —▸ 0xffff88805866fca8 —▸ 0xffffffff81b54009 (ext4_put_super+1081) ◂— mov rdx, r14 /* 0xb848f2894c */
RIP 0xffffffff81b54822 (ext4_put_super+3154) ◂— 0xfea8e9ffc406e9e8
──────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────
0xffffffff81b546c5 <ext4_put_super+2805> add eax, 3
0xffffffff81b546c8 <ext4_put_super+2808> cmp al, dl
0xffffffff81b546ca <ext4_put_super+2810> jl ext4_put_super+2820 <0xffffffff81b546d4>
0xffffffff81b546cc <ext4_put_super+2812> test dl, dl
0xffffffff81b546ce <ext4_put_super+2814> jne ext4_put_super+3154 <0xffffffff81b54822>
↓
► 0xffffffff81b54822 <ext4_put_super+3154> call __asan_report_load4_noabort <0xffffffff81794f10>
rdi: 0xffff888056ca499c ◂— 0x0
0xffffffff81b54827 <ext4_put_super+3159> jmp ext4_put_super+2820 <0xffffffff81b546d4>
0xffffffff81b5482c <ext4_put_super+3164> call __asan_report_load4_noabort <0xffffffff81794f10>
0xffffffff81b54831 <ext4_put_super+3169> jmp ext4_put_super+2858 <0xffffffff81b546fa>
0xffffffff81b54836 <ext4_put_super+3174> mov rdi, r14
0xffffffff81b54839 <ext4_put_super+3177> call __asan_report_load8_noabort <0xffffffff81794f30>
───────────────────────────────────────────[ SOURCE (CODE) ]───────────────────────────────────────────
In file: /home/phantom/kernel/ubuntu-eoan/fs/ext4/super.c
932 le32_to_cpu(sbi->s_es->s_last_orphan));
933
934 printk(KERN_ERR "sb_info orphan list:\n");
935 list_for_each(l, &sbi->s_orphan) {
936 struct inode *inode = orphan_list_entry(l);
► 937 printk(KERN_ERR " "
938 "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
939 inode->i_sb->s_id, inode->i_ino, inode,
940 inode->i_mode, inode->i_nlink,
941 NEXT_ORPHAN(inode));
942 }
───────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
00:0000│ rsp 0xffff88805866fcb0 —▸ 0xffff88805866fca8 —▸ 0xffffffff81b54009 (ext4_put_super+1081) ◂— mov rdx, r14 /* 0xb848f2894c */
01:0008│ 0xffff88805866fcb8 —▸ 0xffffffff818fe3cd (__sync_blockdev+93) ◂— pop rbx /* 0x7500023c80c35d5b */
02:0010│ 0xffff88805866fcc0 —▸ 0xffff88805c793be8 —▸ 0xffff888058c3b400 ◂— 0x400000001000
03:0018│ 0xffff88805866fcc8 —▸ 0xffff88805c793bf0 —▸ 0xffff88805b86b648 ◂— 0x0
04:0020│ 0xffff88805866fcd0 —▸ 0xffff88805c793bb0 ◂— 1
05:0028│ 0xffff88805866fcd8 —▸ 0xffff88805c7958a8 —▸ 0xffff88805c793b80 ◂— 0x20 /* ' ' */
06:0030│ 0xffff88805866fce0 —▸ 0xffff888056ca4a48 ◂— 0xd81a4
07:0038│ 0xffff88805866fce8 —▸ 0xffff88805c795500 —▸ 0xffffffff84a52220 (super_blocks) —▸ 0xffff88805e860000 —▸ 0xffff88805e860880 ◂— ...
─────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
► f 0 ffffffff81b54822 ext4_put_super+3154
f 1 ffffffff81b54822 ext4_put_super+3154
f 2 ffffffff81825327 generic_shutdown_super+311
f 3 ffffffff81827704 kill_block_super+164
f 4 ffffffff818265f7 deactivate_locked_super+151
f 5 ffffffff8182763e deactivate_super+350
f 6 ffffffff8188da72 cleanup_mnt+674
f 7 ffffffff8188dc62 __cleanup_mnt+18
f 8 ffffffff81213f5c task_work_run+268
f 9 ffffffff8100844c exit_to_usermode_loop+444
f 10 ffffffff8100844c exit_to_usermode_loop+444
───────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> x/xg $25->i_mode
0x0 <fixed_percpu_data>: Cannot access memory at address 0x0
pwndbg> x/xg &$25->i_mode
0xffff888056ca499c: 0x0000000000000000
KASAN log on umount (the per-object orphan-list hex dump printed on poc execution is omitted for brevity):
[ 71.797689] ==================================================================
[ 71.799205] BUG: KASAN: use-after-free in ext4_put_super+0xc57/0xd30
[ 71.799205] Read of size 4 at addr ffff88805711a5bc by task umount/327
[ 71.799205]
[ 71.799205] CPU: 0 PID: 327 Comm: umount Not tainted 5.3.7 #1
[ 71.799205] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[ 71.799205] Call Trace:
[ 71.799205] dump_stack+0x7b/0xb5
[ 71.799205] print_address_description+0x7c/0x3b0
[ 71.799205] ? ext4_put_super+0xc57/0xd30
[ 71.799205] __kasan_report+0x134/0x191
[ 71.799205] ? ext4_put_super+0xc57/0xd30
[ 71.799205] ? ext4_put_super+0xc57/0xd30
[ 71.799205] kasan_report+0x12/0x20
[ 71.799205] __asan_report_load4_noabort+0x14/0x20
[ 71.799205] ext4_put_super+0xc57/0xd30
[ 71.799205] ? __sync_blockdev+0x5d/0xb0
[ 71.799205] generic_shutdown_super+0x137/0x380
[ 71.799205] kill_block_super+0xa4/0x1f0
[ 71.799205] deactivate_locked_super+0x97/0xe0
[ 71.799205] deactivate_super+0x15e/0x180
[ 71.799205] ? destroy_unused_super+0xf0/0xf0
[ 71.799205] ? dput+0x5e/0x780
[ 71.799205] cleanup_mnt+0x2a2/0x400
[ 71.799205] __cleanup_mnt+0x12/0x20
[ 71.799205] task_work_run+0x10c/0x180
[ 71.799205] exit_to_usermode_loop+0x1bc/0x280
[ 71.799205] do_syscall_64+0x25b/0x2f0
[ 71.799205] ? prepare_exit_to_usermode+0xf1/0x1a0
[ 71.799205] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 71.799205] RIP: 0033:0x7f2018f8ed77
[ 71.799205] Code: 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 31 f6 e9 09 00 00 00 66 0f 1f 84 00 00 00 00 00 b8 a6 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d f1 00 2b 00 f7 d8 64 89 01 48
[ 71.799205] RSP: 002b:00007ffecf2bf808 EFLAGS: 00000246 ORIG_RAX: 00000000000000a6
[ 71.799205] RAX: 0000000000000000 RBX: 000055ae60680060 RCX: 00007f2018f8ed77
[ 71.799205] RDX: 0000000000000001 RSI: 0000000000000000 RDI: 000055ae60686e30
[ 71.799205] RBP: 000055ae60686e30 R08: 000055ae60685080 R09: 0000000000000014
[ 71.799205] R10: 00000000000006b4 R11: 0000000000000246 R12: 00007f2019490e64
[ 71.799205] R13: 0000000000000000 R14: 000055ae60680240 R15: 00007ffecf2bfa90
[ 71.799205]
[ 71.799205] Allocated by task 324:
[ 71.799205] save_stack+0x21/0x90
[ 71.799205] __kasan_kmalloc+0xcc/0xe0
[ 71.799205] kasan_slab_alloc+0x14/0x20
[ 71.799205] kmem_cache_alloc+0xd3/0x260
[ 71.799205] ext4_alloc_inode+0x1d/0x700
[ 71.799205] alloc_inode+0x60/0x190
[ 71.799205] iget_locked+0x157/0x3f0
[ 71.799205] __ext4_iget+0x210/0x5620
[ 71.799205] ext4_lookup+0x2ad/0x6d0
[ 71.799205] __lookup_slow+0x1af/0x3a0
[ 71.799205] lookup_slow+0x56/0x80
[ 71.799205] walk_component+0x6a5/0xfa0
[ 71.799205] path_lookupat+0x18f/0x8c0
[ 71.799205] filename_lookup+0x183/0x3c0
[ 71.799205] user_path_at_empty+0x36/0x40
[ 71.799205] do_sys_truncate+0x8e/0x120
[ 71.799205] __x64_sys_truncate+0x54/0x80
[ 71.799205] do_syscall_64+0xa5/0x2f0
[ 71.799205] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 71.799205]
[ 71.799205] Freed by task 9:
[ 71.799205] save_stack+0x21/0x90
[ 71.799205] __kasan_slab_free+0x137/0x180
[ 71.799205] kasan_slab_free+0xe/0x10
[ 71.799205] kmem_cache_free+0xe3/0x2e0
[ 71.799205] ext4_free_in_core_inode+0x25/0x30
[ 71.799205] i_callback+0x44/0x70
[ 71.799205] rcu_core+0x414/0xe90
[ 71.799205] rcu_core_si+0xe/0x10
[ 71.799205] __do_softirq+0x1b2/0x605
[ 71.799205]
[ 71.799205] The buggy address belongs to the object at ffff88805711a580
[ 71.799205] which belongs to the cache ext4_inode_cache of size 1072
[ 71.799205] The buggy address is located 60 bytes inside of
[ 71.799205] 1072-byte region [ffff88805711a580, ffff88805711a9b0)
[ 71.799205] The buggy address belongs to the page:
[ 71.799205] page:ffffea00015c4600 refcount:1 mapcount:0 mapping:ffff88805c8c6600 index:0x0 compound_mapcount: 0
[ 71.799205] flags: 0xfffffc0010200(slab|head)
[ 71.799205] raw: 000fffffc0010200 dead000000000100 dead000000000122 ffff88805c8c6600
[ 71.799205] raw: 0000000000000000 00000000800d000d 00000001ffffffff 0000000000000000
[ 71.799205] page dumped because: kasan: bad access detected
[ 71.799205]
[ 71.799205] Memory state around the buggy address:
[ 71.799205] ffff88805711a480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 71.799205] ffff88805711a500: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 71.799205] >ffff88805711a580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 71.799205] ^
[ 71.799205] ffff88805711a600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 71.799205] ffff88805711a680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 71.799205] ==================================================================
[ 71.799205] Disabling lock debugging due to kernel taint
[ 71.841308] inode loop0:16 at 000000003fa23361: mode 100644, nlink 1, next 0
[ 71.843393] ------------[ cut here ]------------
[ 71.843657] kernel BUG at fs/ext4/super.c:1028!
...
Details
CVSS 7.8 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H), CWE-416, published 2019-12-08, last modified 2024-11-21.
Attribution
Found as part of the Best of the Best (BoB) 8th bobfuzzer team project — a five-person team that ported the JANUS file-system fuzzer. This is team work, not sole authorship.