[PATCH v7 1/4] support: Add support_stack_alloc

Florian Weimer fweimer@redhat.com
Wed Jul 7 17:15:20 GMT 2021


* Adhemerval Zanella:

> On 07/07/2021 07:17, Florian Weimer wrote:
>> * Adhemerval Zanella via Libc-alpha:
>> 
>>> The code to allocate a stack from xsigstack is refactored so it can
>>> be more generic.  The new support_stack_alloc() also set PROT_EXEC
>>> if DEFAULT_STACK_PERMS has PF_X.  This is required on some
>>>  architectures (hppa for instance) and trying to access the rtld
>>> global from testsuite will require more intrusive refactoring
>>> in the ldsodefs.h header.
>> 
>> DEFAULT_STACK_PERMS is misnamed, it's really HISTORIC_STACK_PERMS.
>> All architectures override it to RW permissions in the toolchain
>> (maybe with the exception of Hurd, which uses trampolines for nested
>> functions).
>
> This is in fact two different requirements, this gnulib thread gives
> a nice summary about the permission required from trampolines [1]. 
> Another requirement is how Linux layout the signal return code for the 
> signal handler stack.  It seems that hppa still requires executable 
> stacks, since tst-xsigstack does fails without a executable stack even 
> on a recent 5.10.46-1 kernel.

Ugh, okay.

>> I have a cstack_allocate version that handles this.  It can only be done
>> from within glibc proper because we do not export the stack execution
>> status directly.  But I think it's out of scope for glibc 2.34 by now.
>
> We can in theory access the ldsodes.h fields directly and then
> use GL (dl_stack_flags) information to set the stack executable or not.
> The problem is ldsodefs.h is quite convoluted and it would require more
> refactoring to use outside libc.so code.  But I agree with you that
> having less hacky way to obtain this information is better.
>
> So are you ok with the current approach or being conservative and use
> DEFAULT_STACK_PERMS on libsupport?

DEFAULT_STACK_PERMS with a comment is fine.

I will resubmit my cstack_allocate patches for glibc 2.35 patches, and
they will fully handle executable stacks.

>>> +  /* The guard bands need to be large enough to intercept offset
>>> +     accesses from a stack address that might otherwise hit another
>>> +     mapping.  Make them at least twice as big as the stack itself, to
>>> +     defend against an offset by the entire size of a large
>>> +     stack-allocated array.  The minimum is 1MiB, which is arbitrarily
>>> +     chosen to be larger than any "typical" wild pointer offset.
>>> +     Again, no matter what the number is, round it up to a whole
>>> +     number of pages.  */
>>> +  size_t guardsize = roundup (MAX (2 * stacksize, 1024 * 1024), pagesize);
>>> +  size_t alloc_size = guardsize + stacksize + guardsize;
>>> +  /* Use MAP_NORESERVE so that RAM will not be wasted on the guard
>>> +     bands; touch all the pages of the actual stack before returning,
>>> +     so we know they are allocated.  */
>>> +  void *alloc_base = xmmap (0,
>>> +                            alloc_size,
>>> +                            PROT_NONE,
>>> +                            MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE|MAP_STACK,
>>> +                            -1);
>>> +  /* PF_X can be overridden if PT_GNU_STACK is present.  */
>>> +  int prot = PROT_READ | PROT_WRITE
>>> +	     | (DEFAULT_STACK_PERMS & PF_X ? PROT_EXEC : 0);
>>> +  xmprotect (alloc_base + guardsize, stacksize, prot);
>>> +  memset (alloc_base + guardsize, 0xA5, stacksize);
>>> +  return (struct support_stack) { alloc_base + guardsize, stacksize, guardsize };
>> 
>> This doesn't handle different stack growth directions.
>> 
>
> At least for the usages of the routine it does not require any adjustment:
> xsigaltstack and xclone will handle it.  I saw no regression for
> tst-xsigaltstack and tst-clone_range.

Huh, I would expect the guard area to be outside of the stack region
returned by stack allocation.  That's how the cstack_allocate API does
it.  If the current tests expect something else, then the approach in
the patch is okay (with a comment for DEFAULT_STACK_PERMS).

Thanks,
Florian



More information about the Libc-alpha mailing list