Author: mdf
Date: Tue Aug 31 16:57:58 2010
New Revision: 212058
URL: http://svn.freebsd.org/changeset/base/212058

Log:
  The realloc case for memguard(9) will copy too many bytes when
  reallocating to a smaller-sized allocation.  Fix this issue.
  
  Noticed by:     alc
  Reviewed by:    alc
  Approved by:    zml (mentor)
  MFC after:      3 weeks

Modified:
  head/sys/kern/kern_malloc.c
  head/sys/vm/memguard.c
  head/sys/vm/memguard.h

Modified: head/sys/kern/kern_malloc.c
==============================================================================
--- head/sys/kern/kern_malloc.c Tue Aug 31 15:58:15 2010        (r212057)
+++ head/sys/kern/kern_malloc.c Tue Aug 31 16:57:58 2010        (r212058)
@@ -566,11 +566,8 @@ realloc(void *addr, unsigned long size, 
         */
 
 #ifdef DEBUG_MEMGUARD
-       if (is_memguard_addr(addr)) {
-               slab = NULL;
-               alloc = size;
-               goto remalloc;
-       }
+       if (is_memguard_addr(addr))
+               return (memguard_realloc(addr, size, mtp, flags));
 #endif
 
 #ifdef DEBUG_REDZONE
@@ -595,10 +592,6 @@ realloc(void *addr, unsigned long size, 
                return (addr);
 #endif /* !DEBUG_REDZONE */
 
-#ifdef DEBUG_MEMGUARD
-remalloc:
-#endif
-
        /* Allocate a new, bigger (or smaller) block */
        if ((newaddr = malloc(size, mtp, flags)) == NULL)
                return (NULL);

Modified: head/sys/vm/memguard.c
==============================================================================
--- head/sys/vm/memguard.c      Tue Aug 31 15:58:15 2010        (r212057)
+++ head/sys/vm/memguard.c      Tue Aug 31 16:57:58 2010        (r212058)
@@ -399,6 +399,31 @@ memguard_free(void *ptr)
        vm_map_unlock(memguard_map);
 }
 
+/*
+ * Re-allocate an allocation that was originally guarded.
+ */
+void *
+memguard_realloc(void *addr, unsigned long size, struct malloc_type *mtp,
+    int flags)
+{
+       void *newaddr;
+       u_long old_size;
+
+       /*
+        * Allocate the new block.  Force the allocation to be guarded
+        * as the original may have been guarded through random
+        * chance, and that should be preserved.
+        */
+       if ((newaddr = memguard_alloc(size, flags)) == NULL)
+               return (NULL);
+
+       /* Copy over original contents. */
+       old_size = *v2sizep(trunc_page((uintptr_t)addr));
+       bcopy(addr, newaddr, min(size, old_size));
+       memguard_free(addr);
+       return (newaddr);
+}
+
 int
 memguard_cmp(struct malloc_type *mtp, unsigned long size)
 {

Modified: head/sys/vm/memguard.h
==============================================================================
--- head/sys/vm/memguard.h      Tue Aug 31 15:58:15 2010        (r212057)
+++ head/sys/vm/memguard.h      Tue Aug 31 16:57:58 2010        (r212058)
@@ -38,6 +38,7 @@ struct vm_map;
 unsigned long  memguard_fudge(unsigned long, unsigned long);
 void   memguard_init(struct vm_map *);
 void   *memguard_alloc(unsigned long, int);
+void   *memguard_realloc(void *, unsigned long, struct malloc_type *, int);
 void   memguard_free(void *);
 int    memguard_cmp(struct malloc_type *, unsigned long);
 int    is_memguard_addr(void *);
@@ -45,6 +46,7 @@ int   is_memguard_addr(void *);
 #define        memguard_fudge(size, xxx)       (size)
 #define        memguard_init(map)              do { } while (0)
 #define        memguard_alloc(size, flags)     NULL
+#define        memguard_realloc(a, s, mtp, f)  NULL
 #define        memguard_free(addr)             do { } while (0)
 #define        memguard_cmp(mtp, size)         0
 #define        is_memguard_addr(addr)          0
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to