mirror of
https://sourceware.org/git/glibc.git
synced 2025-10-27 12:15:39 +03:00
nptl: Fix MADV_GUARD_INSTALL logic for thread without guard page (BZ 33356)
The main issue is that setup_stack_prot fails to account for cases where the cached thread stack lacks a guard page, which can cause madvise to fail. Update the logic to also handle whether MADV_GUARD_INSTALL is supported when resizing the guard page. Checked on x86_64-linux-gnu with 6.8.0 and 6.15 kernels. Reviewed-by: Florian Weimer <fweimer@redhat.com>
This commit is contained in:
@@ -234,7 +234,7 @@ setup_stack_prot (char *mem, size_t size, struct pthread *pd,
|
||||
/* Update the guard area of the thread stack MEM of size SIZE with the new
|
||||
GUARDISZE. It uses the method defined by PD stack_mode. */
|
||||
static inline bool
|
||||
adjust_stack_prot (char *mem, size_t size, const struct pthread *pd,
|
||||
adjust_stack_prot (char *mem, size_t size, struct pthread *pd,
|
||||
size_t guardsize, size_t pagesize_m1)
|
||||
{
|
||||
/* The required guard area is larger than the current one. For
|
||||
@@ -252,11 +252,23 @@ adjust_stack_prot (char *mem, size_t size, const struct pthread *pd,
|
||||
so use the new guard placement with the new size. */
|
||||
if (guardsize > pd->guardsize)
|
||||
{
|
||||
/* There was no need to previously setup a guard page, so we need
|
||||
to check whether the kernel supports guard advise. */
|
||||
char *guard = guard_position (mem, size, guardsize, pd, pagesize_m1);
|
||||
if (pd->stack_mode == ALLOCATE_GUARD_MADV_GUARD)
|
||||
return __madvise (guard, guardsize, MADV_GUARD_INSTALL) == 0;
|
||||
else if (pd->stack_mode == ALLOCATE_GUARD_PROT_NONE)
|
||||
return __mprotect (guard, guardsize, PROT_NONE) == 0;
|
||||
if (atomic_load_relaxed (&allocate_stack_mode)
|
||||
== ALLOCATE_GUARD_MADV_GUARD)
|
||||
{
|
||||
if (__madvise (guard, guardsize, MADV_GUARD_INSTALL) == 0)
|
||||
{
|
||||
pd->stack_mode = ALLOCATE_GUARD_MADV_GUARD;
|
||||
return true;
|
||||
}
|
||||
atomic_store_relaxed (&allocate_stack_mode,
|
||||
ALLOCATE_GUARD_PROT_NONE);
|
||||
}
|
||||
|
||||
pd->stack_mode = ALLOCATE_GUARD_PROT_NONE;
|
||||
return __mprotect (guard, guardsize, PROT_NONE) == 0;
|
||||
}
|
||||
/* The current guard area is larger than the required one. For
|
||||
_STACK_GROWS_DOWN is means change the guard as:
|
||||
|
||||
Reference in New Issue
Block a user