β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4100

recovery BCCB is never marked BCCB_ACTIVE, so the BDR-completion recovery branch is dead code β€” every command timeout escalates to a full hard bus reset after a 2s freeze

Summary

bttimeout's BDR branch sends bt->recovery_bccb without ever setting BCCB_ACTIVE on it. When the adapter completes the BDR mailbox, btdone hits the (flags & BCCB_ACTIVE)==0 guard first, prints 'Attempt to free non-active BCCB' and returns - the entire recovery branch can never execute. The SIM queue frozen at timeout stays frozen with all pending timeouts stopped until the timed-out CCB's own 2s re-arm fires the full hard-reset path. Targeted device recovery is impossible: a single hung command guarantees a bus-wide reset 2s later, disrupting I/O to every target. Mark-active/clear-on-complete fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4100 Β· 12 files
FileTypeDescriptionSize
README.md β€” 1.6 KB ↓ raw
VERDICT.md β€” 2.8 KB ↓ raw
dfbt_rig.c β€” 26.9 KB view raw
dfbt_ctl.c β€” 8.0 KB view raw
Makefile β€” 127 B ↓ download
push_rig.sh β€” 975 B view raw
run1.sh β€” 3.9 KB view raw
run.log β€” 11.6 KB view raw
env.txt β€” 249 B view raw
fix.diff β€” 6.0 KB view raw
manifest.json β€” 718 B view raw
verdict.json β€” 3.1 KB view raw

DF-4100 β€” Recovery BCCB never BCCB_ACTIVE: BDR recovery branch is dead code

Verdict: REPRODUCED (dead branch + guaranteed hard-reset escalation)

Rig class as DF-2429 (see DF-2429/README.md).

Build

./push_rig.sh

Run

sh run1.sh       # DF-4100 is the second section

Expected output (run.log)

  1. Production bttimeout() fired on a queued I/O CCB takes the BDR branch: flags=0x7 (ACTIVE|DEVICE_RESET|RELEASE_SIMQ), 2s re-arm (timer=1), recovery BCCB programmed β€” and rec_flags=0 (BCCB_FREE, never ACTIVE; the only writer of BCCB_ACTIVE is bt.c:1302 in btexecuteccb, which the recovery BCCB never transits).
  2. The firmware completes the BDR mailbox (BMBI_OK) β†’ production btdone hits the guard first β€” console: unknown: btdone - Attempt to free non-active BCCB 0xfffff801167df690 (f690 == the recovery BCCB) β€” and returns. async_bdr=0: the AC_SENT_BDR notification the recovery branch would send never fires; the pending CCB's timer stays stopped (timeouts are never reinstated); the SIM queue stays frozen.
  3. 2s later the re-armed timer fires bttimeout again β†’ BCCB_DEVICE_RESET set β†’ hard-reset branch: the virtual HBA observes the driver write HARD_RESET (0x80) to CONTROL_REG (vhba_hard_resets=1, last_ctl=128), btreset runs to completion, and the timed-out CCB completes CAM_CMD_TIMEOUT (ccb_status=0xb).

Conclusion: targeted device recovery can never work; a single hung command guarantees a full hard bus reset 2 seconds later, disrupting I/O to every target on the bus.

VERDICT.md
↓ download raw

DF-4100 VERDICT β€” recovery BCCB never marked ACTIVE; BDR branch dead

Bottom line

REPRODUCED end-to-end on the production handlers.

  1. Dead branch: bttimeout's BDR branch (bt.c:2214-2230) arms bt->recovery_bccb without ever setting BCCB_ACTIVE on it. Live snapshot at arm time: rec_flags=0 (BCCB_FREE). When the adapter completes the BDR mailbox, production btdone evaluates the guard at bt.c:1388 first and bails: unknown: btdone - Attempt to free non-active BCCB 0xfffff801167df690 (f690 is the recovery BCCB). The recovery branch at bt.c:1406-1447 is unreachable β€” proven by three independent observables: the guard message printed, async_bdr == 0 (AC_SENT_BDR, which only that branch sends, never fired), and the pending CCB's timeouts were never reinstated (bt.c:1439-1441).
  2. Guaranteed escalation: with the recovery branch dead, the 2s re-armed timer from bt.c:2215 fires bttimeout again; BCCB_DEVICE_ RESET is now set, so bt.c:2183-2200 takes the full hard-reset branch. The virtual HBA observed the production driver write HARD_RESET (0x80) to CONTROL_REG (vhba_hard_resets=1, vhba_last_ctl=128), btreset(hard) completed, and the timed-out CCB finished with ccb_status=0xb (CAM_CMD_TIMEOUT). Console: two CCB ... - timed out lines and No longer in timeout (the hard-branch message).

So every command timeout on real bt(4) hardware escalates to a bus-wide hard reset 2 seconds later (freezing the SIM queue for that period), disrupting I/O to every target β€” targeted BDR recovery is impossible.

Root cause (path:line)

  • bt.c:2214-2230 β€” BDR arm; no recovery_bccb->flags = BCCB_ACTIVE.
  • bt.c:1302 β€” the only site that sets BCCB_ACTIVE (btexecuteccb), which the recovery BCCB never transits.
  • bt.c:1388-1393 β€” the guard that therefore always rejects the BDR completion.
  • bt.c:2215 β€” the 2s re-arm that guarantees the hard-reset escalation.

Impact

Reliability/DoS: one hung command β†’ 2s frozen SIM queue β†’ full hard bus reset β†’ all targets' I/O disrupted. On real hardware this also converts every recoverable single-device hang into a bus-wide event.

Fix validation

fix.diff sets recovery_bccb->flags = BCCB_ACTIVE when the BDR is armed (bttimeout) and clears it to BCCB_FREE when the recovery branch finishes. Patched bt.c+btreg.h compile clean with the kernel's own flags under -Werror (FIXED-COMPILES-CLEAN). No runtime A/B kernel build (DoS class, not memory corruption; not mandated).

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

object-compile validation only (DoS class, kernel A/B not mandated): patched bt.c compiles clean under -Werror with kernel headers

fix.diff; 'FIXED-COMPILES-CLEAN' with bt.fixed.o on the guest
↓ fix.diffper-fix-DF-4100

Confirmed kernel references

Detail

Exploit chain

single hung command -> bttimeout BDR branch (bt.c:2214) arms recovery BCCB with flags still BCCB_FREE -> HBA completes BDR mailbox -> btdone guard at bt.c:1388 rejects ('Attempt to free non-active BCCB') -> recovery branch dead: SIM queue stays frozen, no AC_SENT_BDR, no timeout reinstatement -> 2s re-arm fires bttimeout with BCCB_DEVICE_RESET set -> btreset(hard) writes 0x80 to CONTROL_REG -> bus-wide reset, all targets disrupted

Evidence (decisive lines)

run.log DF-4100 section: [timeout] flags=0x7 rec_flags=0; [comprec] + console 'btdone - Attempt to free non-active BCCB 0xfffff801167df690'; async_bdr=0 across all snapshots; final snap ccb_status=0xb timer=0; vhba counters 1/1/128

PoC changes

recovery completion delivered straight to production btdone via the comprec ioctl (the virtual-HBA firmware emulation), mirroring what bt_intr_locked's mailbox walk feeds it (bt.c:1363-1370)

Verified recommended fix

Set recovery_bccb->flags = BCCB_ACTIVE when arming the BDR in bttimeout and clear it to BCCB_FREE when the recovery branch finishes (fix.diff, object-compile validated)

Verdict

REPRODUCED end-to-end: bttimeout's BDR branch arms the recovery BCCB without BCCB_ACTIVE (rec_flags=0 observed at arm time; only bt.c:1302 sets ACTIVE and the recovery BCCB never transits btexecuteccb), so when the adapter completes the BDR mailbox the production btdone hits the bt.c:1388 guard first -- console 'btdone - Attempt to free non-active BCCB ' -- and returns; the recovery branch (bt.c:1406) is unreachable (AC_SENT_BDR never fires, pending timeouts never reinstated, SIM queue stays frozen). The 2s re-arm (bt.c:2215) then fires the hard-reset branch: the virtual HBA observed the production driver write HARD_RESET(0x80) to CONTROL_REG (vhba_hard_resets=1, last_ctl=128) and the timed-out CCB completed CAM_CMD_TIMEOUT (0xb). Every command timeout therefore escalates to a full bus-wide hard reset 2s later; targeted recovery impossible.