# DF-4160 — Unbounded PHY-reset poll in xe_mii_init(): attach/init hard hang

**File:** `sys/dev/netif/xe/if_xe.c:1637-1639` · **Severity:** Low · **CWE-835**

## Root cause

```c
/* Reset the PHY */
xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_RESET);
DELAY(500);
while(xe_phy_readreg(scp, PHY_BMCR) & PHY_BMCR_RESET);   /* if_xe.c:1639 */
```

The poll has no iteration budget, no timeout, and no bailout. It executes:

- during `xe_attach()` → `xe_init()` (`if_xe.c:397`) — i.e. at PCMCIA card
  insertion / first `ifconfig xe0 up` — inside `crit_enter()` and the ifnet
  serializer, and
- on every later interface up-transition.

A PHY that acknowledges MII transactions but never clears `PHY_BMCR_RESET`
(e.g. broken silicon, or a deliberately malicious PCMCIA card — the card is
external, attacker-insertable hardware) pins the kernel in this loop forever:
crit section + serializer held, CPU spinning on bit-banged MDIO. The system
hangs at card insertion with no watchdog able to fire.

Note the escape hatches that do NOT save you: if the MII transaction fails to
ack, `xe_phy_readreg()` returns 0 (`xe_mii_readreg` zeroed `mii_data`, ack
failure returns garbage-free 0) and the loop exits — the hang requires a PHY
that acks and keeps reporting RESET. That is exactly the "present but stuck"
case a hostile or faulty card produces.

## Fix

`fix.diff` bounds the poll (1000 × 1 ms) and treats a stuck PHY as absent
(`xe_mii_init` then returns 0 → `scp->phy_ok = 0`), which the driver already
handles gracefully (10Mbit-only fallback in `xe_setmedia_serialized`).

## Verification

Hardware-gated (needs a Xircom-class PCMCIA adapter with a misbehaving PHY);
no such hardware exists in the QEMU guest, so no runtime verification is
possible. Source-level certainty: the loop body and exit condition are fully
visible; no hidden bound exists. FreeBSD 10.3's copy of this driver carries
the identical unbounded loop (shared 1999-vintage bug).

## 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.
