MemGuard —
memory allocator for debugging purposes
options DEBUG_MEMGUARD
MemGuard is a simple and small replacement memory
allocator designed to help detect tamper-after-free scenarios. These problems
are more and more common and likely with multithreaded kernels where race
conditions are more prevalent.
MemGuard can take over
malloc(),
realloc()
and
free() for a single malloc type.
Alternatively
MemGuard can take over
uma_zalloc(),
uma_zalloc_arg() and
uma_free() for a single
uma(9) zone. Also
MemGuard can guard all allocations larger than
PAGE_SIZE
, and can guard a random fraction
of all allocations. There is also a knob to prevent allocations smaller than a
specified size from being guarded, to limit memory waste.
To use
MemGuard for a memory type, either add an
entry to
/boot/loader.conf:
vm.memguard.desc=<memory_type>
Or set the
vm.memguard.desc
sysctl(8) variable at run-time:
sysctl vm.memguard.desc=<memory_type>
Where
memory_type can be either a short
description of the memory type to monitor, either name of
uma(9) zone. Only allocations from that
memory_type made after
vm.memguard.desc is set will potentially be
guarded. If
vm.memguard.desc is modified at
run-time then only allocations of the new
memory_type will potentially be guarded once
the
sysctl(8) is set. Existing guarded
allocations will still be properly released by either
free(9) or
uma_zfree(9), depending on what kind of
allocation was taken over.
To determine short description of a
malloc(9) type
one can either take it from the first column of
vmstat(8) -m output,
or to find it in the kernel source. It is the second argument to
MALLOC_DEFINE(9) macro. To determine name of
uma(9) zone one can either take it from the first
column of
vmstat(8)
-z output, or to find it in the kernel source. It
is the first argument to the
uma_zcreate(9)
function.
The
vm.memguard.divisor boot-time tunable is
used to scale how much of the system's physical memory
MemGuard is allowed to consume. The default is
10, so up to
vm_cnt.v_page_count/10 pages can
be used.
MemGuard will reserve
vm_kmem_max /
vm.memguard.divisor bytes of virtual address
space, limited by twice the physical memory size. The physical limit is
reported as
vm.memguard.phys_limit and the
virtual space reserved for
MemGuard is reported
as
vm.memguard.mapsize.
MemGuard will not do page promotions for any
allocation smaller than
vm.memguard.minsize
bytes. The default is 0, meaning all allocations can potentially be guarded.
MemGuard can guard sufficiently large allocations
randomly, with average frequency of every one in 100000 /
vm.memguard.frequency allocations. The
default is 0, meaning no allocations are randomly guarded.
MemGuard can optionally add unmapped guard pages
around each allocation to detect overflow and underflow, if
vm.memguard.options has the 1 bit set. This
option is enabled by default.
MemGuard will
optionally guard all allocations of
PAGE_SIZE
or larger if
vm.memguard.options has the 2 bit set. This
option is off by default. By default
MemGuard
does not guard
uma(9) zones that have been
initialized with the
UMA_ZONE_NOFREE
flag
set, since it can produce false positives on them. However, this safety
measure can be turned off by setting bit 3 of the
vm.memguard.options tunable.
sysctl(8),
vmstat(8),
contigmalloc(9),
malloc(9),
redzone(9),
uma(9)
MemGuard first appeared in
FreeBSD
6.0.
MemGuard was originally written by
Bosko Milekic
<
[email protected]>.
This manual page was originally written by
Christian Brueffer
<
[email protected]>.
Additions have been made by
Matthew Fleming
<
[email protected]>
and
Gleb Smirnoff
<
[email protected]>
to both the implementation and the documentation.