⬢ DragonFlyBSD Kernel Audit
DF-3112 / verdict.json
← back to finding ↓ download raw
{
 "finding_id": "DF-3112",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "none",
 "confidence": "certain",
 "verdict": "Reproduced on the audit guest (DFly 6.5-DEVELOPMENT, X86_64_GENERIC): an unprivileged uid-1001 process executed HAMMERIOC_GETHISTORY/GET_VERSION/GET_INFO/SYNCTID/SCAN_PSEUDOFS (rc=0) on an O_RDONLY fd on a HAMMER1 mount, while gated contrast commands HAMMERIOC_PRUNE/ADD_SNAPSHOT returned EPERM from the same dispatcher (hammer_ioctl.c:72 gate result overwritten by 9 case labels). No direct memory-safety impact; ceiling is unprivileged fs-topology/state disclosure (incl. unclamped disk-length copyout in scan_pseudofs, hammer_pfs.c:363), TID-history enumeration, and global flusher forcing via SYNCTID. Patched kernel (all 9 handlers wrapped in the standard `if (error == 0)` guard) returns EPERM for all five as unprivileged and still succeeds as root - fix validated end-to-end.",
 "exploit_chain": "unprivileged user opens any file on a HAMMER1 mount -> ioctl(2) with the ungated commands -> dispatcher runs handler despite failed caps_priv_check (info disclosure / policy bypass); no escalation chain exists for this class.",
 "evidence": [
  "findings/poc/DF-3112/run.log: lines [A]-[E] *** PRIV GATE BYPASSED *** as uid=1001 with [F]/[G] EPERM contrast",
  "findings/poc/DF-3112/run.root.log: same binary as root reaches handler validation (ADD_SNAPSHOT EINVAL at count check), proving the EPERM is the caps gate",
  "findings/poc/DF-3112/run.patched.log: [A]-[E] -> EPERM on the fix-built kernel",
  "findings/poc/DF-3112/fix.diff: 9 `if (error == 0) guards",
  "sys/vfs/hammer/hammer_ioctl.c:72,86,117,121,177,181,213,233,237,263"
 ],
 "kernel_refs": [
  "sys/vfs/hammer/hammer_ioctl.c:72",
  "sys/vfs/hammer/hammer_ioctl.c:86",
  "sys/vfs/hammer/hammer_ioctl.c:117",
  "sys/vfs/hammer/hammer_ioctl.c:121",
  "sys/vfs/hammer/hammer_ioctl.c:177",
  "sys/vfs/hammer/hammer_ioctl.c:181",
  "sys/vfs/hammer/hammer_ioctl.c:213",
  "sys/vfs/hammer/hammer_ioctl.c:233",
  "sys/vfs/hammer/hammer_ioctl.c:237",
  "sys/vfs/hammer/hammer_ioctl.c:263",
  "sys/vfs/hammer/hammer_pfs.c:363"
 ],
 "poc_changes": "Seed sketch had none; wrote from scratch. In-program privilege drop had to be conditional (setuid(65534) fails when the PoC is already run as unprivileged uid 1001); added keep argv mode so the same binary demonstrates the root-path contrast and the DF-3114 fix validation on the patched kernel. Included kernel headers via -I/usr/src/sys using the sbin/hammer pattern.",
 "attempts": 4,
 "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "runtime_sec": 1380,
 "guest_dirty": 1,
 "build_cmd": "cc -I/usr/src/sys -o /tmp/poc /tmp/hammer_gate_poc.c",
 "run_cmd": "/tmp/poc /mnt/h1/histfile  (as unprivileged user; root contrast: /tmp/poc /mnt/h1/histfile keep)",
 "code_hash": "464fd8750494ffbfc0d5c269cc6d830527553311e503554d07ef7a7ae56f459e",
 "notes": "Guest /tmp is a 975M tmpfs - kernel builds need TMPDIR on / (first make nativekernel died ENOSPC in /tmp). Hammer1 test image: newfs_hammer -f on vn0 (needs -f below 10GB), mounted at /mnt/h1. Three-run stability confirmed (5 bypass markers each run). Same defect class as DF-0815 (BULKFREE gate bypass, hammer2) on the HAMMER1 dispatcher.",
 "recommended_fix": "Wrap all nine ungated case labels in hammer_ioctl() with the same `if (error == 0) guard used by the rest of the dispatcher.",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Sun Sep 6 13:09:37 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "Patched kernel (fix.diff applied to /usr/src, make nativekernel KERNCONF=X86_64_GENERIC, reboot) returns EPERM for all five ungated-class commands as uid 1001 while root still succeeds - the exact bypass behavior is gone.",
 "fix_evidence": [
  "findings/poc/DF-3112/run.patched.log",
  "findings/poc/DF-3112/run.patched.root.log",
  "findings/poc/DF-3112/fix_combined_for_validation.diff"
 ]
}