ciphy_attach 'no media present' branch skips all media setup β miibus_mediainit calls ifmedia_set on an EMPTY list β panic("ifmedia_set") at attach on zero-capability PHYs
Summary
The DF-4930 (atphy) family shape with a CRITICAL DIVERGENCE: ciphy always sets MIIF_NOISOLATE, which GATES mii_phy_add_media's IFM_NONE fallback - the atphy one-liner fix is a no-op here; ciphy needs an explicit IFM_NONE entry (or framework hardening of miibus_mediainit for the ~20 siblings). Sink PROVEN live (panic.txt: ifmedia_set no-match -> guest down; the fixed path survives with non-NULL ifm_cur); end-to-end hw-gated (no Cicada PHY). The DF-4930 sibling.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4957 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| ciphysink.c | β | 3.8 KB | view raw | |
| Makefile | β | 58 B | β download | |
| build.sh | β | 98 B | view raw | |
| run.sh | β | 90 B | view raw | |
| build.log | β | 617 B | view raw | |
| run.log | β | 186 B | view raw | |
| panic.txt | β | 1.3 KB | view raw | |
| env.txt | β | 188 B | view raw | |
| fix.diff | β | 932 B | view raw | |
| VERDICT.md | β | 4.3 KB | β raw | |
| verdict.json | β | 3.9 KB | view raw |
DF-4957 VERDICT β ciphy no-media attach β panic("ifmedia_set")
Status: NOT REPRODUCED end-to-end (no Cicada/Vitesse PHY hardware on
the guest; PHY registers are not emulatable). The kernel-side sink of
the chain is PROVEN live on this exact kernel β replaying
miibus_mediainit's terminal ifmedia_set() on an EMPTY media list (what
ciphy_attach's no-media branch at ciphy.c:142-147 leads to via
mii.c:229-246) yields ifmedia_set: no match for 0x0/0xffffffff β
panic("ifmedia_set") and kills the guest (panic.txt, full trace).
Fix mechanism validated live the same boot.
Root cause (source trace)
ciphy_attach(sys/dev/netif/mii_layer/ciphy.c:142-147): if the PHY's BMSR reports no 10/100 media bits AND EXTSR no gigabit bits, the driver prints "no media present" and skipsmii_phy_add_mediaβ the only routine that would populate the miibus ifmedia list.- ciphy.c:149 still calls
MIIBUS_MEDIAINIT(sc->mii_dev)βmiibus_mediainit(sys/dev/netif/mii_layer/mii.c:229-246): walks the now-EMPTYifm_list,mediastays 0, callsifmedia_set(&mii->mii_media, 0). - DragonFly's
ifmedia_set(sys/net/if_media.c) has no no-match fallback:ifmedia_matchreturns NULL on the empty list βkprintf("ifmedia_set: no match ...")βpanic("ifmedia_set"). (FreeBSD's ifmedia_set prints and returns; the panic is a DragonFly divergence.) - No parent of a CICADA/VITESSE PHY implements the
miibus_mediainithook (in-tree hooks exist only in if_xl/if_tx/if_dc; realistic ciphy parents are nfe/sk/vge β none hook it). - Secondary effect of the same branch: had the boot survived,
ciphy_servicedereferencesmii->mii_media.ifm_cur(ciphy.c:156, 164, 255) which would be NULL.
Why the atphy (DF-4930) one-line fix does NOT apply here
ciphy sets sc->mii_flags |= MIIF_NOISOLATE at ciphy.c:132 BEFORE the
media branch. mii_phy_add_media's IFM_NONE fallback entry is added
only if ((sc->mii_flags & MIIF_NOISOLATE) == 0)
(mii_physubr.c:230-232). Therefore "just call mii_phy_add_media()
unconditionally" (the atphy fix) adds NOTHING for ciphy: the list stays
empty and the panic remains. Every MIIF_NOISOLATE mii driver with this
branch (ciphy, rgephy set NOISOLATE too, β¦) needs an explicit fallback
entry or the shared miibus_mediainit must tolerate an empty list.
Verification on the guest
No CS8201/VSC8601 PHY exists under QEMU and MDIO register behavior
cannot be emulated, so the ciphy_attach path itself could not be
exercised (honest not_reproduced). The kernel-side sink WAS executed
with the real kernel functions via the ciphysink KLD (adapted from the
DF-4930 pack; run.sh):
sysctl hw.ciphysink_fixcheck=1β replays the FIXED ciphy path (ifmedia_init + explicit IFM_NONE entry + ifmedia_set): survived,ifm_cur=0xfffff8004f102640(non-NULL, which also protects ciphy_service's deref).sysctl hw.ciphysink_fire=1β replays the STOCK ciphy path (empty-list ifmedia_set):
ifmedia_set: no match for 0x0/0xffffffff
panic: ifmedia_set
ifmedia_set() at ifmedia_set+0x53
ciphysink_fire() at ciphysink_fire+0x8e
sysctl_root ... userland_sysctl ... sys___sysctl
Debugger("panic") ; guest down
This is byte-for-byte the terminal behavior the ciphy chain produces on a zero-media Cicada PHY at attach (boot-time or kldload).
Fix
fix.diff (ciphy.c): in the no-media branch, after the "no media
present" print, add an explicit
ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0,
sc->mii_inst), MII_MEDIA_NONE, NULL) β miibus_mediainit's ifmedia_set
then finds its match, no panic, and ifm_cur is non-NULL for
ciphy_service. Mechanism validated live (fixcheck above). The
framework-level alternative (make miibus_mediainit skip/tolerate an
empty list) would fix all ~20 sibling drivers at once and is the better
long-term fix; the per-driver diff keeps this pack self-contained.
Guest was reset with-src after the panic capture (boot.log rotated); source of the panic text: serial console capture in panic.txt.
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 (ciphy.c: add an explicit ifmedia_add(IFM_ETHER|IFM_NONE) in the no-media branch -- NOT the atphy-shaped unconditional mii_phy_add_media call, which is a no-op here because of the MIIF_NOISOLATE gate at mii_physubr.c:230-232) could not be exercised end-to-end (no Cicada PHY hardware). Its operative mechanism WAS validated live on the same boot with the real kernel functions: hw.ciphysink_fixcheck=1 replays ifmedia_init + the explicit IFM_NONE entry + ifmedia_set and survives with ifm_cur non-NULL (panic.txt preamble), while the unfixed sequence panics two sysctls later.
panic.txt (fixcheck 'survived; ifm_cur=0xfffff8004f102640' followed by the sink panic); fix.diff; VERDICT.md 'Fix' section
Confirmed kernel references
Detail
Evidence (decisive lines)
panic.txt (sink panic: 'ifmedia_set: no match for 0x0/0xffffffff' -> panic, full trace incl. ciphysink_fire; fixcheck survived with ifm_cur=0xfffff8004f102640 just before), run.log (fixcheck output then connection death on fire), VERDICT.md (ciphy.c:142-149 -> mii.c:229-246 -> if_media.c trace), fix.diff (explicit IFM_NONE fallback entry)
PoC changes
PoC authored fresh (adapted from the DF-4930 uafsink pack): renamed sysctls to hw.ciphysink_fire/fixcheck, updated the replayed chain comments to ciphy.c lines; first build failed on #include
Verified recommended fix
ciphy_attach no-media branch: add explicit ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), MII_MEDIA_NONE, NULL); (see fix.diff); or harden miibus_mediainit for empty lists tree-wide.
Verdict
NOT REPRODUCED end-to-end: the trigger requires CS8201/CS8201A/CS8201B/VSC8601 PHY hardware (ciphys[] table, ciphy.c:72-80) whose ID registers match while BMSR/EXTSR report zero media capability, and no such PHY exists on the QEMU guest (MDIO register behavior is not emulatable). The kernel-side sink of the chain is nonetheless PROVEN on this exact kernel: replaying miibus_mediainit's terminal ifmedia_set() on an EMPTY media list (what ciphy_attach's no-media branch at ciphy.c:142-147 leads to via mii.c:229-246) yields 'ifmedia_set: no match for 0x0/0xffffffff' -> panic("ifmedia_set") with trace ifmedia_set<-ciphysink_fire<-sysctl and kills the guest (panic.txt). DragonFly's ifmedia_set panics on no-match where FreeBSD returns. IMPORTANT divergence from the atphy sibling (DF-4930): ciphy always sets MIIF_NOISOLATE (ciphy.c:132) and mii_phy_add_media's IFM_NONE fallback is gated on that flag being CLEAR (mii_physubr.c:230-232), so the atphy-shaped unconditional-add fix does NOT work here; fix.diff adds an explicit IFM_NONE entry instead, and that mechanism was validated live (hw.ciphysink_fixcheck=1 survives with non-NULL ifm_cur). Boot/attach-time hardware-fault DoS, no user-controlled trigger; family precedent DF-1973/DF-4923/DF-4930, all Low.
No comments yet.