DF-1126 / harness.c
/* * DF-1126 userspace harness — isp_intr response-queue infinite-loop primitive. * * The kernel bug (sys/dev/disk/isp/isp.c:5121-5124): * uint32_t tsto = oop; * r = isp_handle_other_response(isp, etype, hp, &tsto); * ... * while (tsto != oop) { * optr = ISP_NXT_QENTRY(tsto, RESULT_QUEUE_LEN(isp)); * } * * isp_handle_other_response -> isp_target_notify (isp_target.c:178-181) advances * *optrp (= tsto) via `*optrp = ISP_NXT_QENTRY(*optrp, ...)` when an ATIO7 * long-IU continuation is processed in ISP_TARGET_MODE. After it returns, * tsto != oop but the loop body NEVER modifies tsto or oop -> invariant * condition -> unconditional infinite loop in hard interrupt context -> kernel * hang. * * Reachability: requires ISP_TARGET_MODE compiled AND a target-mode FC adapter * AND a remote initiator sending Extended CDB/IU > 56 bytes. Doubly gated, not * reachable on this audit guest. * * This harness simulates the queue bookkeeping and demonstrates the loop never * terminates. We cap iterations to prove the invariance rather than actually * hang. * * Build: cc -O2 -o harness harness.c * Run: ./harness * Expected: "LOOP DID NOT ADVANCE tsto -- infinite loop confirmed". */ #include <stdio.h> #include <stdint.h> #define RESULT_QUEUE_LEN(isp) 256 #define ISP_NXT_QENTRY(i, l) (((i) + 1) & ((l) - 1)) /* stand-in for isp_handle_other_response having processed a long IU and * advanced *optrp by one queue slot (isp_target.c:179). */ static int handle_other_response_advances_tsto(uint32_t *optrp) { *optrp = ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(0)); return 1; /* target_notify succeeded */ } int main(void) { uint32_t oop = 100; uint32_t optr = oop; uint32_t tsto = oop; /* simulate one entry processed that triggers long-IU continuation */ handle_other_response_advances_tsto(&tsto); printf("oop = %u\n", oop); printf("tsto = %u (advanced by isp_target_notify long-IU path)\n", tsto); unsigned long iters = 0; const unsigned long CAP = 1000000; /* would never return in-kernel */ uint32_t tsto_before = tsto; /* exactly the kernel loop body: assigns optr, never touches tsto/oop */ while (tsto != oop) { optr = ISP_NXT_QENTRY(tsto, RESULT_QUEUE_LEN(0)); if (++iters >= CAP) break; } if (iters >= CAP) { printf("\nHit iteration cap (%lu) without termination.\n", CAP); printf("tsto before loop = %u, tsto after = %u (UNCHANGED)\n", tsto_before, tsto); printf("optr = %u (recomputed each iter from constant tsto)\n", optr); printf("\n*** LOOP DID NOT ADVANCE tsto -- infinite loop confirmed ***\n"); printf(" Fix: change `while` to `if` so the body runs at most once.\n"); return 0; } printf("loop terminated after %lu iters -- unexpected.\n", iters); return 1; } |