ISP_TSK_MGMT ioctl (24xx) double-releases the FC scratch buffer on the error path, breaking fcbsy mutual exclusion
Summary
After isp_control(ISPCTL_RUN_MBOXCMD), ispioctl releases FC_SCRATCH_RELEASE(isp, chan) at :665 and, on any firmware failure, releases it again at :667. FC_SCRATCH_RELEASE is a raw fcbsy=0, so the second release destroys the ownership of any concurrent legitimate holder (FC kthread fabric/portdb scans, a second ioctl), letting two contexts share fcp->isp_scratch as the DMA target of MBOX_EXEC_COMMAND_IOCB_A64 - IOCBs and firmware responses get cross-delivered between unrelated mailbox commands. Root-only (/dev/ispN 0600) on 24xx/25xx hardware; corrupted scan/PDB/TMF data within the bounded scratch allocation - wrong abort/reset decisions, DoS-flavored misbehavior, no direct OOB. The double release is literal; one-line delete fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3659 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trig_note.c | β | 1.7 KB | view raw | |
| build.sh | β | 90 B | view raw | |
| run.sh | β | 95 B | view raw | |
| build.log | β | 55 B | view raw | |
| run.log | β | 173 B | view raw | |
| env.txt | β | 386 B | view raw | |
| fix.diff | β | 341 B | view raw | |
| VERDICT.md | β | 2.3 KB | β raw |
DF-3659 VERDICT β double FC_SCRATCH_RELEASE in ISP_TSK_MGMT
Status: not_reproduced (no QLogic hardware on guest; defect is literal in source)
Defect
sys/dev/disk/isp/isp_freebsd.c:665 releases the per-channel FC scratch
(fcbsy = 0, expansion at isp_freebsd.h:380), and line 667 releases it
again on the same path whenever retval != 0 ||
sp->req_completion_status != 0. Every other scratch consumer in the driver
(see isp.c:4557-4581 RESET_DEV, isp.c:4658-4682 ABORT_CMD) is careful to
release exactly once per acquire.
Race window and consequence
- T1 (root ioctl thread) runs a 24xx task-management command; firmware fails it.
- Line 665 clears
fcbsy. - T2 (FC kthread in
isp_fc_runstateβisp_scan_fabric/isp_scan_loop/isp_pdb_sync, or a concurrent ioctl) seesfcbsy == 0, acquires, starts a mailbox command DMAing intofcp->isp_scratch. - Line 667 clears
fcbsyagain β T2's ownership is destroyed. - T3 acquires and overlaps T2: two mailbox commands share one DMA scratch; IOCBs and firmware responses are cross-delivered.
Impact ceiling: corrupted scan/PDB/TMF data within the bounded scratch
allocation β wrong loop ids/WWNs fed into the port database and task
management, i.e. functional corruption and DoS, not a memory-safety break.
Trigger is root-only (/dev/ispN 0600, isp_freebsd.c:229) on 24xx/25xx
hardware with an unlucky interleaving.
Why not reproduced
Guest has zero QLogic PCI devices; /dev/isp* does not exist, so the ioctl
entry point cannot even be opened (run.log). The defect itself is provable
by inspection and the fix is a one-line deletion.
Fix
Remove the duplicate release at line 667 (fix.diff). After the fix the
error path matches the success path and the isp.c discipline.
Fix validation
not_testable β the affected code path requires ISP 24xx hardware plus a firmware-failing TMF racing the kthread; neither exists on this guest.
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_testableone-line deletion restores single-release discipline; cannot be behaviorally validated without 24xx hardware.
findings/poc/DF-3659/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (line-accurate sequence); fix.diff (deletes the duplicate release); run.log (no /dev/isp* on guest)
PoC changes
documentation-only trigger (runtime sequence needs 24xx HBA); compiled and ran the no-op on the guest to record absence
Verified recommended fix
Delete the duplicate FC_SCRATCH_RELEASE at isp_freebsd.c:667.
Verdict
ispioctl ISP_TSK_MGMT 24xx branch releases the FC scratch twice on the error path (isp_freebsd.c:665 then :667; FC_SCRATCH_RELEASE is a raw fcbsy=0 per isp_freebsd.h:380). A concurrent legitimate scratch holder (FC kthread scan or second ioctl) between the two releases loses ownership, allowing two contexts to share fcp->isp_scratch as the DMA target of MBOX_EXEC_COMMAND_IOCB_A64 -> IOCB/response cross-delivery between unrelated mailbox commands. Root-only 0600 cdev, 24xx hardware required, bounded to the scratch buffer (no OOB). Guest has no QLogic device and no /dev/isp* -> not_reproduced, device absent.
No comments yet.