Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Oct 2011 18:08:28 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r226313 - in head/sys: kern vm
Message-ID:  <201110121808.p9CI8Seo077849@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Wed Oct 12 18:08:28 2011
New Revision: 226313
URL: http://svn.freebsd.org/changeset/base/226313

Log:
  Make memguard(9) capable to guard uma(9) allocations.

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

Modified: head/sys/kern/kern_malloc.c
==============================================================================
--- head/sys/kern/kern_malloc.c	Wed Oct 12 17:57:57 2011	(r226312)
+++ head/sys/kern/kern_malloc.c	Wed Oct 12 18:08:28 2011	(r226313)
@@ -458,7 +458,7 @@ malloc(unsigned long size, struct malloc
 		   ("malloc(M_WAITOK) in interrupt context"));
 
 #ifdef DEBUG_MEMGUARD
-	if (memguard_cmp(mtp, size)) {
+	if (memguard_cmp_mtp(mtp, size)) {
 		va = memguard_alloc(size, flags);
 		if (va != NULL)
 			return (va);

Modified: head/sys/vm/memguard.c
==============================================================================
--- head/sys/vm/memguard.c	Wed Oct 12 17:57:57 2011	(r226312)
+++ head/sys/vm/memguard.c	Wed Oct 12 18:08:28 2011	(r226313)
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_map.h>
 #include <vm/vm_object.h>
 #include <vm/vm_extern.h>
+#include <vm/uma_int.h>
 #include <vm/memguard.h>
 
 SYSCTL_NODE(_vm, OID_AUTO, memguard, CTLFLAG_RW, NULL, "MemGuard data");
@@ -125,15 +126,17 @@ SYSCTL_ULONG(_vm_memguard, OID_AUTO, fai
 SYSCTL_ULONG(_vm_memguard, OID_AUTO, fail_pgs, CTLFLAG_RD,
     &memguard_fail_pgs, 0, "MemGuard failures due to lack of pages");
 
-#define MG_GUARD	0x001
-#define MG_ALLLARGE	0x002
-static int memguard_options = MG_GUARD;
+#define MG_GUARD_AROUND		0x001
+#define MG_GUARD_ALLLARGE	0x002
+#define MG_GUARD_NOFREE		0x004
+static int memguard_options = MG_GUARD_AROUND;
 TUNABLE_INT("vm.memguard.options", &memguard_options);
 SYSCTL_INT(_vm_memguard, OID_AUTO, options, CTLFLAG_RW,
     &memguard_options, 0,
     "MemGuard options:\n"
     "\t0x001 - add guard pages around each allocation\n"
-    "\t0x002 - always use MemGuard for allocations over a page");
+    "\t0x002 - always use MemGuard for allocations over a page\n"
+    "\t0x004 - guard uma(9) zones with UMA_ZONE_NOFREE flag");
 
 static u_int memguard_minsize;
 static u_long memguard_minsize_reject;
@@ -282,7 +285,7 @@ memguard_alloc(unsigned long req_size, i
 	 * value.
 	 */
 	size_v = size_p;
-	do_guard = (memguard_options & MG_GUARD) != 0;
+	do_guard = (memguard_options & MG_GUARD_AROUND) != 0;
 	if (do_guard)
 		size_v += 2 * PAGE_SIZE;
 
@@ -429,21 +432,32 @@ memguard_realloc(void *addr, unsigned lo
 	return (newaddr);
 }
 
-int
-memguard_cmp(struct malloc_type *mtp, unsigned long size)
+static int
+memguard_cmp(unsigned long size)
 {
 
 	if (size < memguard_minsize) {
 		memguard_minsize_reject++;
 		return (0);
 	}
-	if ((memguard_options & MG_ALLLARGE) != 0 && size >= PAGE_SIZE)
+	if ((memguard_options & MG_GUARD_ALLLARGE) != 0 && size >= PAGE_SIZE)
 		return (1);
 	if (memguard_frequency > 0 &&
 	    (random() % 100000) < memguard_frequency) {
 		memguard_frequency_hits++;
 		return (1);
 	}
+
+	return (0);
+}
+
+int
+memguard_cmp_mtp(struct malloc_type *mtp, unsigned long size)
+{
+
+	if (memguard_cmp(size))
+		return(1);
+
 #if 1
 	/*
 	 * The safest way of comparsion is to always compare short description
@@ -467,3 +481,21 @@ memguard_cmp(struct malloc_type *mtp, un
 	return (0);
 #endif
 }
+
+int
+memguard_cmp_zone(uma_zone_t zone)
+{
+
+	 if ((memguard_options & MG_GUARD_NOFREE) == 0 &&
+	    zone->uz_flags & UMA_ZONE_NOFREE)
+		return (0);
+
+	if (memguard_cmp(zone->uz_size))
+		return (1);
+
+	/*
+	 * The safest way of comparsion is to always compare zone name,
+	 * but it is also the slowest way.
+	 */
+	return (strcmp(zone->uz_name, vm_memguard_desc) == 0);
+}

Modified: head/sys/vm/memguard.h
==============================================================================
--- head/sys/vm/memguard.h	Wed Oct 12 17:57:57 2011	(r226312)
+++ head/sys/vm/memguard.h	Wed Oct 12 18:08:28 2011	(r226313)
@@ -40,7 +40,8 @@ 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	memguard_cmp_mtp(struct malloc_type *, unsigned long);
+int	memguard_cmp_zone(uma_zone_t);
 int	is_memguard_addr(void *);
 #else
 #define	memguard_fudge(size, xxx)	(size)
@@ -48,7 +49,8 @@ int	is_memguard_addr(void *);
 #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	memguard_cmp_mtp(mtp, size)	0
+#define	memguard_cmp_zone(zone)		0
 #define	is_memguard_addr(addr)		0
 #endif
 

Modified: head/sys/vm/uma.h
==============================================================================
--- head/sys/vm/uma.h	Wed Oct 12 17:57:57 2011	(r226312)
+++ head/sys/vm/uma.h	Wed Oct 12 18:08:28 2011	(r226313)
@@ -255,8 +255,8 @@ int uma_zsecond_add(uma_zone_t zone, uma
  * physical parameters of the request and may not be provided by the consumer.
  */
 #define	UMA_ZONE_INHERIT						\
-    (UMA_ZONE_OFFPAGE | UMA_ZONE_MALLOC | UMA_ZONE_HASH |		\
-    UMA_ZONE_REFCNT | UMA_ZONE_VTOSLAB)
+    (UMA_ZONE_OFFPAGE | UMA_ZONE_MALLOC | UMA_ZONE_NOFREE |		\
+    UMA_ZONE_HASH | UMA_ZONE_REFCNT | UMA_ZONE_VTOSLAB)
 
 /* Definitions for align */
 #define UMA_ALIGN_PTR	(sizeof(void *) - 1)	/* Alignment fit for ptr */

Modified: head/sys/vm/uma_core.c
==============================================================================
--- head/sys/vm/uma_core.c	Wed Oct 12 17:57:57 2011	(r226312)
+++ head/sys/vm/uma_core.c	Wed Oct 12 18:08:28 2011	(r226313)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 
 #include "opt_ddb.h"
 #include "opt_param.h"
+#include "opt_vm.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -88,6 +89,10 @@ __FBSDID("$FreeBSD$");
 
 #include <ddb/ddb.h>
 
+#ifdef DEBUG_MEMGUARD
+#include <vm/memguard.h>
+#endif
+
 /*
  * This is the zone and keg from which all zones are spawned.  The idea is that
  * even the zone & keg heads are allocated from the allocator, so we use the
@@ -1978,7 +1983,29 @@ uma_zalloc_arg(uma_zone_t zone, void *ud
 		WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
 		    "uma_zalloc_arg: zone \"%s\"", zone->uz_name);
 	}
-
+#ifdef DEBUG_MEMGUARD
+	if (memguard_cmp_zone(zone)) {
+		item = memguard_alloc(zone->uz_size, flags);
+		if (item != NULL) {
+			/*
+			 * Avoid conflict with the use-after-free
+			 * protecting infrastructure from INVARIANTS.
+			 */
+			if (zone->uz_init != NULL &&
+			    zone->uz_init != mtrash_init &&
+			    zone->uz_init(item, zone->uz_size, flags) != 0)
+				return (NULL);
+			if (zone->uz_ctor != NULL &&
+			    zone->uz_ctor != mtrash_ctor &&
+			    zone->uz_ctor(item, zone->uz_size, udata, flags) != 0) {
+			    	zone->uz_fini(item, zone->uz_size);
+				return (NULL);
+			}
+			return (item);
+		}
+		/* This is unfortunate but should not be fatal. */
+	}
+#endif
 	/*
 	 * If possible, allocate from the per-CPU cache.  There are two
 	 * requirements for safe access to the per-CPU cache: (1) the thread
@@ -2544,7 +2571,16 @@ uma_zfree_arg(uma_zone_t zone, void *ite
         /* uma_zfree(..., NULL) does nothing, to match free(9). */
         if (item == NULL)
                 return;
-
+#ifdef DEBUG_MEMGUARD
+	if (is_memguard_addr(item)) {
+		if (zone->uz_dtor != NULL && zone->uz_dtor != mtrash_dtor)
+			zone->uz_dtor(item, zone->uz_size, udata);
+		if (zone->uz_fini != NULL && zone->uz_fini != mtrash_fini)
+			zone->uz_fini(item, zone->uz_size);
+		memguard_free(item);
+		return;
+	}
+#endif
 	if (zone->uz_dtor)
 		zone->uz_dtor(item, zone->uz_size, udata);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201110121808.p9CI8Seo077849>