DragonFlyBSD Kernel Audit
DF-2636 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2636",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Reproduced on the stock INVARIANTS guest kernel (DragonFly 6.5-DEVELOPMENT #0). A forged hammer2 image with the PFS-root inode's meta.type set to 0x42 (valid values 0,3,8,10,11..255 also work; only 1,2,4,5,6,7,9 are handled) mounts cleanly; the first VFS_ROOT -- the lstat inside ls -la -- panics exactly at hammer2_inode.c:791-793: 'panic: hammer2: unhandled objtype 66', backtrace hammer2_igetv <- hammer2_vfs_root <- nlookup <- kern_stat <- sys_lstat. ip->meta is copied verbatim from media by hammer2_pfsalloc (vfsops.c:456) with no type validation anywhere on the mount path. Controlled panic (DoS) from a crafted image; requires mount privilege. Fixed kernel returns EINVAL instead of panicking (fix validated).",
  "exploit_chain": "",
  "evidence": "panic.txt lines 46-53 (panic + backtrace), run.log (mount lines then trap), forge_2636.py (byte flip at inode block +0x50 per hammer2_disk.h), fix_run.log (fixed kernel: error return, no panic)",
  "kernel_refs": ["sys/vfs/hammer2/hammer2_inode.c:791-793", "sys/vfs/hammer2/hammer2_inode.c:744-795", "sys/vfs/hammer2/hammer2_vfsops.c:453-456"],
  "poc_changes": "Cribbed the DF-2616/DF-2624 image-forger harness (h2common.py volhdr->sroot->PFS walk, CHECK_NONE ancestors, volhdr CRC32C recompute) instead of writing a forger from scratch; targeted the mounted 'testvol' PFS root inode at image offset 0x1400800, field offset +0x50 (meta.type).",
  "attempts": 1,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026\troot@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 90,
  "guest_dirty": 1,
  "build_cmd": "python3 forge_2636.py h2base.img craft2636.img (host); vnconfig -c vn1 craft2636.img (guest)",
  "run_cmd": "mount_hammer2 -o ro /dev/vn1@testvol /mnt/h2636 && ls -la /mnt/h2636",
  "code_hash": "7ec2f858c93265ac0d8521ff93dd606d16e1120b0d004711f47c120b53229eb3",
  "notes": "objtype values 0 (UNKNOWN) and 10 (WHITEOUT) are defined on-media types with no producer in-kernel, i.e. reachable only via crafted/corrupt images -- same trust boundary as the DF-0763/DF-0804/DF-2616 crafted-image family. ssh session died at panic (guest froze in ddb); serial console capture in panic.txt/run.log.",
  "recommended_fix": "Replace the panic with a VBAD vnode + EINVAL error return in hammer2_igetv's default case (see fix.diff).",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Sat Aug 29 12:37:23 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (default case -> kprintf + VBAD + vx_put + *errorp=EINVAL, with 'if (vp == NULL) break;' guard) applied to the guest /usr/src, kernel rebuilt with 'make nativekernel' + installkernel (fix_build.log), rebooted into kernel #1. Re-running the exact PoC: mount succeeds, 'ls -la /mnt/h2636' returns 'Invalid argument' instead of panicking, guest stays up (fix_run.log). Baseline panic confirmed on stock kernel #0 in the same session.",
  "fix_evidence": "fix_build.log (install completed), fix_run.log (MOUNT_RC=0, ls: Invalid argument, no panic, vm up)"
}