Fix memguard(9) in kernels with INVARIANTS enabled.

With r284861, UMA zones use the trash ctor and dtor by default. This is
incompatible with memguard, which frees the backing page when the item
is freed. Modify the UMA debug functions to be no-ops if the item was
allocated from memguard. This also fixes constructors such as
mb_ctor_pack(), which invokes the trash ctor in addition to performing
some initialization.

Reviewed by:	glebius
MFC after:	3 weeks
Differential Revision:	https://reviews.freebsd.org/D6562
This commit is contained in:
Mark Johnston 2016-06-01 22:31:35 +00:00
parent b1a6b8dcd2
commit bc9d08e1cf
2 changed files with 30 additions and 9 deletions

View File

@ -2112,16 +2112,10 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags)
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);
@ -2655,9 +2649,9 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata)
return;
#ifdef DEBUG_MEMGUARD
if (is_memguard_addr(item)) {
if (zone->uz_dtor != NULL && zone->uz_dtor != mtrash_dtor)
if (zone->uz_dtor != NULL)
zone->uz_dtor(item, zone->uz_size, udata);
if (zone->uz_fini != NULL && zone->uz_fini != mtrash_fini)
if (zone->uz_fini != NULL)
zone->uz_fini(item, zone->uz_size);
memguard_free(item);
return;

View File

@ -33,6 +33,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_vm.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitset.h>
@ -49,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <vm/uma_int.h>
#include <vm/uma_dbg.h>
#include <vm/memguard.h>
static const uint32_t uma_junk = 0xdeadc0de;
@ -57,7 +60,6 @@ static const uint32_t uma_junk = 0xdeadc0de;
* prior to subsequent reallocation.
*
* Complies with standard ctor arg/return
*
*/
int
trash_ctor(void *mem, int size, void *arg, int flags)
@ -65,6 +67,11 @@ trash_ctor(void *mem, int size, void *arg, int flags)
int cnt;
uint32_t *p;
#ifdef DEBUG_MEMGUARD
if (is_memguard_addr(mem))
return (0);
#endif
cnt = size / sizeof(uma_junk);
for (p = mem; cnt > 0; cnt--, p++)
@ -93,6 +100,11 @@ trash_dtor(void *mem, int size, void *arg)
int cnt;
uint32_t *p;
#ifdef DEBUG_MEMGUARD
if (is_memguard_addr(mem))
return;
#endif
cnt = size / sizeof(uma_junk);
for (p = mem; cnt > 0; cnt--, p++)
@ -131,6 +143,11 @@ mtrash_ctor(void *mem, int size, void *arg, int flags)
uint32_t *p = mem;
int cnt;
#ifdef DEBUG_MEMGUARD
if (is_memguard_addr(mem))
return (0);
#endif
size -= sizeof(struct malloc_type *);
ksp = (struct malloc_type **)mem;
ksp += size / sizeof(struct malloc_type *);
@ -158,6 +175,11 @@ mtrash_dtor(void *mem, int size, void *arg)
int cnt;
uint32_t *p;
#ifdef DEBUG_MEMGUARD
if (is_memguard_addr(mem))
return;
#endif
size -= sizeof(struct malloc_type *);
cnt = size / sizeof(uma_junk);
@ -176,6 +198,11 @@ mtrash_init(void *mem, int size, int flags)
{
struct malloc_type **ksp;
#ifdef DEBUG_MEMGUARD
if (is_memguard_addr(mem))
return (0);
#endif
mtrash_dtor(mem, size, NULL);
ksp = (struct malloc_type **)mem;