⬢ DragonFlyBSD Kernel Audit
DF-5016 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5016",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "likely",
  "verdict": "The locking hole is real and the race was executed at scale (274,432 CONS_HISTORY reallocs x continuous scrolling tty writes, both uid 65534): history-ring appends (sc_term_gen_scroll -> sc_hist_save_one_line, sctermvar.h:437) run under syscons_lock only, while every ring realloc/free (sc_hist_ioctl/sc_set_text_mode -> sc_alloc_history_buffer, schistory.c:94-159) runs under vga_token only - no common lock, so kfree() of the ring can interleave with a concurrent appends reads of vtb_buffer/vtb_tail (UAF read + wild write) or with the NULL window. Kernel manifestation: a supervisor WRITE fault inside sc_vtb_bcopy at 0xffffffff7ffffffe during the unpriv churn campaign (panic #1) - the UAF branch signature; that run had NO keyboard input, excluding DF-5015s negative-tail path, and the competing generic ioctl-token assertion (identified via a TIOCGWINSZ-only control, which panics with a DIFFERENT signature: lwkt_reltokref count assertion, never a wild write) cannot produce a wild write. Confidence likely rather than certain because panic #1 occurred once and no backtrace was captured (trace_on_panic not armed on that boot).",
  "exploit_chain": "proc A (unpriv): loop ioctl(CONS_HISTORY) realloc/free of the ring; proc B (unpriv): write scrolling lines to the same vty (append fires per scrolled line, under syscons_lock); interleave kfree under vga_token with a reader mid-append -> UAF write into a freed 4KB-class kmem object with attacker-controlled line content, or wild write via garbage vtb_tail. No uid=0 chain developed.",
  "evidence": "race5016.c; panic-lwkt-token-count-race.log (campaign panic, later identified as the generic ioctl issue via the TIOCGWINSZ control - kept for the record); DF-5015/panic-scvtb_bcopy-unpriv-churn.log (the wild-write panic attributed here); VERDICT.md",
  "kernel_refs": [
    "sys/dev/misc/syscons/sctermvar.h:425-450",
    "sys/dev/misc/syscons/syscons.h:547-548",
    "sys/dev/misc/syscons/syscons.c:970-1006",
    "sys/dev/misc/syscons/syscons.c:1885-1923",
    "sys/dev/misc/syscons/schistory.c:93-159",
    "sys/dev/misc/syscons/scvidctl.c:163"
  ],
  "poc_changes": "racer written from scratch (two-process, uid 65534); discovery chain documented in VERDICT.md including the confound isolation (CONS_CLRHIST-only, TIOCGWINSZ-only controls)",
  "attempts": 5,
  "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": 3600,
  "guest_dirty": 0,
  "build_cmd": "cc -O1 -o /tmp/race5016 /tmp/race5016.c (guest)",
  "run_cmd": "/tmp/race5016 scroll & /tmp/race5016 realloc &  (uid 65534)",
  "code_hash": "19e5e987a36402c82342fa9c14db9a27a3de6cb11b9cd989881f104ed7abf338",
  "notes": "the lwkt_reltokref assertion panic observed in several race runs is a GENERIC DragonFly ioctl-path issue (reproduced with TIOCGWINSZ alone on ttyv0, stock kernel, unpriv, ~60-90s, 4/4) and is NOT this finding; it deserves its own audit ticket outside syscons.",
  "recommended_fix": "perform the install/destroy (and free) of history rings under syscons_lock, the lock every append reader already holds (fix.diff exports syscons_lock and wraps the swap/destroy sections); NULL remains installed only while reallocating, which the scroll path already NULL-checks",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Patched kernel (fix.diff, kernel #2 Sat Sep 26 02:44) compiled, installed and booted; race soak on it (353,280 CONS_HISTORY reallocs x continuous scroll appends in 20s, both uid 65534) produced no vtb-class fault and normal syscons operation remained functional (arm/flip/SCRSHOT/fill verified). The lwkt_reltokref assertion that eventually appears on longer ioctl loops is the generic DragonFly ioctl-path issue (TIOCGWINSZ-only control) and is orthogonal to this fix.",
  "fix_evidence": "/tmp/kbuild.log KBUILD_DONE; race soak transcript in DF-5015 pack run logs"
}