⬢ DragonFlyBSD Kernel Audit
DF-5724 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5724",
  "status": "reproduced",
  "verdict": "set $tabstops=0 followed by any DDB output (the next db>  prompt suffices, via db_readlines db_force_whitespace sync at db_input.c:306) executes rounddown(x,0) in db_force_whitespace (db_output.c:80, NEXT_TAB at :65, rounddown sys/sys/param.h:400) -> fatal trap 18 cascade (31 traps, RIP db_force_whitespace+0x26 = 0xffffffff802cba26, ~0x370 kernel stack consumed per trap) ending in an unrecoverable brick; set $tabstops=-8 makes the same loop spin forever with all CPUs stopped (silent hard hang, zero traps). Both reproduced live on the stock kernel via the socket-serial DDB rig; fix.diff (validating db_varfcn_t setters + defensive NEXT_TAB ternary) validated on a rebuilt kernel: both variants rejected with tabstops must be >= 1, previously-fatal commands work, session alive, zero traps.",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "exploit_chain": "jailed root (DF-2246 reachability: sysctl debug.enter_debugger=ddb) -> set $tabstops=0 -> integer divide fault in DDB -> trap handler re-divides while printing -> 31x fatal trap 18 cascade eats the kernel stack -> whole host bricked (hard reset only). Variant B: set $tabstops=-8 -> non-advancing whitespace loop -> silent all-CPU hang. DoS only; no privilege or memory primitive.",
  "evidence": "serial.variantA.log (31x Fatal trap 18, RIP 0xffffffff802cba26 = db_force_whitespace+0x26 symbolized in env.txt); serial.variantB.log (transcript ends at db>  after set $tabstops=-8, zero traps, ssh dead); serial.fixedkernel.log (both variants rejected, print/d 5 works, zero traps); fix.diff; build.log",
  "kernel_refs": [
    "sys/ddb/db_output.c:65",
    "sys/ddb/db_output.c:74",
    "sys/ddb/db_output.c:80",
    "sys/ddb/db_output.c:82",
    "sys/ddb/db_variables.c:51",
    "sys/ddb/db_variables.c:52",
    "sys/ddb/db_variables.c:120",
    "sys/ddb/db_variables.c:126",
    "sys/ddb/db_input.c:306",
    "sys/sys/param.h:400",
    "sys/ddb/db_command.c:481"
  ],
  "poc_changes": "Trigger reworked vs intuition: no explicit printing command is needed \u2014 the pending trailing space of the next db>  prompt fires db_force_whitespace via db_readlines sync (db_input.c:306) before any echo; variant B likewise hangs before echoing anything. Driver paces <=8 bytes/150ms (guest UART RX FIFO 16) and uses one persistent socket with continuous drain.",
  "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",
  "runtime_sec": 1500,
  "guest_dirty": 0,
  "build_cmd": "stock: none (serial ddb session). fix: scp fix.diff dfbsd:/tmp; cd /usr/src && patch -p1 -N < /tmp/fix.diff && make -j6 nativekernel KERNCONF=X86_64_GENERIC && make installkernel (BUILD_RC=0, kernel #1 Sat Oct 10 17:53:17 UTC 2026)",
  "run_cmd": "./run.sh A   (then guest reset)   ./run.sh B   (then reset; fixed-kernel rerun identical)",
  "code_hash": "4e71cb5ce013d9095ddfb7ff8a65cbf0c0747f6a74da9b35d5ad2b4c57ce432a",
  "notes": "Same session controls: x/x db_active prints normally before each set. Guest reset with-src after validation. Huge tabstops values (0x7fffffffffffffff) wrap (i)+width negative -> same non-advancing loop as variant B.",
  "recommended_fix": "Validating db_varfcn_t setters for $tabstops/$maxwidth (reject <1 via db_error, which longjmps before the store) + defensive db_tab_stop_width>0 ternary in NEXT_TAB.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "Baseline stock kernel: variant A = 31-trap fatal cascade + brick; variant B = silent all-CPU hang. Patched kernel (fix.diff, rebuilt + installed + rebooted): both variants print tabstops must be >= 1, x/x db_active and print/d 5 (the exact B trigger) execute normally, DDB session continues, c resumes \u2014 zero fatal traps. Bad behavior gone.",
  "fix_evidence": "serial.fixedkernel.log (rejected + working output + alive session, 0 Fatal trap occurrences); build.log (BUILD_RC=0, install completed); fix.diff"
}