⬢ DragonFlyBSD Kernel Audit
DF-5384 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/bus/u4b/net/if_aue.c b/sys/bus/u4b/net/if_aue.c
--- a/sys/bus/u4b/net/if_aue.c
+++ b/sys/bus/u4b/net/if_aue.c
@@ -688,7 +688,7 @@
 	    sc, &sc->sc_lock);
 	if (error) {
 		device_printf(dev, "allocating USB transfers failed\n");
-		goto detach;
+		goto detach_usb;
 	}
 
 	ue->ue_sc = sc;
@@ -700,12 +700,21 @@
 	error = uether_ifattach(ue);
 	if (error) {
 		device_printf(dev, "could not attach interface\n");
-		goto detach;
+		goto detach_usb;
 	}
 	return (0);			/* success */
 
-detach:
-	aue_detach(dev);
+detach_usb:
+	/*
+	 * The usb_ether was never attached (or failed halfway): do NOT
+	 * call uether_ifdetach() on it -- with ue_lock still NULL (USB
+	 * transfer setup failure) uether_ifdetach() lockmgr()s through
+	 * the NULL pointer, and after a failed uether_ifattach() the
+	 * embedded ifnet was never if_attach()ed, so ether_ifdetach()
+	 * would corrupt ifindex2ifnet[0] and the global ifnet list.
+	 */
+	usbd_transfer_unsetup(sc->sc_xfer, AUE_N_TRANSFER);
+	lockuninit(&sc->sc_lock);
 	return (ENXIO);			/* failure */
 }
 
diff --git a/sys/bus/u4b/net/usb_ethernet.c b/sys/bus/u4b/net/usb_ethernet.c
--- a/sys/bus/u4b/net/usb_ethernet.c
+++ b/sys/bus/u4b/net/usb_ethernet.c
@@ -269,6 +269,16 @@
 {
 	struct ifnet *ifp;
 
+	/*
+	 * A driver attach() failure may call detach() on a usb_ether that
+	 * was never uether_ifattach()ed: ue_lock is still NULL there and
+	 * the embedded ifnet was never if_attach()ed.  Bail out instead
+	 * of lockmgr()ing through the NULL pointer and tearing down a
+	 * non-existent ifnet.
+	 */
+	if (ue->ue_lock == NULL)
+		return;
+
 	/* wait for any post attach or other command to complete */
 	usb_proc_drain(&ue->ue_tq);