# DF-4981 VERDICT — jmphy "no media present" → empty media list → panic("ifmedia_set") at attach

**File:** sys/dev/netif/mii_layer/jmphy.c:124-129 (+ :131)
**Family:** DF-4930 (atphy), DF-4957 (ciphy) — identical construct, identical
sink. This pack independently re-proves the sink on the current kernel.

## Reproduced?

**NOT reproduced end-to-end; the kernel-side sink is PROVEN on this exact
kernel** (verbatim method, same as the family precedent):

The full trigger requires a JMicron JMP211/JMP202 PHY, behind a jme(4) NIC,
whose ID registers still match miidevs (oui JMICRON 0x001b8c, models 0x21/0x22
— miidevs:227-228) while `PHY_READ(sc, MII_BMSR)` (jmphy.c:119) returns zero
media bits and `MII_EXTSR` (jmphy.c:120-121) contributes none — e.g. a
stuck-reset/powered-down PHY, or jme's SMI read timing out, which returns 0
(if_jme.c:303-308). No such PHY exists or is emulatable on the QEMU guest
(env.txt), so `jmphy_attach` itself cannot be driven into the branch here.

What WAS executed on the guest, using the real kernel `ifmedia_*` functions,
is the exact kernel-side tail of the chain — the state `miibus_mediainit`
is left in when jmphy's no-media branch skips `mii_phy_add_media()`:

1. `jmphy_attach` (jmphy.c:119-121): capabilities/extcapabilities both have
   zero media bits → jmphy.c:124-127 prints "no media present" and SKIPS
   `mii_phy_add_media(sc)` → **the `mii->mii_media.ifm_list` stays EMPTY**.
2. jmphy.c:131 `MIIBUS_MEDIAINIT(sc->mii_dev)` → `miibus_mediainit`
   (mii.c:228-246): the parent poke `MIIBUS_MEDIAINIT(parent)` (mii.c:235) is
   a no-op for jme — jme implements only miibus_{readreg,writereg,statchg}
   (if_jme.c:218-220) and attaches the bus via `mii_phy_probe`
   (if_jme.c:1028) — so nothing else populates the list.
3. The list walk (mii.c:236-240) finds nothing; `media` stays 0;
   mii.c:244 calls `ifmedia_set(&mii->mii_media, 0)`.
4. `ifmedia_set` (sys/net/if_media.c:168-175): `ifmedia_match()` on an empty
   list returns NULL → `panic("ifmedia_set")`.

**Observed (run.log + panic.txt, from the serial console):**

```
jmsink: loaded; sysctl hw.jmsink_fire=1 to panic
jmsink: ifmedia_init (empty list)
jmsink: list walk done, media=0x0; calling ifmedia_set (mii.c:244)
ifmedia_set: no match for 0x0/0xffffffff
panic: ifmedia_set
cpuid = 1
Trace ... ifmedia_set() at ifmedia_set+0x53
        jmsink_fire() at jmsink_fire+0x8e
        sysctl_root ... userland_sysctl ... sys___sysctl
Debugger("panic")
```

The guest died mid-sysctl (ssh never returned; `vm.sh status` ⇒ down) — a
kernel-triggered fatal event at the exact sink the finding cites, on the
unpatched kernel. Note this is DragonFly-specific: FreeBSD's `ifmedia_set`
prints a warning and *returns* on no-match; DragonFly's panics
(sys/net/if_media.c:172-175).

## Impact ceiling

Boot/attach-time kernel panic (DoS) on jme(4)+JMP211/JMP202 hardware whose
PHY misreports zero media capability. No unprivileged-user trigger; requires
a hardware fault state (BMSR=0 with matching ID regs). Memory-safety impact:
none — the panic is an intentional `panic()` guard, reached via a logic gap.
Severity Low, consistent with family precedent DF-1973/DF-4923/DF-4930/DF-4957.

## Fix validation

`fix.diff` (authored after verification, never applied to the read-only
`sys/` tree) makes `jmphy_attach` call `mii_phy_add_media()` unconditionally.
With zero capabilities that installs exactly the IFM_NONE fallback entry
(mii_physubr.c:235-237 — `if ((sc->mii_flags & MIIF_NOISOLATE) == 0) ADD(
IFM_ETHER|IFM_NONE ...)`; jmphy never sets MIIF_NOISOLATE and jme passes no
such flag through `mii_phy_probe`), so `miibus_mediainit`'s `ifmedia_set()`
finds a match and survives, and `ifm_cur` is non-NULL for later
`jmphy_service()` (jmphy.c:138 dereferences `mii->mii_media.ifm_cur`).

**Fixcheck executed on the guest after `vm.sh reset with-src` (run.2.log):**

```
jmsink-fix: ifmedia_init + IFM_NONE fallback entry (the fixed jmphy path)
jmsink-fix: calling ifmedia_set(IFM_ETHER|IFM_NONE) -- must NOT panic
jmsink-fix: survived; ifm_cur=0xfffff8008d481c80 (non-NULL keeps jmphy_service safe)
```

End-to-end kernel build with the patch was not performed: the bug is a
one-line call-site change whose operative mechanism was validated with the
real kernel functions on this kernel; a full jme+jmphy attach cannot exist on
this guest. fix_status: not_testable (as persisted for the family), with the
mechanism proven as above.

Guest was reset (`vm.sh reset with-src`) after both runs; left clean/up.

## 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.
