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.

Reply via email to