DragonFlyBSD Kernel Audit
DF-0792 / panic.txt
← back to finding ↓ download raw
========================================================================
DF-0792 panic signature (unpatched #0 kernel, before fix.diff applied)
========================================================================
Trigger:  cat /mnt/htest/testfile  where the testfile's B-Tree leaf
          entries were rewritten offline to reference vol_no=7 (which is
          not present in this single-volume HAMMER filesystem).

Path:
  cat -> VOP_READ -> hammer_vop_read -> hammer_io_direct_read
    vol_no = HAMMER_VOL_DECODE(zone2_offset) = 7
    volume = hammer_get_volume(hmp, 7, &error);   // NULL, error=ENOENT
    if (error == 0 && ...) error = EIO;           // skipped, error!=0
    if (error == 0) { ... }                       // skipped, error!=0
    hammer_rel_volume(volume, 0);                 // volume==NULL, BUG
      -> hammer_rel_interlock(&volume->io.lock, locked);   // NULL deref

Captured from dfbsd-qemu/boot.log immediately after the panic, before
the snapshot revert (boot.log is rewritten by vm.sh reset):

HAMMER(htest) mounted clean, no recovery needed
Fatal user address access from kernel mode from cat at ffffffff80951940


Fatal trap 12: page fault while in kernel mode
cpuid = 2; lapic id = 2
fault virtual address	= 0x0
fault code		= supervisor read data, page not present
instruction pointer	= 0x8:0xffffffff80951940
stack pointer	        = 0x10:0xfffff80118f34308
frame pointer	        = 0x10:0xfffff80118f34328
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		= 1129 (cat)
current thread          = pri 6 
kernel: type 12 trap, code=0

CPU2 stopping CPUs: 0x0000003b
 stopped
Stopped at      hammer_rel_interlock+0x20:      movl    (%r12),%ebx
db> 

========================================================================
This is the bug, exactly as claimed by DF-0792: an unconditional
hammer_rel_volume(volume, 0) call after hammer_get_volume() may have
returned NULL. The "Stopped at hammer_rel_interlock+0x20" matches the
first instruction that touches the NULL volume pointer (the lock word
at offset 0 of struct hammer_volume's io member).
========================================================================