1
0
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:
Adhemerval Zanella
2025-09-08 13:06:13 -03:00
parent b8254a047f
commit 855bfa2566
2 changed files with 57 additions and 25 deletions

View File

@@ -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: