⬢ DragonFlyBSD Kernel Audit
DF-4343 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/mn/if_mn.c
+++ b/sys/dev/netif/mn/if_mn.c
@@ -241,6 +241,7 @@
 	int	unit;
 	device_t	dev;
 	struct resource *irq;
+	struct resource *mem0, *mem1;
 	void *intrhand;
 	enum framing	framing;
 	int 		nhooks;
@@ -1282,7 +1283,6 @@
 	u_int32_t ver;
 	static int once;
 	int rid, error;
-	struct resource *res;
 
 	if (!once) {
 		if (ng_newtype(&mntypestruct))
@@ -1299,22 +1299,26 @@
 	ksprintf(sc->name, "mn%d", sc->unit);
 
         rid = PCIR_MAPS;
-        res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
-        if (res == NULL) {
+        sc->mem0 = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
+            RF_ACTIVE);
+        if (sc->mem0 == NULL) {
                 device_printf(self, "Could not map memory\n");
                 return ENXIO;
         }
-        sc->m0v = rman_get_virtual(res);
-        sc->m0p = rman_get_start(res);
+        sc->m0v = rman_get_virtual(sc->mem0);
+        sc->m0p = rman_get_start(sc->mem0);
 
         rid = PCIR_MAPS + 4;
-        res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
-        if (res == NULL) {
+        sc->mem1 = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
+            RF_ACTIVE);
+        if (sc->mem1 == NULL) {
                 device_printf(self, "Could not map memory\n");
+                bus_release_resource(self, SYS_RES_MEMORY, PCIR_MAPS,
+                    sc->mem0);
                 return ENXIO;
         }
-        sc->m1v = rman_get_virtual(res);
-        sc->m1p = rman_get_start(res);
+        sc->m1v = rman_get_virtual(sc->mem1);
+        sc->m1p = rman_get_start(sc->mem1);
 
 	/* Allocate interrupt */
 	rid = 0;
@@ -1323,6 +1327,10 @@
 
 	if (sc->irq == NULL) {
 		kprintf("couldn't map interrupt\n");
+		bus_release_resource(self, SYS_RES_MEMORY, PCIR_MAPS + 4,
+		    sc->mem1);
+		bus_release_resource(self, SYS_RES_MEMORY, PCIR_MAPS,
+		    sc->mem0);
 		return(ENXIO);
 	}
 
@@ -1331,6 +1339,11 @@
 
 	if (error) {
 		kprintf("couldn't set up irq\n");
+		bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq);
+		bus_release_resource(self, SYS_RES_MEMORY, PCIR_MAPS + 4,
+		    sc->mem1);
+		bus_release_resource(self, SYS_RES_MEMORY, PCIR_MAPS,
+		    sc->mem0);
 		return(ENXIO);
 	}
 
@@ -1352,7 +1365,7 @@
 	/* We must reset before poking at FALC54 registers */
 	u = mn_reset(sc);
 	if (!u)
-		return (0);
+		return (ENXIO);	/* controller failed bus-master test */
 
 	kprintf("mn%d: Munich32X", sc->unit);
 	switch (ver) {
@@ -1385,14 +1398,16 @@
 
 	if (ng_make_node_common(&mntypestruct, &sc->node) != 0) {
 		kprintf("ng_make_node_common failed\n");
-		return (0);
+		sc->node = NULL;
+		return (ENXIO);
 	}
 	sc->node->private = sc;
 	ksprintf(sc->nodename, "%s%d", NG_MN_NODE_TYPE, sc->unit);
 	if (ng_name_node(sc->node, sc->nodename)) {
 		ng_rmnode(sc->node);
 		ng_unref(sc->node);
-		return (0);
+		sc->node = NULL;	/* softc must not keep the freed node */
+		return (ENXIO);
 	}
 
 	return (0);