[Bug 260303] lang/sdcc: seg fault during build (ASLR fallout)

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 10 Dec 2021 20:41:23 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=260303

Mark Johnston <markj@FreeBSD.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|New                         |Open
                 CC|                            |markj@FreeBSD.org

--- Comment #4 from Mark Johnston <markj@FreeBSD.org> ---
(In reply to Dawid Gorecki from comment #2)
I did some digging into this earlier this week, and I think the problems go
deeper.  I believe the stack gap randomization should be disabled in main until
this is sorted out properly.

Right now on amd64 we have

---------  <---- top of user memory
VDSO page
---------  <---- address returned by KERN_USRSTACK sysctl
ps_strings
auxv
---------
stack gap
---------  <---- address returned by KERN_STACKTOP sysctl
argv, envv
main process stack
...
---------  <---- 
bottom of stack

Some problems:

1. The stack gap is still mapped, just unused.  So mlockall() will wire the
stack gap region, wasting megabytes of memory.

2. The default RLIMIT_STACK value of 512 MB includes the stack gap.  But
setrlimit(RLIMIT_STACK) adds the size of the gap to the soft limit.  So:
2a. The hard limit is clamped to the soft limit, so setting rlim_cur = rlim_max
doesn't work.  That is the problem reported in this PR.
2b. The stack gap adjustment is visible to userspace.  The simplest example,

    getrlimit(RLIMIT_STACK, &lim);
    setrlimit(RLIMIT_STACK, &lim);

    does not work as expected, i.e., it actually changes the stored limit
(assuming 2a) is fixed.

3. The changes made recently to singlethread_map_stacks_exec() and
init_private() in libthr don't make sense to me.  In the former, we grab the
KERN_STACKTOP and then mprotect() a region of size RLIMIT_STACK, but part of
that region is unmapped (or mapped for something other than the stack) since
RLIMIT_STACK includes the stack gap but KERN_STACKTOP is already adjusted by
the stack gap.  Meanwhile, __libc_map_stacks_exec() was not similarly modified.
 Moreover, old copies of libthr.so will continue to use KERN_USRSTACK.

Rather than including the gap in RLIMIT_STACK, can we map the full 512MB stack
starting at the (randomized) argv/envv location (creating a separate mapping
for ps_strings/auxv), or include ps_strings/auxv at the beginning of the
randomized region?  The latter is more work, since the kernel uses the
ABI-defined ps_strings address in some places.  It would break very old
binaries that hard-code the ps_strings address, but aren't they effectively all
32-bit binaries anyway?

In any case, I propose disabling the stack gap randomization for now to address
the regressions.  sdcc is not the only affected program.

-- 
You are receiving this mail because:
You are the assignee for the bug.