{
  "finding_id": "DF-5725",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "db_set_breakpoints() (sys/ddb/db_break.c:161-180) has no per-breakpoint fault isolation and defers reading the original instruction byte to resume time: a single breakpoint at an unmapped address (operator typo) aborts the insert pass mid-list via Fatal trap 12 -> nested DDB entry, leaving breakpoints earlier in the list patched with INT3 while db_breakpoints_inserted stays FALSE (proven live: db_invltlb_cmd byte 0x0f -> 0xcc at the nested prompt, twice, run1/run2 logs), after which no code path ever restores the byte (db_clear_breakpoints restores only when the flag says inserted) and any later insert pass re-reads the patched INT3 as the original (bkpt_inst poisoned at db_break.c:171) making the corruption permanent on clear. The nested CRIT-context trap state then panics deterministically (panic: trap: critical section count mismatch!, crash dump, reboot) in both runs. Root-gated DDB console surface -> Low severity, but the demonstrated primitive is real kernel-text corruption at an address the operator did not type plus an unrecoverable panic.",
  "exploit_chain": "Root at DDB console: (1) b <unmapped-addr> then b <valid-text-addr> (LIFO: valid bp inserted first), (2) c -> insert pass writes INT3 to the valid address, faults on the bad one, flag desync, (3) orphaned INT3 persists (x/bx shows 0xcc) and poisons bkpt_inst on any re-insert; deleting all breakpoints leaves the 0xcc permanently in kernel text; (4) the next nested trap panics with crit-section mismatch -> dump+reboot. No unprivileged path (debug.enter_debugger is root-gated, verified EPERM as uid 1002 by DF-5721 probes); escalation not applicable - corruption target is chosen by the operators own valid breakpoint, so an operator can corrupt any text byte deliberately, which DDB already permits by design via w; the defect is that it happens unintentionally and irreversibly from a typo plus panics the box.",
  "evidence": "run1-orphan-panic.serial.log + run2-orphan-panic.serial.log: db_invltlb_cmd: f (0x0f pristine) -> b 0xffffffff85000000 + b db_invltlb_cmd + c -> Fatal trap 12 ... 0xffffffff85000000 ... pri 6 (CRIT) -> db_invltlb_cmd: cc (orphaned INT3) -> panic: trap: critical section count mismatch! -1892583040/-1 -> dump -> reboot. control-run.serial.log: same GOOD bp without the bad one restores 0x0f cleanly and resumes. fix_run.log (patched kernel): bad bp rejected at set time (No breakpoints set), c resumes with no trap, byte stays 0x0f, machine up.",
  "kernel_refs": [
    "sys/ddb/db_break.c:88",
    "sys/ddb/db_break.c:106",
    "sys/ddb/db_break.c:161",
    "sys/ddb/db_break.c:171",
    "sys/ddb/db_break.c:174",
    "sys/ddb/db_break.c:178",
    "sys/ddb/db_break.c:187",
    "sys/ddb/db_run.c:207",
    "sys/ddb/db_trap.c:74",
    "sys/platform/pc64/x86_64/db_interface.c:241"
  ],
  "poc_changes": "No seed PoC. Built the socket-serial DDB rig (serial_vm.sh SMP / serial_vm1.sh UP + drive_ddb.py, adapted from the proven DF-5721 rig) plus enter_ddb.sh; discovered x/b alone is modifier-only (must use x/bx) and that the SMP instance wedges after DDB resume (same as DF-5721), so all clean runs are UP.",
  "attempts": 3,
  "runtime_sec": 2400,
  "build_cmd": "(rig) ./serial_vm1.sh up; (fix kernel) cd /usr/src && patch -p1 -N < /tmp/combined.diff && make -j6 nativekernel KERNCONF=X86_64_GENERIC && make installkernel",
  "run_cmd": "./enter_ddb.sh; DF5725_SOCK=/tmp/opencode/df-5725-ser-up.sock ./drive_ddb.py x/bx db_invltlb_cmd 3 b 0xffffffff85000000 2 b db_invltlb_cmd 2 show breaks 3 c 8 x/bx db_invltlb_cmd 6",
  "notes": "Panic counter -1892583040 is the poisoned bkpt-inst/crit context artifact; identical in both runs. Crash dumps from baseline panics wiped by vm.sh reset with-src before the fix build. Fix validated on a single combined-fix kernel (DF-5725+DF-5726+DF-5727 diffs, all three against sys/ddb/). Residual documented in VERDICT.md: page unmapped between set and resume (kldunload) can still abort the insert pass; the poisoning leg is gone by construction.",
  "recommended_fix": "Save and validate the original instruction byte in db_set_breakpoint() at set time (before linking) and make db_set_breakpoints() write BKPT_SET(saved) without re-reading patched memory (fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "Baseline reproduced twice on stock #0 kernel (orphan 0xcc + crit-mismatch panic + dump + reboot). Patched kernel (#1, combined db_break/db_watch fixes): b 0xffffffff85000000 faults at SET time at the prompt (pre-existing recoverable bad-read behavior) and adds nothing (No breakpoints set); good bp insert/clear cycle restores 0x0f at entry; c resumes with no fatal trap; machine stays up. Bad behavior gone.",
  "fix_evidence": "findings/poc/DF-5725/fix.diff; fix_build.log; fix_run.log (patched session: No breakpoints set / db_invltlb_cmd: f / clean resume); baseline: run1-orphan-panic.serial.log, run2-orphan-panic.serial.log; control-run.serial.log",
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 x86_64 (baseline); patched fix kernel #1: Sat Oct 10 18:42:38 UTC 2026",
  "guest_dirty": 0,
  "code_hash": "4af3526ae154b6eda9c58a47a4765ec20f5f92789a42d1c221faabf9f498c9ea",
  "fix_kernel_uname": "DragonFly 6.5-DEVELOPMENT #1: Sat Oct 10 18:42:38 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC"
}