# DF-3912 — mpt handshake reply walk: negative `left` from IOC MsgLength==0 → non-terminating polling loop (attach-time livelock)

**File:** `sys/dev/disk/mpt/mpt.c`
**Lines:** 1475-1491 (`mpt_recv_handshake_reply`)
**Severity:** Low (malicious/faulty IOC → driver-attach hang with MPT_LOCK held) — **hardware-gated**
**Class:** base:dev / CWE-835 (loop with unreachable exit), pass 2 (checklist (f): reply-frame walks beyond the known set)

## Build / Run
```
./build.sh && ./run.sh
```

## Expected output
```
MsgLength=0 -> left=-2
loop ran 100000000 iterations and was cut off by the harness ...
trigger rc=1 (1 == non-terminating loop demonstrated)
```

## Root cause
`left = (hdr->MsgLength << 1) - 2;` (:1475) with the IOC-supplied MsgLength
(u8, dwords). For MsgLength < 2 `left` is negative, and `while (left--)`
(:1477) can never become false (int underflow wraps through INT_MIN). The
loop body only exits via `mpt_wait_db_int()` failure — 300000 × DELAY(100)
= up to 30 s of spinning per attempt — so a malicious IOC that keeps the
doorbell interrupt asserted pins the attach thread in a livelock holding
MPT_LOCK (boot hang). Bounded-write side is safe (`if (reply_left-- > 0)`),
so this is purely the loop-exit defect.

## Fix
`fix.diff` clamps `left < 0` to 0 (skip the remainder walk). Validated in
the batch nativekernel rebuild: mpt.c compiled in-kernel and as module with
`-Werror`, rc=0 (fix_build.log).
