Overview
On mounting a crafted btrfs image, the kernel takes a NULL-pointer dereference in btrfs_verify_dev_extents (the loop list entry inside find_device).
Target
Tested on Linux Kernel 5.0.21 BTRFS filesystem (source).
(It can need the CONFIG_BTRFS_FS=m option.)
CVE-2019-18885 affects fs/btrfs/volumes.c in the Linux kernel before 5.1 (fixed as CID-09ba3bc9dd15).
Reproduce
A crafted image is attached in the upstream writeup.
mkdir ./mnt
mount -t btrfs ./poc_2019_18885.img ./mntRoot cause
fs/btrfs/volumes.c:430
static struct btrfs_device *find_device(struct btrfs_fs_devices *fs_devices,
u64 devid, const u8 *uuid)
{
struct btrfs_device *dev;
[1] list_for_each_entry(dev, &fs_devices->devices, dev_list) {
if (dev->devid == devid &&
(!uuid || !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE))) {
return dev;
}
}
return NULL;
}In the list_for_each_entry loop ([1]), the &fs_devices->devices list entry can be NULL.
Debugger / KASAN
Debugger view. The instruction cmp BYTE PTR [rdx+rbx*1], 0x0 tries to read the address 0xdffffc0000000000 + 0x13 (a KASAN shadow access on a NULL-derived pointer):
─────────────────────────────────────────────────────────── registers ────
$rax : 0x0000000000000000 → 0x0000000000000000
$rbx : 0xdffffc0000000000 → 0xdffffc0000000000
$rcx : 0x0000000000000098 → 0x0000000000000098
$rdx : 0x0000000000000013 → 0x0000000000000013
$rip : 0xffffffff81def0e8 → 0x0890850f001a3c80 → 0x0890850f001a3c80
...
───────────────────────────────────────────────────────── code:x86:64 ────
→ 0xffffffff81def0e8 <btrfs_verify_dev_extents+1912> cmp BYTE PTR [rdx+rbx*1], 0x0
─────────────────────────────────────── source:fs/btrfs/volumes.c+430 ────
→ 430 list_for_each_entry(dev, &fs_devices->devices, dev_list) {
─────────────────────────────────────────────────────────────── trace ────
[#0] 0xffffffff81def0e8 → find_device(uuid=<optimized out>, devid=<optimized out>, fs_devices=<optimized out>)
[#1] 0xffffffff81def0e8 → verify_one_dev_extent(...)
[#2] 0xffffffff81def0e8 → btrfs_verify_dev_extents(fs_info=<optimized out>)
[#3] 0xffffffff81d243f0 → open_ctree(...)
[#4] 0xffffffff81c7c5d4 → btrfs_fill_super(...)
[#5] 0xffffffff81c7c5d4 → btrfs_mount_root(...)
[#6] 0xffffffff816979d9 → mount_fs(...)
...
KASAN / GPF log (trimmed to the relevant frames):
[ 196.879172] kasan: CONFIG_KASAN_INLINE enabled
[ 196.881094] kasan: GPF could be caused by NULL-ptr deref or user memory access
[ 196.883004] general protection fault: 0000 [#1] SMP KASAN NOPTI
[ 196.883474] CPU: 0 PID: 1989 Comm: mount Not tainted 5.0.21 #1
[ 196.883474] RIP: 0010:btrfs_verify_dev_extents+0x778/0x1140
[ 196.883474] RAX: 0000000000000000 RBX: dffffc0000000000 RCX: 0000000000000098
[ 196.883474] RDX: 0000000000000013 RSI: 0000000000000001 RDI: ffff888069afa348
[ 196.883474] Call Trace:
[ 196.883474] open_ctree+0x4cd0/0x7ada
...
[ 196.883474] btrfs_mount_root+0xe24/0x14c0
...
[ 196.883474] mount_fs+0xb9/0x370
[ 196.883474] vfs_kern_mount.part.28+0xb9/0x400
[ 196.883474] btrfs_mount+0x3c5/0x1fd9
...
[ 196.883474] do_mount+0xef4/0x2d40
[ 196.883474] ksys_mount+0x7b/0xd0
[ 196.883474] __x64_sys_mount+0xb5/0x150
[ 196.883474] do_syscall_64+0x12b/0x440
[ 196.883474] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 196.934565] ---[ end trace b2518a0a4d2b3ae0 ]---
Details
CVSS 5.5 (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H), CWE-476, published 2019-11-14, 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.