XPT_RESET_DEV device reset is silently converted to a malformed opcode-0 CCB by btexecuteccb's no-data opcode clobber β HBA error reply then panics the kernel
Summary
btaction sets hccb->opcode = INITIATOR_BUS_DEV_RESET for XPT_RESET_DEV and immediately calls btexecuteccb(bccb, NULL, 0, 0); the nseg==0 path unconditionally overwrites the opcode with INITIATOR_CCB. Every CAM device reset is transmitted as an ordinary initiator CCB with cmd_len=0, sense_len=0 and both datain/dataout set. A conforming MultiMaster firmware rejects that CCB with BTSTAT_INVALID_OPCODE/INVALID_CCB_OR_SG_PARAM, and btdone panics on both. At minimum device-reset error recovery is silently broken. camcontrol reset (privileged admin op that must not panic) triggers it. Preserve-reset-opcode fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4097 Β· 15 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.3 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 | |
| run_clean.sh | β | 3.9 KB | view raw | |
| run_panic.sh | β | 424 B | view raw | |
| run1_clean.log | β | 11.6 KB | view raw | |
| run_panic.log | β | 783 B | view raw | |
| panic.txt | β | 2.5 KB | view raw | |
| env.txt | β | 249 B | view raw | |
| fix.diff | β | 6.0 KB | view raw | |
| manifest.json | β | 786 B | view raw | |
| verdict.json | β | 2.6 KB | view raw |
DF-4097 β XPT_RESET_DEV clobbered into a malformed opcode-0 CCB
Verdict: REPRODUCED (clobber observed live + terminal kernel panic)
Same rig class as DF-2429 (see DF-2429/README.md): the REAL production
btaction/btdone, dispatched through the real CAM XPT layer
(xpt_action) over a fabricated post-attach softc.
Build
./push_rig.sh
Run
sh run_clean.sh # non-panicking half: the clobber observation sh run_panic.sh # panicking half: firmware rejection -> btdone panic
Expected output
queue io(control): post-dispatch hccb snapshotop=0x00 cmd_len=6β a normal no-data TUR.queue rst(XPT_RESET_DEV through the same production path): post-dispatch hccb snapshotop=0x00 cmd_len=0 sense_len=0β the INITIATOR_BUS_DEV_RESET (0x81) that btaction stored at bt.c:1062 was overwritten with INITIATOR_CCB (0x00) by btexecuteccb's unconditional nseg==0 path (bt.c:1285). The adapter is handed a reset request encoded as an ordinary CCB with a zero-length CDB.- Panic run: the virtual firmware rejects that malformed CCB the way
conforming MultiMaster firmware does β completion BMBI_ERROR with
btstat=BTSTAT_INVALID_OPCODE (0x16) written into the CCB β and
production btdone panics:
panic: bt9: Invalid CCB Opcode code(bt.c:1520), full backtrace in panic.txt.
DF-4097 VERDICT β XPT_RESET_DEV converted to a malformed opcode-0 CCB
Bottom line
REPRODUCED, both halves. (1) A CAM device reset dispatched through
the real xpt_action/production btaction path arrives at the host
adapter mailbox as an opcode 0x00 (INITIATOR_CCB) CCB with
cmd_len == 0, sense_len == 0 β the INITIATOR_BUS_DEV_RESET (0x81)
stored at bt.c:1062 is unconditionally overwritten by btexecuteccb's
nseg == 0 branch (bt.c:1285). (2) Conforming MultiMaster firmware
rejects such a CCB (BTSTAT_INVALID_OPCODE, 0x16) and production
btdone turns that device-fed status into
panic: bt9: Invalid CCB Opcode code (bt.c:1520) β captured with
backtrace in panic.txt.
Live evidence
Clean run (run1_clean.log lines 3-10):
[snap] id=0 (XPT_SCSI_IO TUR): hccb(op=0x00 cmd_len=6 ...) flags=0x1 timer=1 [snap] id=1 (XPT_RESET_DEV): hccb(op=0x00 cmd_len=0 sense_len=0 ...)
Both CCBs went through the identical production path
(xpt_action β devq β sim->sim_action = production btaction). The
reset CCB's opcode is 0x00 with an empty CDB β exactly the clobber.
Panic run (run_panic.log, panic.txt):
[rig] QUEUE done: id=0 bccb=0xfffff801167df620 opcode=0x00 cmd_len=0 ...
[rig] COMP: firmware writes completion: bccb=0xfffff801167df620
comp_code=0x04 btstat=0x16 sdstat=0x00 -> production btdone()
panic: bt9: Invalid CCB Opcode code
btdone() at btdone+0x6cd 0xffffffff8042e95d
rig_ioctl() at rig_ioctl+0x1ee ...
Root cause (path:line)
- sys/dev/disk/buslogic/bt.c:1062 β sets
hccb->opcode = INITIATOR_BUS_DEV_RESETfor XPT_RESET_DEV. - sys/dev/disk/buslogic/bt.c:1284-1287 β
btexecuteccb'snseg == 0branch unconditionally overwrites the opcode with INITIATOR_CCB; XPT_RESET_DEV passesbtexecuteccb(bccb, NULL, 0, 0)(bt.c:1070), so the reset path always lands here. - Terminal consequence: bt.c:1520 panic on the firmware's rejection.
Impact
On real bt(4) hardware, every CAM device reset (e.g. camcontrol reset)
is transmitted as a malformed CCB; error recovery is broken, and a
standards-conforming firmware reply panics the kernel. Privileged
admin-triggerable panic + broken recovery.
Fix validation
fix.diff preserves INITIATOR_BUS_DEV_RESET across the nseg==0 path.
Patched bt.c+btreg.h compile clean with the X86_64_GENERIC kernel flags
under -Werror (FIXED-COMPILES-CLEAN, bt.fixed.o). No runtime A/B
kernel build (panic 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_testableobject-compile validation only (panic 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
Confirmed kernel references
Detail
Exploit chain
camcontrol reset / CAM error recovery -> xpt_action(XPT_RESET_DEV) -> production btaction stores opcode 0x81 (bt.c:1062) -> btexecuteccb(bccb,NULL,0,0) (bt.c:1070) -> nseg==0 path overwrites opcode to 0x00 (bt.c:1285) -> firmware returns BTSTAT_INVALID_OPCODE (0x16) -> btdone panic at bt.c:1520
Evidence (decisive lines)
run1_clean.log (id=0 op=0x00 cmd_len=6 vs id=1 op=0x00 cmd_len=0 sense_len=0 through the identical production path); run_panic.log + panic.txt (panic: bt9: Invalid CCB Opcode code, btdone+0x6cd backtrace)
PoC changes
rig-built finding: XPT func_code constants corrected to 0x0901/0x0912 (XPT_FC_DEV_QUEUED is 0x900); queue->dispatch is asynchronous through the devq so each queue is followed by sleep+snap
Verified recommended fix
Preserve INITIATOR_BUS_DEV_RESET across btexecuteccb's nseg==0 path (fix.diff, object-compile validated)
Verdict
REPRODUCED both halves: (1) XPT_RESET_DEV through the real xpt_action/production btaction path transmits an opcode-0x00 INITIATOR_CCB with cmd_len=0 sense_len=0 -- the INITIATOR_BUS_DEV_RESET stored at bt.c:1062 is clobbered by btexecuteccb's unconditional nseg==0 branch at bt.c:1285; (2) conforming firmware rejects that malformed CCB with BTSTAT_INVALID_OPCODE and production btdone panics ('panic: bt9: Invalid CCB Opcode code', bt.c:1520) with backtrace captured. Device-reset error recovery is broken and admin-triggerable panic on real bt(4) hardware.
No comments yet.