From owner-svn-src-all@FreeBSD.ORG Wed Oct 12 18:08:29 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 241A9106566B; Wed, 12 Oct 2011 18:08:29 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 132638FC13; Wed, 12 Oct 2011 18:08:29 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p9CI8SLl077855; Wed, 12 Oct 2011 18:08:28 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p9CI8Seo077849; Wed, 12 Oct 2011 18:08:28 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201110121808.p9CI8Seo077849@svn.freebsd.org> From: Gleb Smirnoff Date: Wed, 12 Oct 2011 18:08:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r226313 - in head/sys: kern vm X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Oct 2011 18:08:29 -0000 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 #include #include +#include #include 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 #include @@ -88,6 +89,10 @@ __FBSDID("$FreeBSD$"); #include +#ifdef DEBUG_MEMGUARD +#include +#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);