qsphy_attach 'no media present' branch skips mii_phy_add_media, so miibus_mediainit calls ifmedia_set on an EMPTY media list β panic("ifmedia_set") at attach (5th leaf of the DF-4930/4957/4981/5003 family, hub DF-5001)
Summary
Same family shape; qsphy sets MIIF_NOISOLATE so the generic IFM_NONE fallback is gated off - the leaf must add it itself (like truephy DF-5003). REPRODUCED on stock guest: synthetic QS6612-ID MII KLD -> 'no media present' -> panic: ifmedia_set, guest down. Explicit-IFM_NONE leaf fix (+ DF-5001 hub guard as primary).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5053 Β· 17 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.6 KB | β raw | |
| VERDICT.md | β | 5.1 KB | β raw | |
| qsmedia.c | β | 9.2 KB | view raw | |
| Makefile | β | 152 B | β download | |
| build.sh | β | 128 B | view raw | |
| run.sh | β | 193 B | view raw | |
| run_fix.sh | β | 608 B | view raw | |
| build.log | β | 883 B | view raw | |
| run.log | β | 954 B | view raw | |
| run.2.log | β | 424 B | view raw | |
| run.3.log | β | 393 B | view raw | |
| panic.txt | β | 849 B | view raw | |
| kernel_build.log | β | 1.4 KB | view raw | |
| env.txt | β | 287 B | view raw | |
| fix.diff | β | 893 B | view raw | |
| manifest.json | β | 2.1 KB | view raw | |
| verdict.json | β | 5.5 KB | view raw |
DF-5053 β qsphy_attach 'no media present' branch β panic("ifmedia_set") at attach (5th leaf of the DF-4930 family)
What
qsphy_attach() (sys/dev/netif/mii_layer/qsphy.c:166-174) reads BMSR
once, after qsphy_reset(sc) (qsphy.c:162 β mii_phy_reset writes
BMCR_RESET, mii_physubr.c:191); if the media capability bits are clear it
prints "no media present" (qsphy.c:171) and skips
mii_phy_add_media(), then still calls MIIBUS_MEDIAINIT (qsphy.c:174)
β miibus_mediainit() (mii.c:227-245) walks an EMPTY ifm_list and
terminates in ifmedia_set(&mii->mii_media, 0) (mii.c:244) β DragonFly
panic("ifmedia_set") (sys/net/if_media.c). Family: atphy DF-4930,
ciphy DF-4957, jmphy DF-4981, truephy DF-5003; hub fix belongs to
DF-5001. Note mii_phy_add_media's own IFM_NONE fallback is unavailable
here β it is gated on MIIF_NOISOLATE being clear (mii_physubr.c:230)
and qsphy always sets MIIF_NOISOLATE (qsphy.c:160).
Reproduce (on the QEMU guest)
# build (guest): sh build.sh # make SYSDIR=/usr/src/sys -> qsmedia.ko # baseline run: sh run.sh # kldload -> panic; grab vm.sh log # fixcheck: sh run_fix.sh # (after reset) mechanism replay # patched kernel: apply fix.diff, make nativekernel+installkernel, # reboot, kldload again -> no panic (run.3.log)
qsmedia.ko is a synthetic MII MAC controller presenting a QS6612
(PHYIDR1=0x0181 PHYIDR2=0x4401 β OUI 0x006051/model 0, miidevs:66,241)
whose BMSR loses its media bits across the reset the driver itself
issues β the faulty/flaky-PHY precondition. The REAL qsphy driver probes
and attaches on the synthetic bus.
Expected output
Baseline (serial console, panic.txt / run.log):
qsmedia0: <synthetic single-PHY MII controller (DF-5053)> on motherboard qsmedia: probing MII bus (QS6612 id1=0x0181 id2=0x4401, pre-reset BMSR=0x7808) miibus0: <MII bus> on qsmedia0 qsphy0: <QS6612 10/100 media interface> on miibus0 qsphy0: no media present ifmedia_set: no match for 0x0/0xfffffff panic: ifmedia_set Trace: ifmedia_set() <- qsphy_attach() <- device_doattach() <- bus_generic_attach() <- miibus_attach()
Patched kernel (run.3.log): same kldload, qsphy0: no media present,
attach completes, NO panic, clean kldunload.
Severity rationale
Low: attach/boot-time kernel DoS requiring a PHY that answers the ID probe but reports no media capabilities after reset (faulty hardware or MDIO-in-the-loop). No unprivileged userland path drives the bus into this state. The sink itself is proven on the stock kernel with a real qsphy driver in the backtrace.
DF-5053 β VERDICT
Status: reproduced (panic), fix validated (behavioral, patched kernel). Impact: kernel DoS at attach (Low). Confidence: certain.
The bug (path:line)
qsphy.c:166βsc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;read afterqsphy_reset(sc)(qsphy.c:162) which writes BMCR_RESET (mii_physubr.c:187-191).qsphy.c:168-171βif (sc->mii_capabilities & BMSR_MEDIAMASK) mii_phy_add_media(sc); else kprintf("no media present");β the else branch adds NOTHING tomii->mii_media.qsphy.c:174βMIIBUS_MEDIAINIT(sc->mii_dev)βmiibus_mediainit(mii.c:227-245): parent adds nothing,ifm_liststays EMPTY, the walk (mii.c:238-243) never runs,mediastays 0 (mii.c:232), andifmedia_set(&mii->mii_media, 0)(mii.c:244) executespanic("ifmedia_set")(if_media.c).- 5th leaf of the atphy DF-4930 / ciphy DF-4957 / jmphy DF-4981 /
truephy DF-5003 family; hub = DF-5001 (mii.c). qsphy-specific nuance:
the generic
mii_phy_add_mediaIFM_NONE fallback is gated on MIIF_NOISOLATE being CLEAR (mii_physubr.c:230-232) and qsphy always sets MIIF_NOISOLATE (qsphy.c:160), so the leaf fix must add the fallback entry itself (exactly like truephy DF-5003).
How it was reproduced
Synthetic single-PHY MII controller KLD (qsmedia.c, fakemic/DF-5009
machinery): PHYIDR1/2 = 0x0181/0x4401 (MII_OUI()=0x6051 QUALSEMI,
MII_MODEL()=0 QS6612, mii.h:109-111), pre-reset BMSR = 0x7808 (passes
miibus_no_phy, mii.c:113-115), and any BMCR write with BMCR_RESET
latches "hosed" β later BMSR reads return 0. That is precisely the
hardware state the family documents (a PHY that answers probe but loses
media capabilities across reset).
Stock kernel (run.log / panic.txt, serial console):
qsphy0: <QS6612 10/100 media interface> on miibus0 qsphy0: no media present ifmedia_set: no match for 0x0/0xfffffff panic: ifmedia_set ifmedia_set() at ifmedia_set+0x53 qsphy_attach() at qsphy_attach+0x159 device_doattach() ... bus_generic_attach() ... miibus_attach()
The REAL qsphy driver is in the backtrace; ssh died mid-kldload;
vm.sh status β down. Deterministic (the attach path is single-shot).
Fix validation (fix_status: fixed)
fix.diff(leaf-level, mirrors DF-5003's approved shape): the no-media branch addsifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), MII_MEDIA_NONE, NULL);before the MIIBUS_MEDIAINIT. Applies clean (patch -p1Hunk #1 succeeded).- Mechanism replay on a live stock guest (run.2.log, DF-5001's
run_fix.sh pattern): the fixed attach shape + verbatim hub walk
survives with
ifm_curnon-NULL (media=0x22 = IFM_ETHER|IFM_NONE) β the exact invariant that keeps every*_service()'sife->ifm_cur->ifm_mediaentry dereference safe. - Full behavioral validation (kernel_build.log excerpt + run.3.log):
fix.diff applied to guest /usr/src,
make -j6 nativekernel KERNCONF=X86_64_GENERICRC=0 (qsphy.c compiled under the full -Werror kernel flag set), installkernel RC=0, reboot into kernel #1 (Sat Sep 26 16:13:05 UTC 2026), and the exact same kldload trigger now completes:qsphy0: no media present, no panic, miibus attaches, clean kldunload. Sources reverted, md5 back to pristine (6c17ac33ff09cf4e26e4f5131b6adf7a), guest reset to the with-src snapshot.
Reachability / ceiling (honest)
Boot/attach-time DoS only. Requires the driver to attach against a PHY that matched the QS6612 ID yet reports zero media capability bits after the driver's reset β faulty silicon, power-transition flake, or MDIO-in-the-loop (e.g. malicious USB/emulated NIC servicing MDIO in software, if such a parent driver existed). No unprivileged syscall reaches the attach path; no memory corruption (the sink is a deliberate panic in ifmedia_set). Ceiling: reboot-loop/DoS on affected hardware.
Also checked on this file (pass-2 negatives)
- service entry (qsphy.c:188): the CORRECT guard form
(
if (IFM_INST(ife->ifm_media) != sc->mii_inst)), not the DF-1973/ DF-5009 KKASSERT β no sibling-PHY INVARIANTS panic here. - the guard's isolate write (qsphy.c:190-191) ignores the driver's own MIIF_NOISOLATE (qsphy.c:160) β inherited NetBSD functional nit (link-loss on multi-PHY buses, no memory-safety impact); not filed.
- status decode default β IFM_NONE (qsphy.c:289-292): safe.
ifm_cur->ifm_mediaat qsphy.c:295 is the family-wide post-attach shape (ifm_cur guaranteed by successful attach); not qsphy-specific. - reset waits live in
mii_phy_reset(mii_physubr.c:201-209): 500us DELAY + bounded 100x1ms poll β correct;MII_QSPHY_IMASKwrite is a constant clause-22 index (0x1e, qsphyreg.h:62) β no OOB. - probe sentinel: qsphys[] NULL-terminated (qsphy.c:111);
mii_phy_matchstops on mpd_name==NULL (mii_physubr.c:555-563) β 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
fixedfixed: fix.diff applied to guest /usr/src; make -j6 nativekernel KERNCONF=X86_64_GENERIC RC=0 (qsphy.c compiled -Werror, kernel_build.log); installkernel RC=0; reboot into kernel #1 (Sat Sep 26 16:13:05 UTC 2026); the identical kldload trigger completes WITHOUT panic ('qsphy0: no media present', miibus attaches, clean kldunload β run.3.log) vs stock-kernel panic (run.log/panic.txt). Sources reverted md5-verified (6c17ac33ff09cf4e26e4f5131b6adf7a); guest reset afterwards.
fix.diff; kernel_build.log; run.log (baseline panic); run.2.log (mechanism fixcheck); run.3.log (patched-kernel behavioral run); VERDICT.md
Confirmed kernel references
- sys/dev/netif/mii_layer/qsphy.c:160
- sys/dev/netif/mii_layer/qsphy.c:162
- sys/dev/netif/mii_layer/qsphy.c:166
- sys/dev/netif/mii_layer/qsphy.c:168
- sys/dev/netif/mii_layer/qsphy.c:171
- sys/dev/netif/mii_layer/qsphy.c:174
- sys/dev/netif/mii_layer/mii.c:227
- sys/dev/netif/mii_layer/mii.c:244
- sys/dev/netif/mii_layer/mii.c:105
- sys/dev/netif/mii_layer/mii.h:109
- sys/dev/netif/mii_layer/miidevs:66
- sys/dev/netif/mii_layer/miidevs:241
Detail
Evidence (decisive lines)
panic.txt + run.log (decisive: 'qsphy0: no media present' -> 'panic: ifmedia_set' with qsphy_attach+0x159 in the trace); run.3.log (patched kernel: same kldload survives, KLDLOAD_RC=0, clean detach); run.2.log (fixcheck mechanism, ifm_cur=... media=0x22); kernel_build.log (nativekernel -Werror, qsphy.o compile line); build.log; qsmedia.c; VERDICT.md
PoC changes
Authored fresh (no seed). Adapted DF-5009's fakemic synthetic-MII-bus machinery to a single hosed QS6612: (1) the BMSR-media-lost latch keys on the driver's OWN BMCR_RESET write so the probe (miibus_no_phy, mii.c:113-115) still sees media bits; (2) QS6612 ID constants derived from miidevs OUI 0x006051/model 0 via mii.h:109-111 (PHYIDR1=0x0181, PHYIDR2=0x4401); (3) kenv hw.qsmedia.fixmode gate + hw.qsmedia_fixcheck sysctl (DF-5001's run_fix.sh pattern) so the fixed attach shape can replay on a live guest; (4) -Werror build fix (drop unused qsmedia_dev).
Verified recommended fix
In the no-media branch, add ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), MII_MEDIA_NONE, NULL); before MIIBUS_MEDIAINIT (per-leaf; the hub-level fix belongs to DF-5001).
Verdict
REPRODUCED with the REAL qsphy driver in the backtrace: a synthetic single-PHY MII controller KLD (qsmedia.ko) presents a QS6612 (PHYIDR1=0x0181/PHYIDR2=0x4401 -> OUI 0x6051/model 0) whose BMSR loses its media capability bits across the BMCR_RESET that qsphy_attach itself issues (qsphy.c:162 -> :166); the attach takes the 'no media present' branch (qsphy.c:168-171), skips mii_phy_add_media, and MIIBUS_MEDIAINIT (qsphy.c:174) -> miibus_mediainit walks an EMPTY ifm_list and terminates in ifmedia_set(&mii->mii_media,0) (mii.c:244) -> panic("ifmedia_set") β serial console: 'qsphy0: no media present / ifmedia_set: no match for 0x0/0xfffffff / panic: ifmedia_set', backtrace ifmedia_set <- qsphy_attach <- device_doattach <- bus_generic_attach <- miibus_attach; ssh died, guest down. 5th leaf of the atphy DF-4930 / ciphy DF-4957 / jmphy DF-4981 / truephy DF-5003 family (hub: DF-5001). FIX VALIDATED BEHAVIORALLY: fix.diff (ifmedia_add IFM_NONE fallback in the no-media branch, mirroring DF-5003's leaf fix; mii_phy_add_media's own fallback is unavailable because qsphy always sets MIIF_NOISOLATE, qsphy.c:160 vs mii_physubr.c:230) applied to guest /usr/src, nativekernel -Werror rebuild RC=0 (qsphy.o compiled at kbuild.log:18760), installkernel, reboot into kernel #1, and the EXACT same kldload trigger now completes with NO panic and clean kldunload; mechanism replay on stock guest (run.2.log) additionally shows ifm_cur non-NULL post-fix (the invariant keeping *_service() entry derefs safe). Sources reverted md5-verified pristine; guest reset to the with-src snapshot. Attach/boot-time DoS only: requires a PHY that matches the QS6612 ID probe yet reports zero media capabilities after reset β no unprivileged userland path, no memory corruption (deliberate panic sink).
No comments yet.