⬢ DragonFlyBSD Kernel Audit
DF-5514 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/bus/u4b/net/if_ipheth.c b/sys/bus/u4b/net/if_ipheth.c
--- a/sys/bus/u4b/net/if_ipheth.c
+++ b/sys/bus/u4b/net/if_ipheth.c
@@ -232,13 +232,13 @@
 	    uaa->info.bIfaceIndex, IPHETH_ALT_INTFNUM);
 	if (error) {
 		device_printf(dev, "Cannot set alternate setting\n");
-		goto detach;
+		goto detach_usb;
 	}
 	error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no,
 	    sc->sc_xfer, ipheth_config, IPHETH_N_TRANSFER, sc, &sc->sc_lock);
 	if (error) {
 		device_printf(dev, "Cannot setup USB transfers\n");
-		goto detach;
+		goto detach_usb;
 	}
 	ue->ue_sc = sc;
 	ue->ue_dev = dev;
@@ -249,18 +249,27 @@
 	error = ipheth_get_mac_addr(sc);
 	if (error) {
 		device_printf(dev, "Cannot get MAC address\n");
-		goto detach;
+		goto detach_usb;
 	}
 
 	error = uether_ifattach(ue);
 	if (error) {
 		device_printf(dev, "could not attach interface\n");
-		goto detach;
+		goto detach_usb;
 	}
 	return (0);			/* success */
 
-detach:
-	ipheth_detach(dev);
+	/*
+	 * Pre-uether_ifattach() failure paths: the usb_ether was never
+	 * attached, so ipheth_detach() / uether_ifdetach() must not run.
+	 * On the first two branches ue_lock is still NULL (lockmgr through
+	 * NULL, Fatal trap 12) and on the latter two the embedded ifnet was
+	 * never ether_ifattach()ed.  Only unsetup the USB transfers and
+	 * destroy the lock.
+	 */
+detach_usb:
+	usbd_transfer_unsetup(sc->sc_xfer, IPHETH_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,15 @@
 {
 	struct ifnet *ifp;
 
+	/*
+	 * Never-attached guard (DF-5334 class): when uether_ifattach()
+	 * never ran there is no taskqueue to drain and no ifnet to
+	 * detach.  ue_lock is NULL on the driver attach-failure paths
+	 * that jump to detach before ue field initialisation.
+	 */
+	if (ue->ue_lock == NULL)
+		return;
+
 	/* wait for any post attach or other command to complete */
 	usb_proc_drain(&ue->ue_tq);