adv_run_doneq walks the device-fed done-queue FWD chain with no iteration bound β cyclic chain = interrupt-context livelock / hard system hang (DF-4307 livelock facet, narrow twin)
Summary
The done-queue walk terminates solely on the LRAM FWD byte; the only corruption guards are #ifdef DIAGNOSTIC panics compiled out of release kernels. A corrupt/hostile cyclic chain spins the interrupt forever (crit section held, ~10 LRAM port I/O ops per iteration). Guest model over a 3-entry circular chain never terminates within a 1e6 cap. Budget-the-walk fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4350 Β· 16 files| File | Type | Description | Size | |
|---|---|---|---|---|
| df43xx_rig.c | β | 41.5 KB | view raw | |
| advlib.h | β | 25.4 KB | view raw | |
| Makefile | β | 117 B | β download | |
| build.sh | β | 152 B | view raw | |
| prime.sh | β | 1.1 KB | view raw | |
| build_fixed.sh | β | 1.1 KB | view raw | |
| panic.baseline.txt | β | 814 B | view raw | |
| run.4349only-livelock.log | β | 1.7 MB | β download | |
| run.bothfixed.log | β | 34.3 KB | view raw | |
| run.log | β | 986 B | view raw | |
| fix_run.log | β | 819 B | view raw | |
| fix_build.log | β | 599 B | view raw | |
| build.log | β | 929 B | view raw | |
| fix.diff | β | 1.1 KB | view raw | |
| env.txt | β | 1.1 KB | view raw | |
| verdict.json | β | 5.6 KB | view raw |
Fix verification
fixedOn the shipped kernel the cyclic chain panics (DF-4349 sink); on the both-fixed kernel the identical dispatch logs 'adv9: done queue walk exceeded 276 entries, stopping (corrupt LRAM?)' and adv_intr returns after 4273 LRAM data-port services, guest alive, control completions unaffected. baseline_reproduced=1 (system-halting), patched_reproduced=0.
fix_run.log / run.bothfixed.log: 'done queue walk exceeded 276 entries' + 'df43xx[4]: adv_intr RETURNED after 4273 data-port services'; panic.baseline.txt for the baseline halt
Confirmed kernel references
Detail
Exploit chain
Corrupt/hostile AdvanSys LRAM done-queue FWD bytes forming a cycle -> production adv_run_doneq loop (crit section held in the real ISR) never sees ADV_QLINK_END -> shipped kernel: revisit panic via DF-4349 sink (hard crash); DF-4349-fixed kernel: infinite drop-loop = interrupt livelock / permanent kernel-thread wedge, watchdog-class DoS. Requires physical AdvanSys HBA with buggy/hostile firmware or a hostile SCSI peripheral; no unprivileged-user or remote path.
Evidence (decisive lines)
panic.baseline.txt (cyclic chain -> panic on shipped kernel), run.4349only-livelock.log (full serial: 'entering production adv_intr with cyclic FWD chain', 28883 drop lines, no RETURNED, dbg_hits climb, kldunload EBUSY), run.bothfixed.log + fix_run.log (budget break at ADV_MAX_TOTAL_QNG+ADV_MAX_SG_LIST=276, adv_intr RETURNED after 4273 services), run.log (condensed livelock capture)
PoC changes
Replaced the seed userspace model with the production-handler KLD dispatch rig shared with DF-4349 (fabricated softc + watchpoint-emulated ASC LRAM + nm-resolved kernel adv_intr). Added scenario 4 (synchronous cyclic-chain dispatch) and scenario 6 (dedicated-kthread dispatch with heartbeat callouts and a kern.df43xx.dbg_hits counter that counts every emulated LRAM data-port access made by the spinning production walk) plus the two rebuilt-kernel variants that isolate the livelock (DF-4349 fix only) and validate the budget fix (both fixes).
Verified recommended fix
Budget the done-queue walk at ADV_MAX_TOTAL_QNG + ADV_MAX_SG_LIST iterations and break with a diagnostic when exceeded (a legitimate done queue can never be longer).
Verdict
REPRODUCED as a system-halting DoS through the production adv_intr of the shipped kernel binary, with the pure livelock isolated on a purpose-built kernel. Cyclic device-fed FWD chain (6->7->6): on the SHIPPED kernel the unbounded walk revisits completed slots and panics via the DF-4349 double-completion sink (panic.baseline.txt) - a hard device-fed crash. On a kernel rebuilt with ONLY the DF-4349 validation fix (kernel #3), the walk drops the revisited entries and NEVER TERMINATES: the dispatch kthread wedges inside production adv_run_doneq (no RETURNED marker), the console floods with 28,883 'dropping completion' lines, and the LRAM data-port service counter (kern.df43xx.dbg_hits, incremented by the #DB chip emulator on every production port access) climbs monotonically across six samples (9985 -> 24895 -> 360550 -> 365530 -> 425830 -> 433270, ~2500 port ops/s); kldunload is refused EBUSY because the thread is still spinning - exactly the filed interrupt-context livelock. On the kernel with BOTH fixes (kernel #2) the walk is budget-bounded: 'done queue walk exceeded 276 entries, stopping' and adv_intr RETURNS after 4273 port services, guest alive. Termination of the walk is controlled solely by the device-written FWD byte (advansys.c:1043/:1068/:1114); no iteration bound exists in the unpatched driver - confirmed structurally and behaviorally.
No comments yet.