Infinite loop in response queue processing when target mode consumes multiple entries
Summary
isp_intr at isp.c:5121-5124: while(tsto != oop) { optr = ISP_NXT_QENTRY(tsto, ...); }. Loop assigns to optr but NEVER modifies tsto or oop - condition is invariant. If initially true (isp_handle_other_response advanced tsto via target-mode ATIO7 long-IU continuation), unconditional infinite loop in hard interrupt context. Requires ISP_TARGET_MODE compiled (not default) and adapter in target role. Remote FC initiator sends Extended CDB/IU >56 bytes triggering long-IU path in isp_target_notify. Permanent kernel hang. Fix: change while to if.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1126 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | trigger-source | simulates queue pointers; proves loop body never advances tsto | 2.8 KB | view raw |
| fix.diff | suggested-fix | change while (tsto != oop) to if (tsto != oop) | 781 B | view raw |
| build.sh | build-script | cc -O2 -o harness harness.c | 65 B | view raw |
| run.sh | run-script | timeout 10 ./harness | 89 B | view raw |
| build.log | build-log | final successful build | 13 B | view raw |
| run.log | run-log | decisive run incl non-termination marker | 377 B | view raw |
| env.txt | environment | uname, cc version, pciconf (no ISP FC adapter) | 403 B | view raw |
| VERDICT.md | verdict | full narrative + ISP_TARGET_MODE gating discussion | 3.4 KB | β raw |
| README.md | readme | finding summary + build/run/expected | 1.5 KB | β raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-1126 β Infinite loop in isp_intr response-queue processing (SCSI target mode)
Finding
isp_intr at sys/dev/disk/isp/isp.c:5121-5124:
while (tsto != oop) {
optr = ISP_NXT_QENTRY(tsto, RESULT_QUEUE_LEN(isp));
}
The loop body assigns to optr but never modifies tsto or oop β
the condition is invariant. isp_handle_other_response (:5113) passes
&tsto to isp_target_notify (isp_target.c:5988), which in the long-IU
continuation path (isp_target.c:178-181) advances *optrp (= tsto).
After return, tsto != oop and the loop spins forever in hard interrupt
context β permanent kernel hang.
Requires ISP_TARGET_MODE compiled (not default) and a target-mode FC
adapter receiving an Extended CDB/IU > 56 bytes from a remote initiator.
Reachability on this guest
NOT reachable. No QLogic ISP FC adapter present. ISP_TARGET_MODE is
not compiled into the default modules. Doubly gated. Latent.
A userspace harness demonstrates the invariant loop (capped at 1M iters to prove non-termination rather than actually hang).
Build / Run / Expected
cc -O2 -o harness harness.c # build.sh ./harness # run.sh # Expected: "LOOP DID NOT ADVANCE tsto -- infinite loop confirmed"
Files
harness.cβ simulates the queue bookkeeping; proves the loop body never advanceststo.fix.diffβ changeswhile (tsto != oop)toif (tsto != oop).build.log/run.log/env.txtβ captured outputs.
VERDICT β DF-1126
Verdict: REPRODUCED (primitive) / NOT REACHABLE on guest (HW-gated)
The cited bug is real and confirmed by source trace + userspace
loop-bookkeeping demonstration. It is a latent infinite-loop / hang
primitive requiring ISP_TARGET_MODE compiled (not default) and a
target-mode FC adapter receiving an Extended CDB/IU.
Mechanism (confirmed path:line)
isp_intr(sys/dev/disk/isp/isp.c:5112-5124) processes response queue entries. For unrecognized entry types it callsisp_handle_other_response(isp, etype, hp, &tsto)(:5113) wheretstois a local initialized tooop.isp_handle_other_response(:5964-6022) forRQSTYPE_ATIOetc. callsisp_target_notify(isp, hp, optrp)(:5988) inside#ifdef ISP_TARGET_MODE.isp_target_notify(sys/dev/disk/isp/isp_target.c:104) for anRQSTYPE_ATIO7(IS_24XX) with a long IU (at_ta_len > QENTRY_LEN-8) advances*optrpin a loop at:178-181:*optrp = ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp)).- Back in
isp_intr:5121-5124:c while (tsto != oop) { optr = ISP_NXT_QENTRY(tsto, RESULT_QUEUE_LEN(isp)); }The body assigns tooptrbut never modifieststooroop. Afterisp_target_notifyadvancedtstopastoop, the condition is invariantly true β infinite spin in hard interrupt context β permanent kernel hang.
Reproduction (userspace harness)
The harness simulates the queue pointers, calls a stand-in for
isp_handle_other_response that advances tsto by one slot, then runs
the exact kernel loop body (capped at 1M iterations to prove
non-termination rather than actually hang):
oop = 100 tsto = 101 (advanced by isp_target_notify long-IU path) Hit iteration cap (1000000) without termination. tsto before loop = 101, tsto after = 101 (UNCHANGED) *** LOOP DID NOT ADVANCE tsto -- infinite loop confirmed ***
Impact ceiling
- Per-trigger: permanent kernel hang in hard interrupt context. The
CPU spinning in
isp_intrcannot be preempted; the system is wedged. - Privilege: remote β a FC initiator sending an Extended CDB/IU > 56
bytes triggers it. Requires target-mode FC adapter with
ISP_TARGET_MODE. - Realistic: doubly gated (
ISP_TARGET_MODEnot default + FC target role). Niche but remote-triggerable when configured.
Fix
fix.diff changes while to if:
if (tsto != oop) {
optr = ISP_NXT_QENTRY(tsto, RESULT_QUEUE_LEN(isp));
}
The body was always meant to run at most once (it only computes the next
optr from the updated tsto). The while was a latent bug because the
body never advances the loop variables.
Validated: isp.ko builds with RC=0 after applying the fix.
Fix validation
- Patch applies cleanly:
Hunk #1 succeeded at 5114. makeinsys/dev/disk/isp/βisp.ko+ all FC firmware modules linked,ISP_RC=0.- Cannot boot-test (no QLogic ISP FC adapter + no
ISP_TARGET_MODE);fix_status: not_testable.
PoC changes
harness.cwritten from scratch. Simulates queue pointers and proves the loop body never advanceststo(capped at 1M iters).
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_testablecompile validated
module build rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source+harness. isp_intr while(tsto!=oop) body never advances -> infinite loop. Doubly gated (ISP_TARGET_MODE+HW).
No comments yet.