diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-09-08 13:06:13 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-09-23 10:33:49 -0300 |
commit | 18fd689cdced8348e42991964557cddea0ba2dc5 (patch) | |
tree | f2b40065430ac18fea01909898d7754a6faefb17 /nptl/allocatestack.c | |
parent | 46b4e37c9e0619d0cf065ba207c29996b326a06f (diff) | |
download | glibc-release/2.42/master.zip glibc-release/2.42/master.tar.gz glibc-release/2.42/master.tar.bz2 |
nptl: Fix MADV_GUARD_INSTALL logic for thread without guard page (BZ 33356)release/2.42/master
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>
(cherry picked from commit 855bfa2566bbefefa27c516b344df58a75824a5c)
Diffstat (limited to 'nptl/allocatestack.c')
-rw-r--r-- | nptl/allocatestack.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index 800ca89..fb8a60a 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -240,7 +240,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 @@ -258,11 +258,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: |