β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4930

atphy_attach 'no media present' branch skips mii_phy_add_media, so miibus_mediainit calls ifmedia_set on an EMPTY media list β†’ DragonFly panic("ifmedia_set") at attach

Summary

Zero-capability PHYs skip the only call that installs the IFM_NONE fallback yet still trigger mediainit - DFly's ifmedia_set panics where FreeBSD returns (no parent mediainit hook exists). Boot-time panic on hardware-fault PHYs; the ~20 sibling mii drivers share the branch (family precedent DF-1973/DF-4923). Kernel sink EXECUTED live via a KLD replaying the terminal sequence ('no match for 0x0' -> panic, guest down; fix mechanism validated the same way); end-to-end path not_reproduced (no Attansic PHY on guest). Unconditional-add-media fix + mirror the family.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4930 Β· 12 files
FileTypeDescriptionSize
uafsink.c β€” 3.6 KB view raw
fixcheck.snippet.c β€” 1.2 KB view raw
Makefile β€” 54 B ↓ download
build.sh β€” 111 B view raw
run.sh β€” 148 B view raw
build.log β€” 5.8 KB view raw
run.log β€” 107 B view raw
panic.txt β€” 1.2 KB view raw
fix.diff β€” 696 B view raw
env.txt β€” 814 B view raw
VERDICT.md β€” 3.5 KB ↓ raw
verdict.json β€” 3.2 KB view raw
VERDICT.md
↓ download raw

DF-4930 VERDICT β€” atphy no-media attach β†’ panic("ifmedia_set")

Status: NOT REPRODUCED end-to-end (hardware absent on guest); kernel-side sink PROVEN to panic on this exact kernel; fix mechanism validated.

Root cause (source trace)

  • atphy_attach (sys/dev/netif/mii_layer/atphy.c:135-144): if the PHY's BMSR reports no 10/100 media bits and EXTSR no gigabit bits, the driver prints "no media present" and skips mii_phy_add_media β€” the only routine that would have installed the IFM_NONE fallback entry (mii_physubr.c mii_phy_add_media: if ((sc->mii_flags & MIIF_NOISOLATE) == 0) ADD(IFM_ETHER|IFM_NONE, ...)).
  • atphy.c:149 still calls MIIBUS_MEDIAINIT(sc->mii_dev) β†’ miibus_mediainit (sys/dev/netif/mii_layer/mii.c:229-246), which walks the (now EMPTY) ifm_list, leaves media = 0, and calls ifmedia_set(&mii->mii_media, 0).
  • DragonFly's ifmedia_set (sys/net/if_media.c) has NO no-match fallback: ifmedia_match returns NULL on the empty list β†’ kprintf("ifmedia_set: no match ...") β†’ panic("ifmedia_set"). (FreeBSD's version prints and returns; the panic is a DragonFly-specific divergence.)
  • Neither parent driver (age, ale) implements a miibus_mediainit hook that could add fallback media (grep: no MEDIAINIT in if_age.c/if_ale.c).
  • Secondary effect of the same branch: had the boot survived, atphy_service dereferences mii->mii_media.ifm_cur (atphy.c:156β†’164, 224) which would be NULL; the attach-time panic preempts this.

Precondition: an Attansic/Atheros F1/F1_7/F2 PHY whose ID registers match (so atphy attaches) but whose BMSR/EXTSR report zero media capability β€” a broken/partially-fried PHY or flaky MDIO. Not attacker-craftable in software; it is a hardware-fault boot/attach-time panic (auto-attach at boot or kldload). Same family and severity class as DF-1973 (mlphy KKASSERT) and DF-4923 (tlphy NULL-deref), and the "no media present" branch exists in ~20 sibling PHY drivers β€” the fix belongs in each driver's attach (this pack fixes atphy; siblings should get the same one-liner).

Verification on the guest

No Attansic PHY hardware exists under QEMU and PHY register behavior cannot be emulated, so the atphy path itself could not be exercised (honest not_reproduced). The kernel-side sink WAS executed with the real kernel functions via the uafsink KLD (run.sh β†’ sysctl hw.uafsink_fire=1):

ifmedia_set: no match for 0x0/0xffffffff
panic: ifmedia_set
ifmedia_set() at ifmedia_set+0x53
uafsink_fire() at uafsink_fire+0x8e ...

Guest down (see panic.txt). This is byte-for-byte the terminal behavior the atphy chain would produce.

Fix

fix.diff (atphy.c): call mii_phy_add_media(sc) unconditionally after the "no media present" print (restores the FreeBSD parent behavior; with zero capabilities it adds exactly the IFM_NONE fallback entry). Mechanism validated on the guest with the real kernel functions (sysctl hw.uafsink_fixcheck=1): with the fallback entry present, ifmedia_set(IFM_ETHER|IFM_NONE) finds its match, does not panic, and leaves ifm_cur non-NULL (protecting atphy_service). The atphy.c edit itself was not exercised end-to-end (no PHY hardware) β€” fix_status not_testable with the mechanism demonstrated.

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_testable
baseline no→ patch + rebuild →patched clean

fix.diff (atphy.c: call mii_phy_add_media unconditionally; with zero capabilities it installs the IFM_NONE fallback entry) could not be exercised end-to-end (no PHY hardware). Its operative mechanism WAS validated on the guest with the real kernel functions: with the fallback entry present, the identical ifmedia_set sequence survives and leaves ifm_cur non-NULL (hw.uafsink_fixcheck=1, see build.log/run transcript in VERDICT.md).

VERDICT.md 'Fix' section; fix.diff; uafsink.c fixcheck sysctl output ('survived; ifm_cur=0xfffff8008d6c11e0')
↓ fix.diffper-fix-DF-4930

Confirmed kernel references

Detail

Evidence (decisive lines)

panic.txt (sink panic: 'ifmedia_set: no match for 0x0/0xffffffff' -> panic, full trace), run.log (rc=124, guest down), run.sh (exact replay of mii.c:229-246 with empty list), build.log, VERDICT.md (atphy.c:135-149 -> mii.c:229-246 -> sys/net/if_media.c trace)

PoC changes

PoC authored fresh (no seed): uafsink KLD replaying the sink; grew a fixcheck sysctl after the first build (missing sys/conf.h include for DEV_MODULE fixed).

Verified recommended fix

atphy_attach: call mii_phy_add_media() unconditionally so the IFM_NONE fallback entry always exists (see fix.diff); mirror in sibling mii drivers or make miibus_mediainit tolerate an empty list.

Verdict

NOT REPRODUCED end-to-end: the trigger requires Attansic/Atheros F1-family PHY hardware whose BMSR/EXTSR report zero media capability while its ID registers still match, and no such PHY exists on the QEMU guest (PHY 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 atphy_attach's no-media branch at atphy.c:140-149 leads to via mii.c:229-246) yields panic("ifmedia_set") with trace ifmedia_set<-uafsink_fire<-sysctl and kills the guest (panic.txt). DragonFly's ifmedia_set panics on no-match where FreeBSD returns. The finding is therefore certain as a code path and likely as a field event (hardware-fault precondition), severity Low (boot/attach-time DoS, no user-controlled trigger).