โฌข DragonFlyBSD Kernel Audit
DF-3141 / panic.txt
โ† back to finding โ†“ download raw
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