e1000_release_swfw_sync_80003es2lan acquires the SWSM hardware semaphore in an unbounded empty-body loop on every PHY/KMRN/NVM release path: a stuck SMBI bit pins a CPU forever under the driver serializer
Summary
The release path takes the hardware semaphore via an unbounded empty-body while loop. The per-call acquire is bounded (~1.6s MMIO spin max) but returns failure on timeout, so a stuck SMBI bit (ASF/management-firmware hold, wedged sibling function on the dual-port part, post-bus-error device) makes the outer loop retry forever. Every PHY/KMRN/NVM access and reset funnels through it under the igb serializer: CPU livelock + interface wedge. The acquire side is bounded; the release side lost the bound. Identical upstream-inherited shape at 82575.c and i210.c. Bound-the-release-retry fix (replicate x3).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4306 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.5 KB | β raw | |
| VERDICT.md | β | 4.6 KB | β raw | |
| env.txt | β | 1.2 KB | view raw | |
| fix.diff | β | 847 B | view raw | |
| manifest.json | β | 1021 B | view raw | |
| verdict.json | β | 3.6 KB | view raw |
DF-4306 β e1000_release_swfw_sync_80003es2lan spins unboundedly acquiring the HW semaphore on every PHY/NVM release path
File: sys/dev/netif/ig_hal/e1000_80003es2lan.c (pass 2, no known findings)
Lines: 449-463 (e1000_release_swfw_sync_80003es2lan, empty-body while at :455-456), reached from every PHY/KMRN/NVM release on this MAC: :499/:514/:531 (gg82563 read), :570/:585/:602 (gg82563 write), :318 (phy release wrapper), :353 (KMRN mac_csr release), :375/:391 (NVM release), :851 (reset_hw).
Family shape: while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS); β identical pattern at e1000_82575.c:1110 and e1000_i210.c:146 (upstream-inherited Intel HAL; Linux e1000e has the same construct).
The bug
The SW/FW-sync acquire side is bounded (50 Γ 5 ms, :402-439), but the release side takes the SWSM hardware semaphore in an unbounded retry loop:
while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
; /* Empty */ /* e1000_80003es2lan.c:455-456 */
e1000_get_hw_semaphore_generic (e1000_mac.c:1721) is itself a bounded
busy-wait (timeout = nvm.word_size + 1 iterations of usec_delay(50);
word_size β€ 16384 by the :176-178 cap β up to ~1.6 s of MMIO spin per
attempt) that returns -E1000_ERR_NVM when the SMBI bit stays set. A
stuck SMBI bit β management-firmware hold (this MAC reports
asf_firmware_present = TRUE, :223), a second port's driver wedged, or a
device gone south after a bus error β therefore turns every release
call into an infinite ~1.6 s-step MMIO spin. All call sites run under the
igb driver serializer; the spinning thread pins its CPU, burns the PCI
link with MMIO reads, and blocks every other entry point on the interface
until reboot.
Severity Low per rubric: "narrow trigger β¦ requires specific hardware" (the 80003ES2LAN NIC plus a wedged SMBI bit β a hardware/firmware fault, not attacker-controllable state). The code shape itself is certain.
Guest status
No 80003ES2LAN (or any igb) device on this guest (env.txt: hw.igb
unknown oid, virtio-only); not_reproduced per family convention
(cf. DF-3827). Defect certain from source.
Fix
Bound the retry (mirroring the acquire-side 50Γ5 ms budget) and bail with
a debug print instead of spinning forever β see fix.diff
(patch -p1 --dry-run clean). Trade-off documented in the diff: bailing
leaves the SW_FW_SYNC bit set (PHY/NVM access bricked) but saves the CPU
and the system; the NIC is unusable either way with a stuck semaphore.
DF-4306 VERDICT β unbounded HW-semaphore spin in the 80003ES2LAN SWFW release path
Bottom line
Source-certain unbounded-wait defect (DF-4217 family shape: a hardware
wait whose timeout branch can never be reached because the loop condition
never terminates). Runtime not reproducible on this guest β no 80003ES2LAN
device exists (hw.igb unknown oid, virtio-only guest; QEMU's Intel NIC
models are e1000-family MMIO-incompatible with the 80003 KMRN/SWFW
register set and no such device is attached anyway) β not_reproduced
per family convention (DF-3827). Impact ceiling on real hardware: CPU
livelock + interface wedge (availability only). Low severity: trigger is a
hardware/firmware fault state (stuck SWSM.SMBI bit), not attacker-set
state.
Trace
e1000_release_swfw_sync_80003es2lan(e1000_80003es2lan.c:449-463):while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) ;at :455-456 β no bound, no yield, MMIO read loop.e1000_get_hw_semaphore_generic(e1000_mac.c:1721-1745): bounded per-call (SMBI poll timeout =hw->nvm.word_size + 1Γ 50 Β΅s; word_size capped to 1<<14 by e1000_80003es2lan.c:176-178), returns-E1000_ERR_NVMon timeout β the outerwhileretries the entire bounded poll forever.- Reachability: every PHY register access (
e1000_read/write_phy_reg_ gg82563_80003es2lan:482/:499/:514/:531, :553/:570/:585/:602), every KMRN access (:1388/:1402, :1425/:1436), NVM acquire/release wrapper (:368-391), ande1000_reset_hw_80003es2lan(:845-851) funnel through acquire/release β i.e. link maintenance (1 Hz igb tick), ifmedia changes, resets. All execute under the igb serializer. - Why SMBI sticks: the 80003 pairs with manageability firmware
(
mac->asf_firmware_present = TRUE:223; FWSM-checkedarc_subsystem_valid:227-228) and dual-function parts share the semaphore β a fw hold or a wedged sibling function leaves SMBI set indefinitely (this is why the acquire side has a timeout at all; the release side just forgot the bound).
Checklist coverage (whole-file negative results)
- (a) init_function_pointers NULL-op coverage:
set_lan_idcalled at :269 is pre-assigned bye1000_init_mac_ops_generic(e1000_mac.c:58) whiche1000_setup_init_funcs(e1000_api.c:447) runs BEFORE the family init (:486) β safe. Serdes (non-copper) early-return leaves phy read/write NULL, but both local call sites guard (if (!(hw->phy.ops.read_reg)):670/:765) andcfg_on_link_upis only invoked on the copper branch ofe1000_get_link_up_info_80003es2lan(:800-803). Clean. - (b) rar/LAA: no direct RAR mutation in this file (delegates to
e1000_init_rx_addrs_generic/e1000_check_alt_mac_addr_generic);rar_entry_count = E1000_RAR_ENTRIES(:221). Clean. - (c) PHY modes: KMRN retry do/while loops bounded by
GG82563_MAX_KMRN_RETRY=5 (e1000_80003es2lan.h:92) at :1312/:1363;
smart-speed not implemented here; cable-length table indexing guarded
(
index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5:774-775 with mask 0x0007, table[11] β max touch table[10]). Clean. - (d) NVM ops: word_size derived from EECD with the
size > 14 β 14cap (:176-178, 16 K words max); write delegates toe1000_write_nvm_spi. The mdic_wa verify-read at :511 ignores its ret_val before comparingtemp(:513) βtempis pre-initialized (:496), worst case a wrong page read is returned; verbatim upstream Intel HAL, no kernel memory effect (not filed; hardening note only). - (e) semaphore paths: acquire bounded (:412-431); release unbounded
(:455) β this finding;
e1000_get_cfg_donebounded (PHY_CFG_TIMEOUT Γ 1 ms, :641-646). - (f) div0: the only division is the constant
/2at :780. Clean. - (g) FreeBSD divergence: file is byte-carried from FreeBSD's ig_hal
(Intel-shared source,
$FreeBSD$tag :33); no DragonFly-local modifications of substance in this snapshot (single bulk-import commit in history).
Fix validation
fix.diff bounds the retry (50 attempts, matching the acquire-side budget)
with a DEBUGOUT on give-up; patch -p1 --dry-run clean. Same-shape
instances exist at e1000_82575.c:1110 and e1000_i210.c:146 β the fix
should be replicated there (noted; those files are separate audit rows).
Cannot be runtime-validated without 80003 hardware β fix_status
not_testable.
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 authored against the read-only sys/ tree (patch -p1 --dry-run clean); cannot be runtime-validated without 80003ES2LAN hardware.
findings/poc/DF-4306/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (path:line trace incl. per-call bound analysis of e1000_get_hw_semaphore_generic and the whole-file checklist negative results); env.txt (hw.igb unknown oid, virtio-only guest, guest src md5 == audited tree); fix.diff (bounded retry, patch -p1 --dry-run clean)
PoC changes
No seed; no runnable PoC exists without an 80003ES2LAN device - pack documents the source proof, per-call cost analysis, family cross-references, and the fix.
Verified recommended fix
Bound the release retry to the acquire-side budget (e.g. 50 attempts) and give up with a debug print instead of spinning forever; replicate at e1000_82575.c:1110 and e1000_i210.c:146; see fix.diff.
Verdict
Source-certain unbounded-wait defect (DF-4217 family shape): e1000_release_swfw_sync_80003es2lan (sys/dev/netif/ig_hal/e1000_80003es2lan.c:449-463) acquires the SWSM hardware semaphore in an empty-body unbounded loop (:455-456). e1000_get_hw_semaphore_generic (e1000_mac.c:1721) is bounded per call (word_size+1 iterations of usec_delay(50), word_size capped at 16384 by :176-178) and returns -E1000_ERR_NVM on timeout, so a stuck SMBI bit (ASF/management-firmware hold - this MAC sets asf_firmware_present=TRUE at :223 - wedged sibling function on the dual-port part, or post-bus-error device) makes the outer loop retry the full ~1.6s MMIO poll forever. Every PHY register access (:482/:499/:514/:531, :553/:570/:585/:602), KMRN access (:1388/:1402/:1425/:1436), NVM wrapper path (:368-391) and reset_hw (:845-851) funnel through this release while the caller holds the igb driver serializer: a stuck semaphore pins one CPU at 100% MMIO spin and wedges every interface entry point until reboot. The acquire side is bounded (50x5ms, :412-431) - the release side simply lost the bound. Identical upstream-inherited shape at e1000_82575.c:1110 and e1000_i210.c:146. Kernel-path reproduction impossible on this guest: no 80003ES2LAN/igb device exists (env.txt: hw.igb unknown oid, virtio-only) - not_reproduced per family convention (DF-3827). Impact ceiling: CPU livelock + interface wedge on real hardware; trigger is a hardware/firmware fault state, not attacker-controllable - Low severity, availability only.
No comments yet.