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

acphy_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 (6th leaf of the DF-4930/4957/4981/5003/5053 family; hub DF-5001)

Summary

6th leaf: the no-media branch + MIIF_NOISOLATE (kills the fallback) + the hub's unguarded ifmedia_set. Sink panic re-proven fresh on guest (verbatim hub walk replay, panic.txt); leaf branch not emulatable in QEMU (not_reproduced, family-consistent). Hub-guard fix build+behavior validated.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-5077 Β· 13 files
FileTypeDescriptionSize
miihub.c β€” 5.0 KB view raw
Makefile β€” 73 B ↓ download
build.sh β€” 79 B view raw
run.sh β€” 103 B view raw
run.log β€” 1.1 KB view raw
panic.txt β€” 1.1 KB view raw
fix.diff β€” 894 B view raw
fix_build.log β€” 32.2 KB view raw
env.txt β€” 1.5 KB view raw
VERDICT.md β€” 4.5 KB ↓ raw
README.md β€” 1.7 KB ↓ raw
verdict.json β€” 4.3 KB view raw
manifest.json β€” 1.3 KB view raw

DF-5077 β€” acphy_attach 'no media present' branch β†’ hub panic("ifmedia_set") at attach

File: sys/dev/netif/mii_layer/acphy.c:169-172 (6th leaf of the DF-4930 / DF-4957 / DF-4981 / DF-5003 / DF-5053 empty-media family; hub = DF-5001)

Build (on the guest)

mkdir -p /root/df5077 && cp miihub.c Makefile build.sh run.sh /root/df5077/
sh /root/df5077/build.sh        # make -m /usr/share/mk -> miihub.ko (rc=0)

Run (on the guest)

sh /root/df5077/run.sh
  1. hw.miihub_fixcheck=1 β€” the FIXED hub walk (empty list β†’ add IFM_ETHER|IFM_AUTO β†’ ifmedia_set) must survive with ifm_cur != NULL.
  2. hw.miihub_fire=1 β€” the VERBATIM miibus_mediainit walk (mii.c:238-244) on the EMPTY media list β€” exactly the state produced when acphy_attach takes its 'no media present' branch.

Expected

  • fixcheck: survives, prints ifm_cur=0xfffff8... (non-NULL), rc=0.
  • fire: ifmedia_set: no match for 0x0/0xfffffff then panic: ifmedia_set β€” trace ifmedia_set <- miihub_fire <- sysctl; guest goes down into DDB (panic.txt).

Trigger precondition (why end-to-end is not_reproduced)

Firing the leaf itself requires an Altima AC101/AC101L-family PHY whose ID registers match acphys[] (acphy.c:107-113) while its BMSR reports ZERO media capability at attach time (faulty PHY, or mii_capmask masking the media bits). PHY register behavior is not emulatable in the QEMU guest β€” same class as the family leaves (DF-4930 verdict). The kernel-side sink of the chain is nonetheless proven fresh on this guest (panic.txt), and the family-wide fix (DF-5001 hub guard) is build-validated (fix_build.log, miibus.ko rc=0, 0 errors/0 warnings) and behavior-validated (fixcheck).

VERDICT.md
↓ download raw

DF-5077 VERDICT β€” acphy empty-media leaf (DF-4930 family), sink proven, leaf trigger hardware-gated

Status: not_reproduced (end-to-end), impact none, confidence likely β€” the exact family treatment of DF-4930 (atphy), applied to the 6th leaf.

Root cause (code-certain)

acphy_attach():

  • acphy.c:167 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
  • acphy.c:169 if (sc->mii_capabilities & BMSR_MEDIAMASK)
  • acphy.c:170 mii_phy_add_media(sc);
  • acphy.c:171 else
  • acphy.c:172 kprintf("no media present"); ← zero media β†’ nothing added
  • acphy.c:175 MIIBUS_MEDIAINIT(sc->mii_dev); β†’ miibus_mediainit

aggravated by acphy.c:161 sc->mii_flags |= MIIF_NOISOLATE; β€” the IFM_NONE fallback inside mii_phy_add_media is gated off for MIIF_NOISOLATE drivers (mii_physubr.c:229-232), so even a partial pass adds nothing without real BMSR media bits.

miibus_mediainit (mii.c:228-245) then walks the (empty) ifm_list, media stays 0, and the terminal ifmedia_set(&mii->mii_media, 0) (mii.c:244) hits DragonFly's ifmedia_match()==NULL β†’ panic("ifmedia_set") (sys/net/if_media.c:174) at NIC attach β€” boot/attach-time DoS. Sibling leaves: atphy DF-4930, ciphy DF-4957, jmphy DF-4981, truephy DF-5003, qsphy DF-5053; the hub and the family-wide fix belong to DF-5001 (mii.c empty-list guard).

What was reproduced on the guest (fresh, this run)

  • Sink panic: KLD replaying the verbatim hub walk against an EMPTY media list β€” the exact state acphy's no-media branch leaves β€” panicked the running stock kernel: ifmedia_set: no match for 0x0/0xfffffff β†’ panic: ifmedia_set, trace ifmedia_set <- miihub_fire <- sysctl (panic.txt, guest down in DDB; console session hung mid-sysctl).
  • Fix behavior: hw.miihub_fixcheck=1 (fixed walk: empty β†’ add IFM_ETHER|IFM_AUTO β†’ ifmedia_set) survived with ifm_cur=0xfffff8008d5a10c0 non-NULL β€” the downstream ife->ifm_media deref every mii *_service() performs is then safe (run.log).
  • Fix build: DF-5001's hub-guard diff (this pack's fix.diff) applied to guest /usr/src, make -j4 in sys/dev/netif/mii_layer β†’ miibus.ko rc=0, 0 error:/0 warning: (fix_build.log, 209 lines); sources reverted md5-verified pristine (2f16a4a6...), make clean.

Why the leaf itself cannot fire on this guest

acphys[] matches on PHY ID registers (acphy.c:107-113); the no-media branch additionally needs BMSR media bits == 0 (or fully masked) at attach. QEMU's NIC models do not emulate MII PHY register files. Same verdict class as DF-4930 ("no such PHY exists on the QEMU guest"). A hardware-fault / malicious-PHY precondition is required in the field β€” severity Low, no unprivileged trigger, no memory unsafety.

Negative results (pass-2 depth on this file)

  • No service-entry KASSERT (DF-1973/DF-5009 family does NOT apply): acphy_service (acphy.c:189-196) uses the standard foreign-instance guard (ISO|PDOWN on MEDIACHG only); the miibus dispatch (mii.c:301-360) passes the shared ifm_cur to every child β€” verified harmless for acphy.
  • Vendor register indexes all within the 5-bit MII space (acphyreg.h:37-76: 0x10..0x18 < 0x20) β€” no OOB register index; the LED config (MII_ACPHY_MCTL AC_MCTL_LED_SEL) is never programmed by this driver at all.
  • Status decode (acphy.c:273-283): DIAG speed/duplex bits β†’ IFM constants match acphyreg.h:53-54 β€” no amphy-DF-2101-style transcription error; the forced-media else copying ife->ifm_media wholesale is the upstream shape shared across the family (cosmetic at most).
  • Probe table sentinel MII_PHYDESC_NULL present (acphy.c:112).
  • Reset waits: mii_phy_reset (mii_physubr.c:183-213) has the 500us + 100x1ms settle loop; the added PHY_WRITE(MII_ACPHY_INT, 0) (acphy.c:290) needs no wait; MIIF_NOISOLATE correctly suppresses the post-reset ISO write.
  • No copyin/copyout, no privilege surface, no locks/refcounts to race.

Artifacts

miihub.c (DF-5001's KLD, verbatim β€” it models exactly this leaf's state), panic.txt (fresh sink panic + fixcheck transcript), run.log, fix_build.log (miibus.ko with hub fix), fix.diff (DF-5001 hub guard β€” the family-wide fix covering this leaf), env.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

fixed
baseline reproduced→ patch + rebuild →patched reproduced

Fix validated at behavior + build level on this guest: (a) the fixed hub walk (empty list -> ifmedia_add(IFM_ETHER|IFM_AUTO) -> ifmedia_set) survived the identical empty-list scenario with ifm_cur non-NULL while the verbatim walk panicked the guest (panic.txt); (b) the fix.diff applied clean to guest /usr/src (hunk at :241) and miibus.ko rebuilt rc=0 with 0 errors/0 warnings (fix_build.log); sources reverted md5-verified pristine (2f16a4a6...), make clean. The diff is DF-5001's hub guard β€” the family-wide fix that owns this leaf.

fix_build.log (miibus.ko rc=0, 0 error:/0 warning:); panic.txt (baseline panic vs fixcheck survival in the same session); fix.diff (the guard hunk)
↓ fix.diffper-fix-DF-5077

Confirmed kernel references

Detail

Evidence (decisive lines)

panic.txt (fresh guest panic + fixcheck transcript: ifmedia_set<-miihub_fire<-sysctl); VERDICT.md (root cause acphy.c:169-172 + mii.c:244 + if_media.c:174); run.log (fixcheck survived, ifm_cur=0xfffff8008d5a10c0); fix_build.log (miibus.ko with hub guard, rc=0, 0/0 diagnostics); fix.diff (DF-5001 hub guard, family fix)

PoC changes

miihub.c reused verbatim from DF-5001's pack (it models exactly this leaf's state); only the pack scripts/logs are new. Trigger is DF-5001's hw.miihub_fire / hw.miihub_fixcheck pair.

Verified recommended fix

Family-wide hub guard in miibus_mediainit (mii.c): never call ifmedia_set() on an empty media list β€” add IFM_ETHER|IFM_AUTO and set it (fix.diff = DF-5001's, covering every leaf including acphy).

Verdict

NOT REPRODUCED end-to-end: the trigger requires an Altima AC101/AC101L-family PHY whose ID registers match acphys[] (acphy.c:107-113) while its BMSR reports zero media capability at attach (hardware fault or mii_capmask masking), and PHY register behavior is not emulatable on the QEMU guest β€” the same class as the family leaves (DF-4930 atphy). The kernel-side sink of the chain is nonetheless PROVEN FRESH on this exact guest and kernel: replaying miibus_mediainit's walk (mii.c:238-244) on the EMPTY media list β€” exactly the state acphy_attach's 'no media present' branch (acphy.c:169-172, aggravated by MIIF_NOISOLATE at acphy.c:161 which also disables the mii_physubr.c:230 IFM_NONE fallback) leaves β€” yields 'ifmedia_set: no match for 0x0/0xfffffff' -> panic("ifmedia_set") with trace ifmedia_set<-miihub_fire<-sysctl and kills the guest (panic.txt, captured this run). The fixed hub walk (fix.diff = DF-5001's empty-list guard) survived the identical scenario with ifm_cur non-NULL (service deref safe), and that same fix build-validates: miibus.ko rebuilt rc=0, 0 errors/0 warnings (fix_build.log). 6th leaf of the DF-4930/4957/4981/5003/5053 family; the family-wide fix belongs to hub DF-5001. Attach/boot-time DoS on faulty hardware, no user-controlled trigger, no memory unsafety; severity Low.