⬢ DragonFlyBSD Kernel Audit
DF-5677 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5677",
  "status": "reproduced",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "prop_object_release_emergency dispatches (*po->po_type->pot_emergency_free)(parent) with parent==NULL whenever the first loop iteration breaks (ocnt!=1 concurrent-retain race or DONE) \u2014 reproduced deterministically at unit level on the same-source rig: assert(parent) abort at prop_object.c:1048 (exit 134) and raw NULL-deref SIGSEGV under NDEBUG (exit 139). Kernel impact none today: the emergency path requires _prop_stack_push to fail, and kernel _PROP_MALLOC is kmalloc(M_WAITOK) which cannot return NULL (kern_kmalloc.c:706 panics instead) \u2014 dead code in-kernel, live for userland libprop under allocation failure plus the retain race. Fixed and validated on the rig: parent==NULL early-return makes both builds survive.",
  "exploit_chain": "userland libprop under malloc pressure: prop_object_release on a deep container hits _PROP_OBJECT_FREE_FAILED (stack-push malloc fails) -> emergency walk -> concurrent retain on the target restores refcount>1 -> first iteration breaks with parent==NULL -> NULL deref/abort. Kernel chain blocked by M_WAITOK semantics (no FAILED possible).",
  "evidence": "run.log: Assertion failed: (parent), function prop_object_release_emergency, file proporig/prop_object.c, line 1048 exit=134; NDEBUG control Segmentation fault exit=139; fixed rig DF5677: survived (bug not present) exit=0 both builds.",
  "kernel_refs": [
    "sys/libprop/prop_object.c:1005-1052",
    "sys/libprop/prop_object.c:1094-1105",
    "sys/libprop/prop_object_impl.h:260",
    "sys/kern/kern_kmalloc.c:706",
    "sys/libprop/prop_stack.c:49-53"
  ],
  "poc_changes": "Harness written fresh: TU-include of prop_object.c to reach the static function; refcount-2 array as the deterministic stand-in for the raced state; NDEBUG control build to show the raw NULL deref behind the assert.",
  "attempts": 1,
  "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": 200,
  "guest_dirty": 0,
  "build_cmd": "sh build.sh  (guest root /tmp/df5677: same-source rig + TU-include harness)",
  "run_cmd": "sh run.sh  (assert build + NDEBUG control, then fixed-rig re-run)",
  "code_hash": "4de1d75f3711d2315113c6f4d4ee2cc4c52d6942c6d79d136bc3d0d9a633c1f5",
  "notes": "Filed Low because the kernel path is unreachable with M_WAITOK semantics; noted in the same bucket (not separately filed): emergency_free called without the type lock and the refcount restore at prop_object.c:1046/1102 running outside the lock \u2014 same malloc-failure/race edge, and the pot_lock contract hole for this family is already tracked as DF-5674.",
  "recommended_fix": "Return early when parent==NULL (nothing was walked, nothing to emergency-free) instead of asserting and dereferencing.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff (parent==NULL early return) applied to the same-source rig on the guest: baseline aborts/SIGSEGVs, fixed harness survives in both assert and NDEBUG builds (exit 0). Kernel rebuild not performed \u2014 the emergency path cannot execute in-kernel (M_WAITOK push cannot fail), so there is no kernel behavior to validate.",
  "fix_evidence": "run.log (baseline exit=134 assert / 139 NDEBUG; fixed survived (bug not present) exit=0 both); fix.diff"
}