https://bugs.kde.org/show_bug.cgi?id=516202
Bug ID: 516202
Summary: FreeBSD: try a better approach to mmap MAP_STACK
Classification: Developer tools
Product: valgrind
Version First 3.27 GIT
Reported In:
Platform: Other
OS: FreeBSD
Status: REPORTED
Severity: normal
Priority: NOR
Component: general
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
This problem is similar to https://bugs.kde.org/show_bug.cgi?id=514297
The man page says
MAP_STACK Creates both a mapped region that grows downward on
demand and an adjoining guard that both reserves
address space for the mapped region to grow into and
limits the mapped region's growth. Together, the
mapped region and the guard occupy len bytes of the
address space. The guard starts at the returned
address, and the mapped region ends at the returned
address plus len bytes. Upon access to the guard, the
mapped region automatically grows in size, and the
guard shrinks by an equal amount. Essentially, the
boundary between the guard and the mapped region moves
downward so that the access falls within the enlarged
mapped region. However, the guard will never shrink
to less than the number of pages specified by the
sysctl security.bsd.stack_guard_page, thereby ensuring
that a gap for detecting stack overflow always exists
between the downward growing mapped region and the
closest mapped region beneath it.
MAP_STACK implies MAP_ANON and offset of 0. The fd
argument must be -1 and prot must include at least
PROT_READ and PROT_WRITE. The size of the guard, in
pages, is specified by sysctl
security.bsd.stack_guard_page.
In other words, one mmap results in 2 VM mappings that can change silently
without Valgrind being informed. That poses a problem with --sanity-level=3.
My initial fix was to bodge parse_procselfmaps so that it would try to work out
what the original mmap was and so make Valgrind's record match the VM map that
the kernel provides. Ugh.
My first attempt at this is
RegWord arg4 = ARG4;
if ((arg4 & VKI_MAP_STACK) && (VG_(clo_sanity_level) >= 3)) {
arg4 &= ~VKI_MAP_STACK;
arg4 |= VKI_MAP_PRIVATE | VKI_MAP_ANON | VKI_MAP_NOCORE;
}
(in PRE(sys_mmap))
As far as I can tell this only affects pthread stacks (and any guest code that
uses MAP_STACK, unlikely). Even if the main thread is uses this mmap flag we
don't use the OS created main stack so we should not have a problem with that.
The libthr code is
/* Map the stack and guard page together, and split guard
page from allocated space: */
if ((stackaddr = mmap(stackaddr, stacksize + guardsize,
_rtld_get_stack_prot(), MAP_STACK,
-1, 0)) != MAP_FAILED &&
(guardsize == 0 ||
mprotect(stackaddr, guardsize, PROT_NONE) == 0)) {
stackaddr += guardsize;
} else {
if (stackaddr != MAP_FAILED)
munmap(stackaddr, stacksize + guardsize);
stackaddr = NULL;
}
attr->stackaddr_attr = stackaddr;
We can't make the mmap fail like in 514297 since failure results in a NULL
pthread stack and then pthread_create failing and setting EAGAIN.
--
You are receiving this mail because:
You are watching all bug changes.