Error paths permanently strand reserved request slots and hang CAM ccbs: AEN/param channels die; map-failed ccb is on no queue and can never be completed
Summary
(1) The send/set/get error paths return leaving reserved slots BUSY forever - the AEN fetch channel and param channel die permanently (the get_param slot has cb=NULL, uncompletable). (2) tws_execute_scsi returns on map failure without xpt_done or slot release; the request is on NO queue (submission inserts it), so the reset drain can never rescue it - permanent ccb leak + hung transaction, with the pre-armed callout turning a software failure into a full controller reset. Complete+release fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4403 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.1 KB | β raw | |
| VERDICT.md | β | 2.5 KB | β raw | |
| trigger.c | β | 633 B | view raw | |
| fix.diff | β | 2.6 KB | view raw | |
| verdict.json | β | 2.5 KB | view raw | |
| env.txt | β | 541 B | view raw |
DF-4403 β Reserved request slots and CAM ccbs leaked on error paths (permanent AEN/param channel death; hung ccb)
What
Four error paths in sys/dev/raid/tws/tws_cam.c abandon resources:
tws_send_scsi_cmd():841-844:req->data = kmalloc(TWS_SECTOR_SIZE, M_NOWAIT|M_ZERO); on failure returns ENOMEM whilereqs[1](the AEN fetch slot) staysTWS_REQ_STATE_BUSYforever β reserved slots are gated bystatealone and are never on FREE_Q (tws.c:631-632, 760-769), so the asynchronous-event channel is permanently dead: no AEN ever fetched again (eachtws_aen_completere-arms viatws_fetch_aen,tws_cam.c:472-476).tws_set_param():868-872: same forreqs[3]β the parameter channel dies;tws_aen_synctime_with_hostand shutdowntws_init_connectpaths degrade.tws_execute_scsi():807-810: the ccb timeout callout is armed at:807andtws_map_request()may fail (e.g.bus_dmamap_loadENOMEM / EFBIG); the error is returned totws_action(:271-272, trace only) withoutxpt_done(ccb)and without releasing the request β the request slot is off FREE_Q forever (it is only re-queued by completion paths), the ccb is never completed, and because the request was never submitted it is not on BUSY_Q either (tws_submit_commandinserts,tws_hdm.c:326-330), so even the reset drain (tws_drain_busy_queue,tws_cam.c:616-643) can never complete it: permanent ccb leak + hung upper-layer transaction (its callout eventually firestws_timeoutβ full controller reset for a software failure).tws_get_param():918-921: same slot-stranding pattern forreqs[3]when the sector kmalloc fails (req->cb == NULLthere, so nothing can ever complete it).
Impact
Progressive driver degradation β CAM resource exhaustion β I/O DoS on the adapter under sustained memory pressure; loss of AEN delivery (array events/alarms silently stop). Requires kmalloc/dmamap failure β Low severity, but the leaks are permanent (no recovery path).
Status
QEMU guest has no 3ware HBA β inconclusive; each leak path proven from source.
VERDICT β DF-4403
Status: inconclusive (hardware-gated).
Proof (per path)
- Reserved-slot lifecycle.
tws_get_request()marks slots 0-3 BUSY bystateonly (tws.c:749-789); only slots β₯TWS_RESERVED_REQSever live on FREE_Q (tws.c:631-632). A reserved slot is freed by settingstate = TWS_REQ_STATE_FREE(e.g.tws_getset_param_complete,tws_cam.c:392-394). If an allocation between get and submit fails, none of those completion paths runs: -tws_send_scsi_cmdtws_cam.c:842-844βreqs[1](AEN) stuck BUSY; -tws_set_param:870-872andtws_get_param:919-921βreqs[3] (GETSET_PARAM) stuck BUSY (get_param additionally hascb == NULL,:924, so even a spurious firmware response can never complete it). Every futuretws_get_request(type)for that type returns NULL (tws.c:763-764) β the channel is dead for the life of the adapter. AEN death specifically silencestws_aen_completeβtws_fetch_aenre-arm (tws_cam.c:472-476`), i.e. array event delivery stops silently. - SCSI IO slot + ccb.
tws_execute_scsiremoves a request from FREE_Q at:719(tws.c:792-794) and arms the ccb callout at:807. Iftws_map_requestfails (:809βbus_dmamap_loadENOMEM; the EINPROGRESS case is converted at:995-999and is fine), the function returns the error;tws_actiononly traces (:271-272). The ccb hasCAM_SIM_QUEUEDset (:717) and is neverxpt_doned; the request is on no queue (BUSY_Q insertion happens only intws_submit_command,tws_hdm.c:326-330, never reached), sotws_drain_busy_queue(tws_cam.c:616-643) cannot rescue it during a reset either. The upper layer waits forever; the armed callout (:807) firestws_timeoutβtws_resetβ adapter-wide disruption β for a software allocation failure.
Trigger
Kernel memory pressure (M_NOWAIT sector kmallocs / dmamap load failure) on a host with the controller. Not reproducible on the audit guest.
Impact ceiling
Permanent (unrecoverable) resource loss per event: AEN/param channels die; CAM transactions hang with no completion path. DoS-grade degradation, gated on allocation failure β Low.
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_testablefix.diff adds the missing unwind on all four paths; not validatable on the guest (no controller, uncontrollable allocation failure).
fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (per-path proof); fix.diff (free reserved slots on alloc failure; complete+release ccb on map failure); trigger.c (conditions)
PoC changes
no seed; conditions stub only
Verified recommended fix
Return reserved slots to FREE state on allocation failure and complete+release the ccb when tws_map_request fails in tws_execute_scsi.
Verdict
Certain from source, hardware/allocation-failure gated. (1) tws_send_scsi_cmd (:842-844), tws_set_param (:870-872) and tws_get_param (:919-921) strand reserved slots reqs[1]/reqs[3] in TWS_REQ_STATE_BUSY when their sector kmalloc fails β reserved slots are gated by state alone (tws.c:749-789, 631-632), so the AEN fetch channel and the parameter channel die permanently (get_param's slot even has cb==NULL at :924, so nothing can ever complete it). (2) tws_execute_scsi (:807-810) returns tws_map_request failure to tws_action (:271, trace only) without xpt_done and without releasing the slot; the request was never submitted so it is on no queue (BUSY_Q insert happens only in tws_submit_command, tws_hdm.c:326-330) and even the reset drain (tws_cam.c:616-643) can never complete the ccb β permanent CAM transaction hang plus slot leak, and the pre-armed callout turns the software failure into a full controller reset. Guest lacks the HBA; each path proven from source in VERDICT.md.
No comments yet.