⬢ DragonFlyBSD Kernel Audit
DF-5355 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/pccard/pccard.c
+++ b/sys/bus/pccard/pccard.c
@@ -494,11 +494,34 @@
 		pf->cfe = cfe;
 		break;
 	    not_this_one:;
+		{
+			/*
+			 * Unwind whatever this config entry managed to
+			 * allocate before failing.  Leaving the entries in
+			 * the list makes the next candidate entry re-add the
+			 * same (type, rid), which panics in
+			 * resource_list_add("resource entry is busy"), and
+			 * leaks the allocated bus windows for every failed
+			 * entry.  pccard_function_init() is documented to
+			 * hold no resources on return, so any busy entry at
+			 * this point belongs to a failed candidate.
+			 */
+			struct resource_list_entry *trle;
+
+again:
+			SLIST_FOREACH(trle, rl, link) {
+				if (trle->res != NULL) {
+					bus_release_resource(bus, trle->type,
+					    trle->rid, trle->res);
+					trle->res = NULL;
+					resource_list_delete(rl, trle->type,
+					    trle->rid);
+					goto again;	/* list changed */
+				}
+			}
+		}
 		DEVPRVERBOSE((bus, "Allocation failed for cfe %d\n",
 		    cfe->number));
-#if 0 /* YYY */
-		resource_list_purge(rl);
-#endif
 	}
 }