tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

changes to malloclog to print out neighbouring memory allocations



I have been working with someone to try and track down what looks to
be a memory corruption, memory is getting modified on the kernel
freelist.  They have enabled MALLOCLOG which allows us to track memory
allocations for the region of interest but I wanted to investigate the
possibility of there being a "bad neighbour" meaning that the
object allocated before the one detecting the corruption is being
overflowed and corrupting memory further along.  To try and catch this
I modified the MALLOCLOG code to include a neighbour detection which
checks the logs for allocations where base + size modulo is within a
"fuzz" factor of the address of interest.

Attached is a patch that does this - the variable malloclog_fuzz
controls how wide the matching is.  This is a variable so it can be
tweaked dynamically (via ddb or the like) to broaden or narrow the
matching range depending how much noise (or lack thereof) is returned.

Useful?  Commit?

-- 
Brett Lymn
"Warning:
The information contained in this email and any attached files is
confidential to BAE Systems Australia. If you are not the intended
recipient, any use, disclosure or copying of this email or any
attachments is expressly prohibited.  If you have received this email
in error, please notify us immediately. VIRUS: Every care has been
taken to ensure this email and its attachments are virus free,
however, any loss or damage incurred in using this email is not the
sender's responsibility.  It is your responsibility to ensure virus
checks are completed before installing any data sent in this email to
your computer."

Index: kern_malloc.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_malloc.c,v
retrieving revision 1.119
diff -u -r1.119 kern_malloc.c
--- kern_malloc.c       17 Mar 2008 17:05:54 -0000      1.119
+++ kern_malloc.c       16 Oct 2008 12:32:53 -0000
@@ -192,6 +192,13 @@
 
 long   malloclogptr;
 
+/*
+ * Fuzz factor for neighbour address match this must be a mask of the lower
+ * bits we wish to ignore when comparing addresses
+ */
+__uintptr_t malloclog_fuzz = 0x7FL;
+
+
 static void
 domlog(void *a, long size, struct malloc_type *type, int action,
     const char *file, long line)
@@ -227,11 +234,41 @@
        } \
 } while (/* CONSTCOND */0)
 
-       for (l = malloclogptr; l < MALLOCLOGSIZE; l++)
+/*
+ * Print fuzzy matched "neighbour" - look for the memory block that has
+ * been allocated below the address we are interested in.  We look for a
+ * base address + size that is within malloclog_fuzz of our target
+ * address. If the base address and target address are the same then it is
+ * likely we have found a free (size is 0 in this case) so we won't report
+ * those, they will get reported by PRT anyway.
+ */
+#define        NPRT do { \
+       __uintptr_t fuzz_mask = ~(malloclog_fuzz); \
+       lp = &malloclog[l]; \
+       if ((__uintptr_t)lp->addr != (__uintptr_t)a && \
+           (((__uintptr_t)lp->addr + lp->size + malloclog_fuzz) & fuzz_mask) \
+           == ((__uintptr_t)a & fuzz_mask) && lp->action) {            \
+               printf("neighbour malloc log entry %ld:\n", l); \
+               printf("\taddr = %p\n", lp->addr); \
+               printf("\tsize = %ld\n", lp->size); \
+               printf("\ttype = %s\n", lp->type->ks_shortdesc); \
+               printf("\taction = %s\n", lp->action == 1 ? "alloc" : "free"); \
+               printf("\tfile = %s\n", lp->file); \
+               printf("\tline = %ld\n", lp->line); \
+       } \
+} while (/* CONSTCOND */0)
+
+       for (l = malloclogptr; l < MALLOCLOGSIZE; l++) {
                PRT;
+               NPRT;
+       }
+
 
-       for (l = 0; l < malloclogptr; l++)
+       for (l = 0; l < malloclogptr; l++) {
                PRT;
+               NPRT;
+       }
+
 #undef PRT
 }
 #endif /* MALLOCLOG */


Home | Main Index | Thread Index | Old Index