Unbounded PHY-reset busy-wait in my_autoneg_xmit β the driver's only hardware-wait loop without MY_TIMEOUT (spins forever in ioctl, boot, and ISR contexts holding ifp->if_serializer)
Summary
The reset-bit poll has no counter - contrast my_setcfg and my_reset, both bounded at MY_TIMEOUT with failure kprintf. A PHY whose BMCR sticks at 0xFFFF parks the caller forever: via ifconfig media (root), via boot FORCEDELAY, and worst via my_txeoc's deferred autoneg running inside my_intr holding the serializer - the whole ifnet including its watchdog is wedged. The my(4) instance of the unbounded idle/reset-loop family (DF-4217 sibling). Bounded-loop fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4258 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trigger.sh | β | 532 B | view raw | |
| env.txt | β | 1007 B | view raw | |
| VERDICT.md | β | 2.1 KB | β raw | |
| fix.diff | β | 704 B | view raw | |
| manifest.json | β | 790 B | view raw | |
| verdict.json | β | 2.3 KB | view raw |
DF-4258 VERDICT β unbounded while (BMCR & RESET) spin in my_autoneg_xmit
Status: inconclusive on the audit guest (hardware-gated). Missing bound certain at source level.
Reproduction attempt
No Myson PCI device on the guest (env.txt) β my0 cannot exist, the MII
bit-bang (my_send_cmd_to_phy, if_my.c:161-209) cannot run. This matches
the treatment of the sibling unbounded-loop family findings (DF-4217 ae
i-- and the DF-3604/3761/3715 NIC-checklist set, all hardware-gated).
Analysis
if_my.c:379 is the only hardware-wait loop in the driver without the
MY_TIMEOUT guard β contrast if_my.c:708-714 (my_setcfg) and if_my.c:738-743
(my_reset), both for (i = 0; i < MY_TIMEOUT; i++) with a failure
kprintf. The reset poll executes:
- at boot for every attach (FORCEDELAY, if_my.c:946 β 422),
- from
my_ifmedia_updon SIOCSIFMEDIA (root via ifconfig, if_my.c:1508-1511), - from
my_txeocin the interrupt service routine when a deferred autoneg fires (if_my.c:1203-1204 β 436).
A PHY whose BMCR read sticks at 0xFFFF (hung part, unplugged card, PCI
error) or that never completes self-reset parks the caller forever. In the
ISR case ifp->if_serializer is held by my_intr (established via
bus_setup_intr(..., ifp->if_serializer), if_my.c:955-957), so the whole
ifnet β watchdog included β is wedged: system-level denial of service on
affected hardware. Root ioctl or hardware fault required to trigger at
runtime; boot variant needs no privileges but requires a broken PHY on the
installed card.
Severity Low (hardware/root-gated DoS), CWE-835, confidence certain for the missing bound.
Fix
Bound the loop like my_reset does (fix.diff): poll MY_TIMEOUT iterations with DELAY(10) and warn if the reset never completes.
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 bounded poll + warning, mirroring my_reset; hardware-gated, not validated here
findings/poc/DF-4258/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (all three trigger contexts + bounded-loop contrast); env.txt
PoC changes
trigger.sh wraps the ifconfig in timeout(1) to make the wedge observable
Verified recommended fix
Bound the BMCR reset poll with the same MY_TIMEOUT loop used in my_reset
Verdict
my_autoneg_xmit polls the PHY reset bit with 'while (my_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_RESET);' (sys/dev/netif/my/if_my.c:379) β the only hardware-wait loop in the driver without a MY_TIMEOUT bound (contrast my_setcfg 708-714 and my_reset 738-743). A PHY whose BMCR reads stick at 0xFFFF (hung part, card unplugged, PCI error β bit 15 always set) parks the caller forever, each iteration being a ~ms-scale bit-banged MII transaction. Reachable from SIOCSIFMEDIA (ifconfig media autoselect, if_my.c:1508-1511), at boot from my_attach's FORCEDELAY autoneg (if_my.c:946), and β worst β from my_txeoc inside the ISR with ifp->if_serializer held (if_my.c:1203-1204, bus_setup_intr established against the serializer at 955-957), which wedges the whole ifnet including its watchdog. Not executable on the audit guest (no Myson NIC, env.txt); missing bound is certain at source level. This is the my(4) instance of the unbounded idle/reset-loop family (cf. DF-4217).
No comments yet.