[issue568] ACPI(?) double-free on shutdown (More K9AGM fun)

Matthew Dillon dillon at apollo.backplane.com
Thu Mar 8 08:41:51 PST 2007


:Joe "Floid" Kanowitz <jkanowitz at snet.net> added the comment:
:
:Looks like the patch was a winner; what you've won, I'm not experienced (or
:awake) enough to figure out.
:
:http://bugs.dragonflybsd.org/file213/Patch_Panic_1.png and
:http://bugs.dragonflybsd.org/file214/Patch_Panic_2.png ,
:
:hopefully the PNGs are less eye-searingly blurry than the JPGs were, and
:hopefully I'll have a working serial header within a week or two.
:
:-Floid

    Yah.  It looks like a reference count problem in the ACPI contrib code,
    and it doesn't look like it will be easy to find.

    The ACPI code is clearly reusing freed memory so it may panic in 
    other ways, but we can try just letting this error slide and see if
    that stops your panics.  Here's a patch to try.

					-Matt
					Matthew Dillon 
					<dillon at backplane.com>

Index: Osd/OsdCache.c
===================================================================
RCS file: /cvs/src/sys/dev/acpica5/Osd/OsdCache.c,v
retrieving revision 1.2
diff -u -r1.2 OsdCache.c
--- Osd/OsdCache.c	19 Jan 2007 23:58:53 -0000	1.2
+++ Osd/OsdCache.c	8 Mar 2007 16:29:37 -0000
@@ -39,6 +39,20 @@
 	struct objcache_malloc_args args;
 };
 
+/*
+ * Add some magic numbers to catch double-frees earlier rather
+ * then later.
+ */
+struct acpiobjhead {
+	int state;
+	int unused;
+};
+
+#define TRACK_ALLOCATED	0x7AF45533
+#define TRACK_FREED	0x7B056644
+
+#define OBJHEADSIZE	sizeof(struct acpiobjhead)
+
 #include "acpi.h"
 
 #ifndef ACPI_USE_LOCAL_CACHE
@@ -50,7 +64,7 @@
 	ACPI_CACHE_T *cache;
 
 	cache = kmalloc(sizeof(*cache), M_TEMP, M_WAITOK);
-	cache->args.objsize = ObjectSize;
+	cache->args.objsize = OBJHEADSIZE + ObjectSize;
 	cache->args.mtype = M_CACHE;
 	cache->cache = objcache_create(CacheName, 0, 0, NULL, NULL,
 	    NULL, objcache_malloc_alloc, objcache_malloc_free, &cache->args);
@@ -79,17 +93,30 @@
 void *
 AcpiOsAcquireObject(ACPI_CACHE_T *Cache)
 {
+	struct acpiobjhead *head;
 	void *Object;
 
-	Object = objcache_get(Cache->cache, M_WAITOK);
-	bzero(Object, Cache->args.objsize);
-	return Object;
+	head = objcache_get(Cache->cache, M_WAITOK);
+	bzero(head, Cache->args.objsize);
+	head->state = TRACK_ALLOCATED;
+	return (head + 1);
 }
 
 ACPI_STATUS
 AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object)
 {
-	objcache_put(Cache->cache, Object);
+	struct acpiobjhead *head = (void *)((char *)Object - OBJHEADSIZE);
+
+	if (head->state != TRACK_ALLOCATED) {
+		if (head->state == TRACK_FREED)
+			printf("AcpiOsReleaseObject: Double Free %p (%08x)\n", Object, head->state);
+		else
+			printf("AcpiOsReleaseObject: Bad object %p (%08x)\n", Object, head->state);
+		return AE_OK;
+	}
+	head->state = TRACK_FREED;
+
+	objcache_put(Cache->cache, head);
 	return AE_OK;
 }
 





More information about the Bugs mailing list