DragonFlyBSD Kernel Audit
DF-0780 / panic.txt
← back to finding ↓ download raw
DF-0780 — kernel panic signature (unpatched baseline, from dfbsd-qemu/boot.log)
==============================================================================

Trigger: malicious FUSE daemon replies to FUSE_READ with 131072 bytes when the
kernel requested 8192 (a 2-block cluster buffer).  fuse_io_execute() does an
unchecked memcpy of fuse_out_data_size() (131056 bytes) into bp->b_data
(an 8192-byte buffer-cache buffer) => heap OOB write that runs off the end of
the mapped buffer-cache KVA region and page-faults inside memcpy.

panic: assertion "obj != NULL" failed in vm_object_hold_shared at /usr/src/sys/vm/vm_object.c:330
cpuid = 2
Trace beginning at frame 0xfffff80117f77638
vm_object_hold_shared() at vm_object_hold_shared+0x3f 0xffffffff809ab9bf
vm_object_hold_shared() at vm_object_hold_shared+0x3f 0xffffffff809ab9bf
vm_fault() at vm_fault+0x408 0xffffffff8099e0b8
trap_pfault() at trap_pfault+0x9a 0xffffffff80bd52ca
trap() at trap+0x17c 0xffffffff80bd5bcc
calltrap() at calltrap+0x9 0xffffffff80b991fa
--- trap 000000000000000c, rip = ffffffff80bcac8a, rsp = fffff80117f77a50, rbp = fffff80117f77ab0 ---
memcpy() at memcpy+0xfa 0xffffffff80bcac8a
Debugger("panic")

CPU2 stopping CPUs: 0x0000003b
 stopped
Stopped at      Debugger+0x7c:  movb    $0,0xbdaf09(%rip)
db>

Reproduced deterministically 3/3 runs from a fresh `vm.sh reset with-src`
(unpatched audit-source kernel #0) + the stock fuse.ko built from the same
source.

Interpretation:
  * trap 0xc == T_PAGEFLT (12).  The faulting RIP is inside memcpy() at
    memcpy+0xfa, i.e. the OOB *write* access in fuse_io_execute's
        memcpy(bp->b_data, fuse_out_data(fip), fuse_out_data_size(fip));
    (sys/vfs/fuse/fuse_vnops.c:2054) ran past the end of bp->b_data's mapped
    KVA into an unmapped page.
  * vm_fault() tried to resolve the write fault, dereferenced a (corrupted /
    out-of-range) vm_object and hit the obj != NULL assertion.
  * The fault originates in the very memcpy that lacks the bound check, on the
    FUSE READ path, exactly as the finding describes.