DF-3141 / panic.txt
DF-3141 panic variant โ captured from the serial console (boot.log of the
QEMU instance running diag kernel #2; the DFCHK vget print is
bounds-checked and deliberately SKIPS unsafe geometries, so this fault is
the STOCK bcopy in hpfs_vget, not the instrumentation).
Trigger: stat /tmp/hpfsmp/FILE as uid 1001 on df3142.img (that image's
dirent then pointed de_fnode at 0x3FFF = last sector; identical geometry
to df3141p.img's FILE fnode at 0x4F). fnode LSN 0x3FFF ->
dbtodoff = 0x7FFE00 = page+0xE00; the 512-byte buffer ends exactly at the
page boundary; bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode)=520)
reads 8 bytes into the next, unmapped page of the buffer's MAXBSIZE KVA
reservation.
----------------------------------------------------------------------
login: DFCHK vget ino=20 b_data=0xfffff8005d3e6000 tail8=0000000000000000 sizeof(fnode)=520
Fatal trap 12: page fault while in kernel mode
cpuid = 0; lapic id = 0
fault virtual address = 0xfffff800563b7000
fault code = supervisor read data, page not present
instruction pointer = 0x8:0xffffffff80bca995
stack pointer = 0x10:0xfffff80117a4f300
frame pointer = 0x10:0xfffff80117a4f358
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 0, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 861
current thread = pri 6
kernel: type 12 trap, code=0
CPU0 stopping CPUs: 0x0000003e
stopped
Stopped at memmove+0x95: movq (%rsi),%rdx
db>
----------------------------------------------------------------------
(memmove+0x95 is the bcopy source read; fault VA is page-aligned, i.e.
exactly page+0x1000 = the first byte past the 512-byte buffer's mapped
page. After the fix (fn_int 0x13c -> 0x138, sizeof(struct fnode)=512)
the identical trigger prints "stat returned, size=512 (no panic)" โ see
fix_run.log.)
Sibling capture (same bug, write side, earlier diag session) โ hpfs_update
writes 8 bytes past its 512-byte buffer:
DFCHK upd pre ino=48 b_data=... tail8=5959595959595959 <- B's "YYYYYYYY"
DFCHK upd post ino=48 tail8=5858585858585858 hfn_tail=5858585858585858
<- attacker-crafted
"XXXXXXXX" written
past the buffer