miibus device_t UAF race between uether_ifdetach and unprivileged SIOCGIFMEDIA ioctl
| Field | Value |
|---|---|
| ID | DF-1082 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:H |
| CWE | CWE-416 Use After Free |
| File | sys/bus/u4b/net/usb_ethernet.c |
| Lines | 289-294 (detach order), 505-509 (SIOCGIFMEDIA deref) |
| Area | bus/u4b/net (USB Ethernet framework layer) |
| Confidence | likely |
| Discovered | 2026-07-14 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
uether_ifdetach calls device_delete_child(ue->ue_miibus) β which frees the miibus
device_t via kobj_delete (subr_bus.c:1306) β BEFORE calling ether_ifdetach(ifp)
which removes the interface from the global ifnet list. During that window, an
unprivileged SIOCGIFMEDIA ioctl (dispatched without privilege check at if.c:2364)
reaches uether_ioctl, reads the now-dangling ue->ue_miibus pointer (never nulled), and
dereferences freed memory via device_get_softc then ifmedia_ioctl on the freed
mii_data.
Root cause
In uether_ifdetach (usb_ethernet.c:289-294), the ordering is:
device_delete_child(ue->ue_dev, ue->ue_miibus)which callsdevice_detachβkobj_deleteon the miibusdevice_t, freeing it;ether_ifdetach(ifp)which callsif_detachto removeifpfrom the global interface list.
The pointer ue->ue_miibus is never set to NULL after deletion.
In uether_ioctl (usb_ethernet.c:505-509), the SIOCGIFMEDIA / SIOCSIFMEDIA case
reads ue->ue_miibus without holding UE_LOCK:
if (ue->ue_miibus != NULL) {
mii = device_get_softc(ue->ue_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
}
device_get_softc (subr_bus.c:1784) dereferences dev->softc on the freed device_t β
a UAF read β and the returned mii_data pointer is also freed, so ifmedia_ioctl
dereferences freed mii_data.
The ioctl dispatcher in if.c:2364-2373 dispatches SIOCGIFMEDIA with NO
caps_priv_check, so any local user can trigger the read path. The race window spans the
entire duration of device_delete_child (miibus teardown + kobj_delete), which is wider
than a single instruction gap because the miibus detach routine and method dispatch take
time.
Threat model & preconditions
- Attacker position: A local unprivileged user on a system with a USB Ethernet adapter.
Issues
SIOCGIFMEDIA(e.g.ifconfig ue0 media) in a tight loop. - Privileges gained or impact:
- Primary: kernel panic (local DoS / A:H). The freed memory (
M_BUS/kobjzone) could be reclaimed and groomed;device_get_softcreturns an attacker-influencedsoftcpointer, andifmedia_ioctlreads / writes fields in it, potentially enabling controlled kernel memory read (C:L) or, with sophisticated heap grooming of thekobj-freed slab, code execution. - Required config or capabilities: Default kernel with any
u4bEthernet driver. The detach trigger requires physical USB access or root privilege (usbconfig unconfigure/kldunload), which limits practical exploitability to DoS on multi-user systems with physically accessible USB ports. - Reachability: Concurrent
SIOCGIFMEDIAioctl loop (unprivileged) + USB adapter detach (physical unplug or root-driven).
Proof of concept
On a DragonFlyBSD system with a u4b Ethernet adapter (e.g. if_aue) attached as ue0:
- Compile a tight-loop C program that opens an
AF_INETdatagram socket and callsioctl(s, SIOCGIFMEDIA, &ifr)targetingue0in an infinite loop with no delay β this is unprivileged (SIOCGIFMEDIAhas nocaps_priv_check). - Concurrently, physically unplug the USB Ethernet adapter (or, as root, run
usbconfig -u <bus> -a <addr> unconfigureorkldunload if_aue). - With high probability within a few hundred unplug attempts, the ioctl thread dereferences
the freed miibus
device_tduring the window betweendevice_delete_child(usb_ethernet.c:290) andether_ifdetach(usb_ethernet.c:294), causing a kernel panic (NULL deref indevice_get_softcon reclaimed memory, or page fault on freed / unmappedkobjslab).
Build & run
cc -o race_poc race_poc.c ./race_poc ue0 & # unprivileged user, tight ioctl loop # then physically unplug the USB adapter (or sudo usbconfig unconfigure)
Expected output
Kernel panic / system crash. The panic signature will be a page fault in
device_get_softc or ifmedia_ioctl called from uether_ioctl.
For the info-leak variant, capture the ifmr.ifm_active / ifm_current values returned
across many attempts and look for non-deterministic values indicating reads from reclaimed
kernel memory.
Impact
Local DoS (kernel panic) via UAF race between USB Ethernet adapter detach and unprivileged
SIOCGIFMEDIA ioctl loop. Potential info leak of freed kobj slab contents with heap
grooming. The detach trigger requires physical USB access or root, keeping practical
exploitability to DoS. Low severity per "narrow trigger" + "local DoS on concurrent
detach".
Recommended fix
Reorder uether_ifdetach to call ether_ifdetach(ifp) BEFORE
device_delete_child(ue->ue_miibus), so the ifp is removed from the global interface
list (preventing all new ioctls) before the miibus is freed. Additionally null
ue->ue_miibus as defense-in-depth. ether_ifdetach β if_detach does not require the
miibus to be alive (it only calls if_down, ng_ether_detach, bpfdetach, if_detach β
none access miibus), so the reorder is safe.
--- a/sys/bus/u4b/net/usb_ethernet.c
+++ b/sys/bus/u4b/net/usb_ethernet.c
@@ -285,16 +285,18 @@ uether_ifdetach(struct usb_ether *ue)
/* drain any callouts */
usb_callout_drain(&ue->ue_watchdog);
- /* detach miibus */
- if (ue->ue_miibus != NULL) {
- device_delete_child(ue->ue_dev, ue->ue_miibus);
- }
-
/* detach ethernet */
ether_ifdetach(ifp);
+ /* detach miibus β must come AFTER ether_ifdetach so that no
+ * concurrent SIOCGIFMEDIA ioctl can dereference the freed
+ * miibus device_t via ue->ue_miibus (SIOCGIFMEDIA requires
+ * no privilege in the generic ifioctl dispatcher). */
+ if (ue->ue_miibus != NULL) {
+ device_delete_child(ue->ue_dev, ue->ue_miibus);
+ ue->ue_miibus = NULL;
+ }
+
/* free sysctl */
sysctl_ctx_free(&ue->ue_sysctl_ctx);
References
sys/bus/u4b/net/usb_ethernet.c:289-294β detach ordering (miibus freed before ifp removed)sys/bus/u4b/net/usb_ethernet.c:505-509βSIOCGIFMEDIAderef of freedue->ue_miibussys/kern/subr_bus.c:1306βkobj_deletefrees thedevice_tduringdevice_delete_childsys/kern/subr_bus.c:1784βdevice_get_softcderefsdev->softcon freeddevice_tsys/net/if.c:2364βSIOCGIFMEDIAdispatch has nocaps_priv_check- CWE-416 Use After Free
Timeline
- 2026-07-14 Discovered during automated audit.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1082 Β· 3 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | Source-confirmation verdict for DF-1082 | 624 B | β raw |
| fix.diff | suggested-fix | Move ether_ifdetach before miibus delete, NULL ue_miibus | 574 B | view raw |
| ../fix_build.log | build-log | Batch kernel build log (all fixes, rc=0) | 5.6 MB | β download |
DF-1082 Verification Verdict
Severity: Low Impact class: uaf Verification method: Source-only confirmation (HW-gated, not triggerable on QEMU guest)
Verdict: REPRODUCED (source-confirmed)
The bug is confirmed in the audited source at the cited path:line. Triggerable but requires specific driver/config.
Fix: Move ether_ifdetach before miibus delete, NULL ue_miibus
Fix applied and validated in batch kernel build (rc=0, -Werror).
Fix validation
All 41-fix patches batched into single make -j6 nativekernel KERNCONF=X86_64_GENERIC build.
Build result: rc=0, 0 errors (full -Werror clean).
Fix verification
fixedVALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.
VALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
REPRODUCED (source-only): uether_ifdetach frees miibus via device_delete_child BEFORE ether_ifdetach removes ifp from ifnet list; ue->ue_miibus pointer never NULLed. UAF on detach.
Verified recommended fix
REPRODUCED (source-only): uether_ifdetach frees miibus via device_delete_child BEFORE ether_ifdetach removes ifp from ifnet list; ue->ue_miibus pointer never NULLed. UAF on detach.
Verdict
REPRODUCED (source-only): uether_ifdetach frees miibus via device_delete_child BEFORE ether_ifdetach removes ifp from ifnet list; ue->ue_miibus pointer never NULLed. UAF on detach.
No comments yet.