Unchecked PHY/EEPROM read return values across ixgbe_common.c: config decisions from uninitialized kernel stack, and a failed PHY read written back clobbering the AN advertisement (DF-3643 parity)
Summary
Five clusters discard hw->phy.ops.read_reg / hw->eeprom.ops.read return values and act on the results: ixgbe_set_lan_id_multi_port_pcie (bus->instance_id from uninitialized stack u16 on read failure); ixgbe_setup_fc_generic (failed copper PHY read leaves reg_cu=0 which is then WRITTEN BACK to IXGBE_MDIO_AUTO_NEG_ADVT, silently zeroing all non-FC advertisement bits - link renegotiation breakage); ixgbe_fc_autoneg_copper (failed reads silently degrade flow-control negotiation); ixgbe_get_device_caps_generic (start_hw branches on uninitialized stack device_caps to decide need_crosstalk_fix); clear_hw_cntrs (benign). Upstream-identical vendored code (diff-verified) - decisions only, no userspace memory disclosure. Hardening in vendored Intel shared code (fix owner: upstream), matching DF-3643.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3671 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.4 KB | β raw | |
| VERDICT.md | β | 2.7 KB | β raw | |
| fix.diff | β | 2.4 KB | view raw | |
| build_baseline.log | β | 15.8 KB | view raw | |
| build_patched.log | β | 15.8 KB | view raw | |
| env.txt | β | 1.0 KB | view raw | |
| manifest.json | β | 667 B | view raw | |
| verdict.json | β | 2.5 KB | view raw |
DF-3671 β ixgbe_common.c: unchecked PHY/EEPMD read returns feed config decisions from uninitialized/zeroed state
File: sys/dev/netif/ix/ixgbe_common.c Β· Severity: Info (hardening; DF-3643 parity) Β· Class: error-handling discipline
Sites (all upstream-identical vendored shared code; no divergence found)
ixgbe_clear_hw_cntrs_genericixgbe_common.c:621-628 β fourhw->phy.ops.read_reg(..., &i)calls with discarded return values (X540/ X550 path). On failure nothing is decided from them (results unused), so impact is nil here; included for completeness.ixgbe_set_lan_id_multi_port_pcie:1095 βhw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4)unchecked; on failureee_ctrl_4is an uninitialized stack u16 used to derivebus->instance_id(CS4227 MAC instance selection) β config from garbage.ixgbe_setup_fc_generic:278-279 β copper path reads the PHY AN advertisement with the return discarded;reg_custays 0 and is then written back toIXGBE_MDIO_AUTO_NEG_ADVTat :375-376 after OR-ing in pause bits β a failed read turns into a PHY register clobber that silently drops all non-FC advertisement bits (link renegotiation breakage).ixgbe_fc_autoneg_copper:3083-3088 β two unchecked PHY reads whose (zero-initialized) results feedixgbe_negotiate_fc; zero inputs happen to be rejected there (!(adv_reg)check at 2953), so failure degrades tofc_noneinstead of an explicit error β silent misconfiguration.ixgbe_get_device_caps_generic:4438 β unchecked EEPROM read; the callerixgbe_start_hw_generic(:397/:430-431) passes the address of an uninitialized stack u16 and then testsdevice_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WRβ the crosstalk-fix decision (hw->need_crosstalk_fix) is made from uninitialized kernel stack memory.
No path returns these values to userspace, so this is a correctness/hardening defect, not a leak β same classification as DF-3643 (Info).
PoC / verification
Hardware-gated (PHY/EEPROM read failures need a malfunctioning or malicious
NIC/PHY). No runnable PoC; guest has no ixgbe device (env.txt).
fix.diff checks all five return values (device_caps zero-initialized +
error propagation, PHY reads bailing with IXGBE_ERR_PHY, skipped write-back
on failed read) and compile-validates on the guest's md5-identical source
(build_patched.log, -Werror clean).
DF-3671 β VERDICT
Status: inconclusive (runtime) / source-level certain. Severity Info: no kernel-memory disclosure, decisions-only uninitialized/garbage inputs. DF-3643 parity for the ixgbe HAL.
Analysis
The e1000_ich8lan pass-1 lesson (DF-3643: "Unchecked PHY-read return values: EEE decisions and PHY write-backs derived from uninitialized kernel stack") applies verbatim to five clusters in the ixgbe shared code; none of them propagates the read status:
| Site | Discarded return | Downstream use |
|---|---|---|
| ixgbe_common.c:621-628 | 4Γ phy.ops.read_reg(...,&i) |
none (counter clear) β benign |
| ixgbe_common.c:1095 | eeprom.ops.read(EE_CTRL_4, &ee_ctrl_4) |
bus->instance_id from uninit stack u16 |
| ixgbe_common.c:278-279 | phy.ops.read_reg(AN_ADVT, ®_cu) |
**write-back at :375-376 clobbers PHY advertisement with 0 |
| ixgbe_common.c:3083-3088 | 2Γ phy.ops.read_reg |
ixgbe_negotiate_fc inputs; 0 inputs silently degrade to ixgbe_fc_none |
| ixgbe_common.c:4438 | eeprom.ops.read(DEVICE_CAPS, device_caps) |
ixgbe_start_hw_generic (:397, :430-431) branches on uninitialized stack for need_crosstalk_fix |
Reachability: all execute during ix_start_hw/ix_setup_fc/ix_init β i.e.,
attach and every interface init on real ixgbe hardware. The reads fail when
the PHY/MDIO bus is wedged, during overtemp resets, or under a hostile PHY β
precisely the states where making config decisions from garbage compounds the
fault.
Impact ceiling: wrong flow-control negotiation, broken link advertisement (site 3 actively corrupts PHY state), wrong crosstalk-fix enablement. No userspace-visible memory disclosure β Info, matching DF-3643.
Upstream fidelity
Function-level diffs against FreeBSD head shared code
(ixgbe_fc_autoneg_copper, ixgbe_setup_fc_generic) came back IDENTICAL for
these sites β FreeBSD carries the same pattern; this is vendored-code
divergence logging (fix owner: Intel shared code), filed for completeness and
for the local hardening patch.
Verification performed
Source walk only + fix compile validation (fix.diff adds return-value
checks; build_patched.log -Werror clean on the guest's md5-identical
/usr/src). Runtime reproduction requires a failing PHY on real hardware β
absent on this guest (env.txt). Guest source restored; guest left clean.
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_testableCompile-validated only; runtime validation needs hardware.
build_baseline.log / build_patched.log (-Werror clean with fix).
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (site table with path:line); build_patched.log; env.txt
PoC changes
New pass-2 finding, no seed.
Verified recommended fix
Check every phy.ops/eeprom.ops read return; zero-init *device_caps; skip the PHY write-back when the preceding read failed (fix.diff).
Verdict
Source-level certain, Info-class (DF-3643 parity): five clusters in ixgbe_common.c discard PHY/EEPROM read return values and act on the (uninitialized or zeroed) outputs β ixgbe_common.c:621-628 (benign), :1095 (instance_id from uninit stack u16), :278-279+375-376 (failed PHY read written back, clobbering the PHY AN advertisement), :3083-3088 (FC negotiation silently degrades to fc_none on failed reads), :4438 + consumer ixgbe_start_hw_generic :397/:430-431 (need_crosstalk_fix decided from uninitialized stack). No kernel-memory disclosure to userspace; decisions only. Upstream FreeBSD shared code is IDENTICAL at these sites (diff verified) β vendored-code issue, filed for hardening. Hardware-gated; guest has no ixgbe device (env.txt). fix.diff checks all five returns; compile-validated -Werror-clean on md5-identical guest source.
No comments yet.