DragonFlyBSD Kernel Audit
DF-2716 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2716",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "authz_bypass (sticky-bit / append-only-dir deletion+rename restriction bypass; not uid0/panic/leak class)",
  "confidence": "certain",
  "verdict": "REPRODUCED on stock INVARIANTS kernel #0 (hammer2 root and tmpfs): rmdir(\"stickydir/victim/\") and rename(\"stickydir/victim/\", ...) by uid 1001 succeed where the slashless controls return EACCES, and rmdir(\"sappnd-dir/sub/\") succeeds on hammer2 (EPERM control). Root cause: sys/kern/vfs_nlookup.c:654 tests *nptr=='/' to decide whether the current directory is the leaf's parent, misclassifying a leaf followed by a trailing slash as an intermediate component, so NLC_STICKY/NLC_APPENDONLY feedback (naccess vfs_nlookup.c:1704-1711) is never collected and naccess_lva's sticky/append-only gates (vfs_nlookup.c:1902/1838) never fire. FIX VALIDATED: one-line islastelement(nptr)==0 condition rebuilt in-guest (kernel #1), all PoC phases now denied (a2/a4 EACCES, b2 EPERM), controls and regression suite unchanged.",
  "exploit_chain": "unpriv user -> rmdir(\"/tmp/<other-users-empty-dir>/\") deletes it; rename(\"/tmp/<other-users-dir>/\", \"~/stolen\") relocates another user's directory tree out of the sticky-protected namespace; rmdir(\"<sappnd-dir>/<entry>/\") defeats administrator append-only directories on hammer2. No uid=0 chain — authorization bypass class.",
  "evidence": [
    "findings/poc/DF-2716/run.baseline.log (stock kernel, fresh with-src boot: a2/a4/b2 SUCCESS)",
    "findings/poc/DF-2716/run.hammer2.log (stock kernel pre-reset hammer2 matrix)",
    "findings/poc/DF-2716/run.log (stock kernel tmpfs matrix: a2/a4 SUCCESS)",
    "findings/poc/DF-2716/run.fixed.log (patched kernel #1: a2/a4 EACCES, b2 EPERM + regression suite OK)",
    "findings/poc/DF-2716/fix.diff (islastelement-based condition)"
  ],
  "kernel_refs": [
    "sys/kern/vfs_nlookup.c:653-660",
    "sys/kern/vfs_nlookup.c:678",
    "sys/kern/vfs_nlookup.c:1213-1215",
    "sys/kern/vfs_nlookup.c:1704-1711",
    "sys/kern/vfs_nlookup.c:1838-1842",
    "sys/kern/vfs_nlookup.c:1902-1905",
    "sys/vfs/ufs/ufs_vnops.c:1483",
    "sys/vfs/tmpfs/tmpfs_vnops.c:1132"
  ],
  "poc_changes": "phase-driven rewrite of the seed sketch (single syscall per exec so root can re-create fixtures between phases); env-parametrized base dir so the same binary runs on hammer2 (/df2716h) and tmpfs (/tmp); build on guest with cc; su -m maxx executes each phase.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (baseline) / #1: Mon Aug 31 05:34:49 UTC 2026 (fix-validated)",
  "runtime_sec": 3300,
  "guest_dirty": 0,
  "build_cmd": "cc -O0 -g -o /tmp/df2716_bin/df2716 /root/df2716/df2716.c",
  "run_cmd": "sh /root/df2716/run.sh /df2716h   (root; arg = base dir)",
  "code_hash": "4206e308d9eb957262c17e3482bf0fd98ba7c7822d620275f1c483c56d436b0e",
  "notes": "unlink(file/) is stopped earlier by the ENOTDIR check at vfs_nlookup.c:1127-1131, so the bypass is limited to directory rmdir/rename. a5 (rename-over victim/) bypassed the gate (no EACCES) but failed with ENOENT inside kern_rename/FS dir-over-dir handling on both tmpfs and hammer2; not counted as weaponized. b2 on tmpfs is independently blocked by tmpfs's own APPEND recheck (tmpfs_vnops.c:1132) - hammer2 has no recheck. Reproduced deterministically across two independent boots of the stock kernel.",
  "recommended_fix": "replace '*nptr == 0x2f' dflags-collection test with islastelement(nptr) == 0 in nlookup() (see fix.diff)",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Mon Aug 31 05:34:49 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 denies a2 (EACCES), a4 (EACCES), b2 (EPERM); controls a1/a3/b1 identical to stock; regression suite (own-dir ops incl. trailing slash in sticky dir, non-sticky dir-over-dir rename with/without slash) all pass",
  "fix_evidence": "findings/poc/DF-2716/run.fixed.log"
}