DF-0857 / panic.txt
=== DF-0857 live trigger panic signature (from dfbsd-qemu/boot.log) ===
Guest: DragonFly 6.5-DEVELOPMENT #0 master DEV (X86_64_GENERIC, INVARIANTS ON)
Trigger: mount_hpfs crafted df857.img (root) ; cat /mnt/FILE (any user)
File fnode fn_ab.ab_busycnt forged to 255 -> hpfs_hpbmap walks alleaf[0..254]
past fn_abd[0x60] into rest of struct fnode / struct hpfsnode / slab heap.
bgetvp: overlapr 0000000000002000/2048 0000000000002200 bp 0xfffff8004f5be060 bx 0xfffff8004f5c0010
panic: bgetvp - overlapping buffer
cpuid = 0
Trace beginning at frame 0xfffff80118a9f608
bgetvp() at bgetvp+0x129 0xffffffff806f44c9
bgetvp() at bgetvp+0x129 0xffffffff806f44c9
getblk() at getblk+0x18b 0xffffffff806d703b
breadnx() at breadnx+0x284 0xffffffff806d7714
hpfs_read() at hpfs_read+0xb3 0xffffffff82601683
vop_read() at vop_read+0x9c 0xffffffff8070a4cc
Debugger("panic")
CPU0 stopping CPUs: 0x0000003e
stopped
Stopped at Debugger+0x7c: movb $0,0xbdaf09(%rip)
db>
=== Interpretation ===
This is the INDIRECT panic caused by the DF-0857 OOB read. hpfs_hpbmap()
walked 255 alleaf_t entries past fn_abd[] (the bug); one of the OOB entries
happened to satisfy the (bn >= al_off) && (bn < al_off+al_len) test against
random heap bytes, so hpfs_hpbmap returned *bnp = (bn - alp->al_off + al_lsn)
computed from garbage. hpfs_read() then passed that garbage to bread(), whose
bgetvp() panicked because the bogus disk offset overlapped an existing buffer
in the buffer cache.
This is the info-leak + DoS manifestation: the OOB-read-derived disk offset
is (a) used as a kernel disk-I/O target (DoS / panic) and (b) reflected back
indirectly to userspace when it happens to be a readable sector (info leak
of kernel heap residue via file contents). The deterministic OOB extent
(2964 bytes past fn_abd for leaf variant) is proven separately by harness.c.