Skip to content
cvekernelf2fsnull-pointer-dereference

Linux kernel f2fs NULL pointer dereference

5 min read

Overview

Mount crafted image can cause Null-Ptr-Deref in f2fs_recover_fsync_data function

Target

Linux kernel f2fs FileSystem

Linux Version Availablity
5.0.21 True

Reproduce

mkdir mnt
mount poc_2019_19815.img ./mnt

Root cause

static inline void f2fs_put_page(struct page *page, int unlock)
{
	if (!page)
		return;
 
	if (unlock) {
		f2fs_bug_on(F2FS_P_SB(page), !PageLocked(page));
		unlock_page(page);
	}
	put_page(page);
}
 
static inline struct f2fs_sb_info *F2FS_P_SB(struct page *page)
{
[1]	return F2FS_M_SB(page->mapping);
}
 

in function [1] page->mapping, can be NULL

Debugger / KASAN

Debugger view:

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0xfffffffffffffffb  →  0xfffffffffffffffb
$rbx   : 0x0000000000000003  →  0x0000000000000003
$rcx   : 0xffffffff8175e61d  →  0x0133840f344bfff0  →  0x0133840f344bfff0
$rdx   : 0x0000000000000000  →  0x0000000000000000
$rsp   : 0xffff88806661f8b0  →  0xffff888064bd1100  →  0xffff888064bd1980  →  0xffffffff8312d9c0  →  0xffff88806d021100  →  0xffff88806d021980  →  0xffff88806d024400  →  0xffff88806d025500
$rbp   : 0x00000000fffffffb  →  0x00000000fffffffb
$rsi   : 0x0000000000000004  →  0x0000000000000004
$rdi   : 0x0000000000000003  →  0x0000000000000003
$rip   : 0xffffffff8179b6f3  →  0x468b49ffb1f628e8  →  0x468b49ffb1f628e8
$r8    : 0xfffff94000327ec7  →  0x0000000000000000  →  0x0000000000000000
$r9    : 0xfffff94000327ec7  →  0x0000000000000000  →  0x0000000000000000
$r10   : 0x0000000000000001  →  0x0000000000000001
$r11   : 0xfffff94000327ec6  →  0x0000000000000000  →  0x0000000000000000
$r12   : 0xffff88806661f940  →  0xffff88806661f940  →  [loop detected]
$r13   : 0xffff88806c96c930  →  0x0000400900000007  →  0x0000400900000007
$r14   : 0xfffffffffffffffb  →  0xfffffffffffffffb
$r15   : 0xffff888064bd1100  →  0xffff888064bd1980  →  0xffffffff8312d9c0  →  0xffff88806d021100  →  0xffff88806d021980  →  0xffff88806d024400  →  0xffff88806d025500  →  0xffff88806d026600
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0010 $ss: 0x0018 $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffff88806661f8b0│+0x0000: 0xffff888064bd1100  →  0xffff888064bd1980  →  0xffffffff8312d9c0  →  0xffff88806d021100  →  0xffff88806d021980  →  0xffff88806d024400  →  0xffff88806d025500     ← $rsp
0xffff88806661f8b8│+0x0008: 0x0000000000501206  →  0x0000000000501206
0xffff88806661f8c0│+0x0010: 0x0000000000000000  →  0x0000000000000000
0xffff88806661f8c8│+0x0018: 0x0000000000801ff6  →  0x0000000000801ff6
0xffff88806661f8d0│+0x0020: 0x0000000000000246  →  0x0000000000000246
0xffff88806661f8d8│+0x0028: 0xffff88806661f980  →  0xffff88806661f980  →  [loop detected]
0xffff88806661f8e0│+0x0030: 0xffff88806661f9c0  →  0xffff88806661f9c0  →  [loop detected]
0xffff88806661f8e8│+0x0038: 0x0000000012010000  →  0x0000000012010000
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0xffffffff8179b6e9 <f2fs_recover_fsync_data+1561> div    BYTE PTR [rdi+riz*2+0x49]
   0xffffffff8179b6ed <f2fs_recover_fsync_data+1565> lea    ebx, [rsi+0x8] [1]
   0xffffffff8179b6f0 <f2fs_recover_fsync_data+1568> mov    rdi, rbx
 → 0xffffffff8179b6f3 <f2fs_recover_fsync_data+1571> call   0xffffffff812bad20 <__asan_load8>
   ↳  0xffffffff812bad20 <__asan_load8_noabort+0> movabs rax, 0xffff7fffffffffff
      0xffffffff812bad2a <__asan_load8_noabort+10> mov    rcx, QWORD PTR [rsp]
      0xffffffff812bad2e <__asan_load8_noabort+14> cmp    rdi, rax
      0xffffffff812bad31 <__asan_load8_noabort+17> jbe    0xffffffff812bad64 <__asan_load8+68>
      0xffffffff812bad33 <__asan_load8_noabort+19> lea    rax, [rdi+0x7]
      0xffffffff812bad37 <__asan_load8_noabort+23> mov    rdx, rax
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments ────
__asan_load8 (
   long unsigned int var_0 = 0x0000000000000003 → 0x0000000000000003
)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:./include/linux[...].h+193 ────
    188	 })
    189
    190	 static __always_inline
    191	 void __read_once_size(const volatile void *p, void *res, int size)
    192	 {
 →  193	 	__READ_ONCE_SIZE;
    194	 }

KASAN log (the trailing NULL-pointer Oops panic that repeats the same frames is truncated):

[  220.714471] F2FS-fs (loop0): Fix alignment : done, start(4096) end(436224000) block(8396800)
[  220.717356] F2FS-fs (loop0): Wrong MAIN_AREA boundary, start(4096) end(16384) block(14848)
[  220.719675] F2FS-fs (loop0): Cant find valid F2FS filesystem in 2th superblock
[  220.754065] F2FS-fs (loop0): invalid cp_pack_total_block_count:33023
[  232.122480] hrtimer: interrupt took 8468280 ns
[  232.671931] attempt to access beyond end of device
[  232.676755] loop0: rw=8192, want=41979960, limit=131072
[  232.762826] ==================================================================
[  232.762826] BUG: KASAN: null-ptr-deref in f2fs_recover_fsync_data+0x628/0xc10
[  232.762826] Read of size 8 at addr 0000000000000003 by task mount/1855
[  232.762826]
[  232.762826] CPU: 1 PID: 1855 Comm: mount Not tainted 5.0.21 #2
[  232.762826] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[  232.762826] Call Trace:
[  232.762826]  dump_stack+0x5b/0x8b
[  232.762826]  ? f2fs_recover_fsync_data+0x628/0xc10
[  232.762826]  kasan_report+0x176/0x19b
[  232.762826]  ? f2fs_recover_fsync_data+0x628/0xc10
[  232.762826]  ? f2fs_recover_fsync_data+0x628/0xc10
[  232.762826]  f2fs_recover_fsync_data+0x628/0xc10
[  232.762826]  ? f2fs_space_for_roll_forward+0x50/0x50
[  232.762826]  ? _raw_write_lock+0x7f/0xe0
[  232.762826]  ? _raw_spin_lock_bh+0xf0/0xf0
[  232.762826]  ? rb_insert_color+0x27b/0x3d0
[  232.762826]  ? f2fs_remove_orphan_inode+0x10/0x10
[  232.762826]  ? f2fs_fill_super+0x278e/0x2d50
[  232.762826]  f2fs_fill_super+0x2c3f/0x2d50
[  232.762826]  ? f2fs_commit_super+0x2f0/0x2f0
[  232.762826]  ? sget_userns+0x614/0x640
[  232.762826]  ? set_blocksize+0x83/0x130
[  232.762826]  ? f2fs_commit_super+0x2f0/0x2f0
[  232.762826]  mount_bdev+0x1bb/0x200
[  232.762826]  mount_fs+0xac/0x210
[  232.762826]  ? emergency_thaw_all+0xa0/0xa0
[  232.762826]  ? memcpy+0x34/0x50
[  232.762826]  ? __init_waitqueue_head+0x29/0x30
[  232.762826]  vfs_kern_mount+0x5f/0x190
[  232.762826]  do_mount+0x30a/0x1500
[  232.762826]  ? copy_mount_string+0x20/0x20
[  232.762826]  ? __switch_to_asm+0x41/0x70
[  232.762826]  ? __switch_to_asm+0x35/0x70
[  232.762826]  ? __switch_to_asm+0x41/0x70
[  232.762826]  ? finish_task_switch+0xdd/0x320
[  232.762826]  ? __switch_to_asm+0x41/0x70
[  232.762826]  ? __switch_to_asm+0x35/0x70
[  232.762826]  ? kasan_unpoison_shadow+0x31/0x40
[  232.762826]  ? __kasan_kmalloc+0xd5/0xf0
[  232.762826]  ? strndup_user+0x3a/0x60
[  232.762826]  ? __kmalloc_track_caller+0xc7/0x1c0
[  232.762826]  ? _copy_from_user+0x61/0x90
[  232.762826]  ? memdup_user+0x39/0x60
[  232.762826]  ksys_mount+0x79/0xc0
[  232.762826]  __x64_sys_mount+0x5d/0x70
[  232.762826]  do_syscall_64+0x5e/0x150
[  232.762826]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  232.762826] RIP: 0033:0x7f00728ec48a
[  232.762826] Code: 48 8b 0d 11 fa 2a 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d de f9 2a 00 f7 d8 64 89 01 48
[  232.762826] RSP: 002b:00007fffd0ee76c8 EFLAGS: 00000202 ORIG_RAX: 00000000000000a5
[  232.762826] RAX: ffffffffffffffda RBX: 0000560f63f2a080 RCX: 00007f00728ec48a
[  232.762826] RDX: 0000560f63f2c760 RSI: 0000560f63f2bf60 RDI: 0000560f63f30230
[  232.762826] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000020
[  232.762826] R10: 00000000c0ed0000 R11: 0000000000000202 R12: 0000560f63f30230
[  232.762826] R13: 0000560f63f2c760 R14: 0000000000000000 R15: 00000000ffffffff
[  232.762826] ==================================================================
[  232.762826] Disabling lock debugging due to kernel taint
...

Details

CVSS 5.5 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H), CWE-476, published 2019-12-17, 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.

References