⬢ DragonFlyBSD Kernel Audit
DF-5641 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/isa/x86_64/isa.c
+++ b/sys/bus/isa/x86_64/isa.c
@@ -84,10 +84,17 @@
 	 */
 	int passthrough = (device_get_parent(child) != bus);
 	int isdefault = (start == 0UL && end == ~0UL);
-	struct isa_device* idev = DEVTOISA(child);
-	struct resource_list *rl = &idev->id_resources;
+	/*
+	 * The child's ivars are only a struct isa_device for direct
+	 * children of this bus; a passthrough (grandchild) request must
+	 * never cast them.  The resource_list helpers do not touch rl
+	 * on passthrough, so leave it NULL for that case.
+	 */
+	struct resource_list *rl = NULL;
 	struct resource_list_entry *rle;
 
+	if (!passthrough)
+		rl = &DEVTOISA(child)->id_resources;
 	if (!passthrough && !isdefault) {
 		rle = resource_list_find(rl, type, *rid);
 		if (!rle) {
@@ -127,8 +134,13 @@
 isa_release_resource(device_t bus, device_t child, int type, int rid,
 		     struct resource *r)
 {
-	struct isa_device* idev = DEVTOISA(child);
-	struct resource_list *rl = &idev->id_resources;
+	/* ivars are a struct isa_device only for direct children */
+	struct resource_list *rl;
+
+	if (device_get_parent(child) == bus)
+		rl = &DEVTOISA(child)->id_resources;
+	else
+		rl = NULL;
 
 	return resource_list_release(rl, bus, child, type, rid, r);
 }