Hey, just a quick heads-up (in case you're not aware). We over at Arch Linux have a received a few regression reports about various downstream projects impacted by the "dlopen and dlmopen no longer make the stack executable if a shared library requires it" change that was mentioned in the 2.41 release announcement i.e. this commit: https://sourceware.org/pipermail/libc-alpha/2024-December/163146.html It's mainly closed source apps like "discord", some Steam games, but also "julia" language and possibly a few others. Some more details here: https://gitlab.archlinux.org/archlinux/packaging/packages/glibc/-/issues/19 Anyway, AFAICT all these projects need to adapt i.e. fix their code. But we just wanted to let you know just in case you were not anticipating any breakage/compat issues. Feel free to close this ticket ASAP if this is all "going to plan". Thanks!
Wanted to add some additional context: This also affects Mono for 32-bit systems in particular; libmono appears to set RWE but only for i386; whether or not it's actually used I can't say for sure but this effectively means .NET will be broken for that architecture if dynamically loaded. The biggest consumer I'm aware of is Unity3D, which dlopens libmono rather than directly linking to it. Another example (albeit proprietary this time) is FMOD Studio; for whatever reason their libraries are marked RWE for all architectures so users have to manually strip out the flag: https://steamcommunity.com/app/504230/discussions/4/601895505111349304/ Luckily 'execstack -c' appears to work, but I'm not sure how or why this is set - from the developer side I'd personally be happy with loading the library and just letting attempts to execute stack memory fail (like it really should...), maybe with a warning in the system log saying "shared object X requested execstack, ignoring." Either way, thanks in advance for your time!
(In reply to Ethan Lee from comment #1) > Wanted to add some additional context: > > This also affects Mono for 32-bit systems in particular; libmono appears to > set RWE but only for i386; whether or not it's actually used I can't say for > sure but this effectively means .NET will be broken for that architecture if > dynamically loaded. The biggest consumer I'm aware of is Unity3D, which > dlopens libmono rather than directly linking to it. > > Another example (albeit proprietary this time) is FMOD Studio; for whatever > reason their libraries are marked RWE for all architectures so users have to > manually strip out the flag: > > https://steamcommunity.com/app/504230/discussions/4/601895505111349304/ Indeed, I expected some breakage since after CVE-2023-38408 [1], some distros found some other libraries potentially loaded with dlopen with an executable stack. The main problem is that this approach was never really reliable either, especially now in a more multithread world. The glibc never stopped program execution while changing the thread stack, so it was always subject to a thread creating another thread during the permission change, which led the program to an unreliable state (where some threads have an executable stack, while others don't). We also have the main drive of this change, which silent changing program security expectations is *really* (and I can't express really) bad semantic security-wise (the exploitable CVE is just a real-world example). On old ABIs non-executable stack is done through explicit setting -z,noexecstack (it is done automatically by a recent toolchain though). > > Luckily 'execstack -c' appears to work, but I'm not sure how or why this is > set - from the developer side I'd personally be happy with loading the > library and just letting attempts to execute stack memory fail (like it > really should...), maybe with a warning in the system log saying "shared > object X requested execstack, ignoring." This might be recipe for more trouble, since it is usually leads to very hard to debug issues. But if this is really required, one option would be to add glibc tunable to accomplish it. The execstack should work, since the problem is having the program started by the kernel without an exectuable stack (there still the issue of binaries without a PT_GNU_STACK, which implies executable stack). > > Either way, thanks in advance for your time!
Per azanella's comment, I'd say it's WONTFIX/INVALID. Thanks for the headsup but I don't consider there anything for us to do here. Andreas as RM (or anyone else) is free to reopen if they want, ofc.
Fair enough - one last thing: > On old ABIs non-executable stack is done through explicit setting -z,noexecstack (it is done automatically by a recent toolchain though). Do we know which GCC version made this change? I'd like to try and put something together that lets developers know how to avoid this either with a newer toolchain or their existing one; after asking around it seems like this happens either because an old toolchain was used or there's handwritten asm that causes the compiler/assembler to assume RWE is required. The former seems easy enough to document, but I'm not sure about the latter... basically I'd just like to have something to point to that explains what to do about GCC potentially making binaries that don't work with glibc anymore.
We could check for the READ_IMPLIES_EXEC personality and disable the error. This may be more convenient to set up than an environment variable.
(In reply to Florian Weimer from comment #5) > We could check for the READ_IMPLIES_EXEC personality and disable the error. > This may be more convenient to set up than an environment variable. I think we will still need call _dl_make_stack_executable in such cases as well, if the idea is to keep compatibility.
Let me try to answer this and correct some possible misconceptions. (In reply to Ethan Lee from comment #4) > Fair enough - one last thing: > > > On old ABIs non-executable stack is done through explicit setting -z,noexecstack (it is done automatically by a recent toolchain though). > > Do we know which GCC version made this change? On GCC side, nothing changed. GCC always properly marks the assembly it produces, even if you use inline asm in C and C++. The assembly produced by GCC is always marked as no-exec-stack, except if the code uses nested functions and passes pointers to such functions in a way that generating executable trampolines on the stack becomes necessary — IOW, only in obscure cases. The problem is usually with hand-written assembly files, not inline assembly. By default, assembler does not synthesize .note.GNU-stack. When object files without .note.GNU-stack are linked with others, on 32-bit and 64-bit x86 the linker marks the resulting executable/library for exec-stack — i.e. omission of explicit mark on an object file is treated as "needs exec-stack". What recently changed is that binutils configure gained --disable-default-execstack option to treat omitted .note.GNU-stack as "doesn't need exec-stack". > I'd like to try and put > something together that lets developers know how to avoid this either with a > newer toolchain or their existing one; With a sufficiently new linker it's possible to upgrade exec-stack warnings to errors with -Wl,--error-execstack (and then fix the sources). If in a hurry and the code doesn't actually need executable stack anywhere, -Wl,-z,noexecstack will force it off at link time. See https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart on how to fix hand-written files (GNU as and NASM need different incantations). > after asking around it seems like > this happens either because an old toolchain was used or there's handwritten > asm that causes the compiler/assembler to assume RWE is required. The former > seems easy enough to document, but I'm not sure about the latter... > basically I'd just like to have something to point to that explains what to > do about GCC potentially making binaries that don't work with glibc anymore. Happy to answer any further questions.
(In reply to Alexander Monakov from comment #7) > Let me try to answer this and correct some possible misconceptions. > > (In reply to Ethan Lee from comment #4) > > Fair enough - one last thing: > > > > > On old ABIs non-executable stack is done through explicit setting -z,noexecstack (it is done automatically by a recent toolchain though). > > > > Do we know which GCC version made this change? > > On GCC side, nothing changed. GCC always properly marks the assembly it > produces, even if you use inline asm in C and C++. The assembly produced by > GCC is always marked as no-exec-stack, except if the code uses nested > functions and passes pointers to such functions in a way that generating > executable trampolines on the stack becomes necessary — IOW, only in obscure > cases. This is not accurate. In Debian, GCC 3.2.3 did not emit markers on i386, but GCC 3.4.6 did. This is more recent than I expected. It's probably because there wasn't much reason to do this before PAE with the Execute-Disable bit arrived.
(In reply to Florian Weimer from comment #8) > This is not accurate. In Debian, GCC 3.2.3 did not emit markers on i386, but > GCC 3.4.6 did. This is more recent than I expected. It's probably because > there wasn't much reason to do this before PAE with the Execute-Disable bit > arrived. Indeed, it was changed in June 2003 for gcc-3.4 and backported later that year to the gcc-3.3 branch: https://inbox.sourceware.org/gcc-patches/20030604063846.GY24872@sunsite.ms.mff.cuni.cz/ I didn't realize Adhemerval was talking about that kind of "old".
(In reply to Adhemerval Zanella from comment #6) > (In reply to Florian Weimer from comment #5) > > We could check for the READ_IMPLIES_EXEC personality and disable the error. > > This may be more convenient to set up than an environment variable. > > I think we will still need call _dl_make_stack_executable in such cases as > well, if the idea is to keep compatibility. I don't think so. The kernel already makes the mappings executable for us if the READ_IMPLIES_EXEC personality is active.
(In reply to Alexander Monakov from comment #9) > (In reply to Florian Weimer from comment #8) > > This is not accurate. In Debian, GCC 3.2.3 did not emit markers on i386, but > > GCC 3.4.6 did. This is more recent than I expected. It's probably because > > there wasn't much reason to do this before PAE with the Execute-Disable bit > > arrived. > > Indeed, it was changed in June 2003 for gcc-3.4 and backported later that > year to the gcc-3.3 branch: > https://inbox.sourceware.org/gcc-patches/20030604063846.GY24872@sunsite.ms. > mff.cuni.cz/ > > I didn't realize Adhemerval was talking about that kind of "old". Of course the binaries are that old. I expect they were built right around the transition: the main program with a slightly newer GCC than that engine.so shared object. That's why the main program has markup, but the shared object does not.
(In reply to Florian Weimer from comment #11) > Of course the binaries are that old. Why would they be? Linux port of Half-Life was released in 2013, not 2003. > I expect they were built right around > the transition: the main program with a slightly newer GCC than that > engine.so shared object. That's why the main program has markup, but the > shared object does not. Do you think this is more likely than an unannotated asm file linked into engine.so?
Filed PR32671 to discuss binutils behaviour to upgrade these to build failures in more cases.
(In reply to Alexander Monakov from comment #12) > (In reply to Florian Weimer from comment #11) > > Of course the binaries are that old. > > Why would they be? Linux port of Half-Life was released in 2013, not 2003. The previous binaries we saw in bug 25203 were linked against glibc 2.0. It's possible that they reused some server code when they released the Linux client, I suppose.
(In reply to Florian Weimer from comment #10) > (In reply to Adhemerval Zanella from comment #6) > > (In reply to Florian Weimer from comment #5) > > > We could check for the READ_IMPLIES_EXEC personality and disable the error. > > > This may be more convenient to set up than an environment variable. > > > > I think we will still need call _dl_make_stack_executable in such cases as > > well, if the idea is to keep compatibility. > > I don't think so. The kernel already makes the mappings executable for us if > the READ_IMPLIES_EXEC personality is active. But afaik the kernel will still not make the stack executable if PT_GNU_STACK exists and have the executable bit. From the bug reports, the issue seems to be ET_EXEC with PT_GNU_STACK set to RW trying to load a ET_DYN with PT_GNU_STACK set to RWE (or without a PT_GNU_STACK header, which uses the default executable stack). It also seems that most, if not all, cases are due the existent of some object (ET_REL, most likely from hard written assembly code) that make the linker sets a exectuable stack. However, we can also not be sure if this is the case and not the the modules does require an exectuable stack for some reason (gcc trampoline, etc.). We can't just ignore, but since this is a compatibility issues I think the most straightforward solution would still mimic the old behaviour. These binaries works with an executable stack anyway, and I don't think they are a security issue. So I think we might have some options here: 1. If the default ABI (without a PT_GNU_STACK header) requires an exectuable stack; at program startup checks the personality flag for READ_IMPLIES_EXEC (we can make it during dlopen). After DT_NEEDED loading, we call _dl_make_stack_executable and make the stack executable; even for programs that do not require it (and off course we don't do this for setuid programs). Any dlopen will work regardless of PT_GNU_STACK, since the stack is exectuable anyway. The con is now we are slight changing how setarch -R works wrt glibc. 2. Add a new value for glibc.rtld.execstack, to basically does 1. The con is now we have a environment variable that sets the stack exectuable, and even x86_64 have DEFAULT_STACK_PERMS sets to (PF_R|PF_W|PF_X).
(In reply to Adhemerval Zanella from comment #15) > > 1. If the default ABI (without a PT_GNU_STACK header) requires an exectuable > stack; at program startup checks the personality flag for READ_IMPLIES_EXEC > (we can make it during dlopen). After DT_NEEDED loading, we call I meant that we can *not* make during dlopen, we need to setup the stack executable before any dlopen call.
(In reply to Adhemerval Zanella from comment #15) > (In reply to Florian Weimer from comment #10) > > (In reply to Adhemerval Zanella from comment #6) > > > (In reply to Florian Weimer from comment #5) > > > > We could check for the READ_IMPLIES_EXEC personality and disable the error. > > > > This may be more convenient to set up than an environment variable. > > > > > > I think we will still need call _dl_make_stack_executable in such cases as > > > well, if the idea is to keep compatibility. > > > > I don't think so. The kernel already makes the mappings executable for us if > > the READ_IMPLIES_EXEC personality is active. > > But afaik the kernel will still not make the stack executable if > PT_GNU_STACK exists and have the executable bit. From the bug reports, the > issue seems to be ET_EXEC with PT_GNU_STACK set to RW trying to load a > ET_DYN with PT_GNU_STACK set to RWE (or without a PT_GNU_STACK header, which > uses the default executable stack). It's true that the stack will be mapped as rw-p and not as rwxp as reported in /proc/self/maps. But the difference does not matter because for a READ_IMPLIES_EXEC process, the page tables are set up in such a way that execution is not disabled for pages with read access. This is matches the historic Linux behavior: the kernel tracks PROT_READ and PROT_EXEC independently even on platforms where the CPU does not make a distinction. It's confusing. The gist is that if READ_IMPLIES_EXEC is active, we should not error out in dlopen, without doing anything else.
(In reply to Florian Weimer from comment #17) > (In reply to Adhemerval Zanella from comment #15) > > (In reply to Florian Weimer from comment #10) > > > (In reply to Adhemerval Zanella from comment #6) > > > > (In reply to Florian Weimer from comment #5) > > > > > We could check for the READ_IMPLIES_EXEC personality and disable the error. > > > > > This may be more convenient to set up than an environment variable. > > > > > > > > I think we will still need call _dl_make_stack_executable in such cases as > > > > well, if the idea is to keep compatibility. > > > > > > I don't think so. The kernel already makes the mappings executable for us if > > > the READ_IMPLIES_EXEC personality is active. > > > > But afaik the kernel will still not make the stack executable if > > PT_GNU_STACK exists and have the executable bit. From the bug reports, the > > issue seems to be ET_EXEC with PT_GNU_STACK set to RW trying to load a > > ET_DYN with PT_GNU_STACK set to RWE (or without a PT_GNU_STACK header, which > > uses the default executable stack). > > It's true that the stack will be mapped as rw-p and not as rwxp as reported > in /proc/self/maps. But the difference does not matter because for a > READ_IMPLIES_EXEC process, the page tables are set up in such a way that > execution is not disabled for pages with read access. This is matches the > historic Linux behavior: the kernel tracks PROT_READ and PROT_EXEC > independently even on platforms where the CPU does not make a distinction. > It's confusing. > > The gist is that if READ_IMPLIES_EXEC is active, we should not error out in > dlopen, without doing anything else. Are you sure about it? This is not what I am seeing on a x86_64 kernel (6.8.0-52-generic): $ cat test.c #include <stdio.h> #include <string.h> #include <assert.h> #include <sys/personality.h> #include <stdint.h> int main () { int p = personality (0xffffffff); printf ("READ_IMPLIES_EXEC: %d\n", p & READ_IMPLIES_EXEC); FILE *f = fopen ("/proc/self/maps", "r"); assert (f != NULL); char *line = NULL; size_t linesz = 0; while (getline (&line, &linesz, f) != -1) if (strstr (line, "[stack]")) printf ("%s", line); uint8_t foo[] = { 0x55, // push %ebp 0x89, 0xe5, // mov %esp,%ebp 0xb8, 0x2a, 0x00, 0x00, 0x00, // mov $0x2a,%eax 0x5d, // pop %ebp 0xc3, // ret }; int (*foo_ptr) (void) = (void *) foo; printf ("foo=%d\n", foo_ptr()); return 0; } $ cc -m32 test.c -o test-m32.o -c $ cc -m32 -Wl,-z,execstack test-m32.o -o test-m32-execstack $ cc -m32 -Wl,-z,noexecstack test-m32.o -o test-m32-noexecstack $ ./test-m32-execstack READ_IMPLIES_EXEC: 0 ffc95000-ffcb6000 rwxp 00000000 00:00 0 [stack] foo=42 $ ./test-m32-noexecstack READ_IMPLIES_EXEC: 0 ffbb8000-ffbd9000 rw-p 00000000 00:00 0 [stack] Segmentation fault (core dumped) $ setarch -X ./test-m32-noexecstack READ_IMPLIES_EXEC: 4194304 ffa10000-ffa31000 rw-p 00000000 00:00 0 [stack] Segmentation fault (core dumped) What I am missing here?
execstack implies READ_IMPLIES_EXEC, but not vice versa. READ_IMPLIES_EXEC is checked in the mmap syscall, but setup_arg_pages only considers the execstack flag when mapping the stack.
(In reply to Adhemerval Zanella from comment #18) > > The gist is that if READ_IMPLIES_EXEC is active, we should not error out in > > dlopen, without doing anything else. > > Are you sure about it? This is not what I am seeing on a x86_64 kernel > (6.8.0-52-generic): I *was* sure about it, but it turns out that PT_GNU_STACK overrides the READ_IMPLIES_EXEC personality for the initial stack. The personality is applied to the stacks that glibc maps, as I expected.
(In reply to Florian Weimer from comment #20) > (In reply to Adhemerval Zanella from comment #18) > > > The gist is that if READ_IMPLIES_EXEC is active, we should not error out in > > > dlopen, without doing anything else. > > > > Are you sure about it? This is not what I am seeing on a x86_64 kernel > > (6.8.0-52-generic): > > I *was* sure about it, but it turns out that PT_GNU_STACK overrides the > READ_IMPLIES_EXEC personality for the initial stack. The personality is > applied to the stacks that glibc maps, as I expected. Right, so it seems that only ignoring PT_GNU_STACK on dlopen does not solve all the compatibility issues. I am more inclined to extend the glibc.rtld.execstack, but I don't have a strong opinion here.
This issue was discussed in the Monday morning patch queue review meeting (2025-02-10) and given the discussions and impact on backwards compatibility I'm reopening this bug in order to use it to consider possible options for the release and the applications involved.
(In reply to Adhemerval Zanella from comment #15) > > 1. If the default ABI (without a PT_GNU_STACK header) requires an exectuable > stack; at program startup checks the personality flag for READ_IMPLIES_EXEC > (we can make it during dlopen). After DT_NEEDED loading, we call > _dl_make_stack_executable and make the stack executable; even for programs > that do not require it (and off course we don't do this for setuid > programs). Any dlopen will work regardless of PT_GNU_STACK, since the stack > is exectuable anyway. The con is now we are slight changing how setarch -R > works wrt glibc. And it seems not all architectures keeps the READ_IMPLIES_EXEC over process execution, on x86_64: arch/x86/kernel/process_64.c 715 void set_personality_64bit(void) 716 { 717 /* inherit personality from parent */ 718 719 /* Make sure to be in 64bit mode */ 720 clear_thread_flag(TIF_ADDR32); 721 /* Pretend that this comes from a 64bit execve */ 722 task_pt_regs(current)->orig_ax = __NR_execve; 723 current_thread_info()->status &= ~TS_COMPAT; 724 if (current->mm) 725 __set_bit(MM_CONTEXT_HAS_VSYSCALL, ¤t->mm->context.flags); 726 727 /* TBD: overwrites user setup. Should have two bits. 728 But 64bit processes have always behaved this way, 729 so it's not too bad. The main problem is just that 730 32bit children are affected again. */ 731 current->personality &= ~READ_IMPLIES_EXEC; 732 } So it seems we need a glibc tunable to enable this workaround.
Given the extent of the regressions (Matlab is also affected), I think it would be wise to add the override and workaround, per this patch[1] (2046742). Is there any status or progress on this? [1]: https://patchwork.ozlabs.org/project/glibc/patch/20250213170343.1265362-1-adhemerval.zanella@linaro.org/ Thank you
(In reply to Calum McConnell from comment #24) > Given the extent of the regressions (Matlab is also affected), I think it > would be wise to add the override and workaround, per this patch[1] > (2046742). Is there any status or progress on this? > > [1]: > https://patchwork.ozlabs.org/project/glibc/patch/20250213170343.1265362-1- > adhemerval.zanella@linaro.org/ > > Thank you It is still under review, I will raise this once the weekly call.
Fixed on 2.42. I think it should be backportable to 2.41 if required.
2.41 is the version of GLIBC in Debian Trixie, so I think a backport would be a good idea. This way there will be one solution for the issue when folks go looking for it in a few years time.
(In reply to Calum McConnell from comment #27) > 2.41 is the version of GLIBC in Debian Trixie, so I think a backport would > be a good idea. This way there will be one solution for the issue when > folks go looking for it in a few years time. This was backported to glibc 2.41 today (release/2.41/master), so this is out for use by any distribution that is pulling from the rolling release branch. https://sourceware.org/cgit/glibc/commit/?h=release/2.41/master&id=b861755a84eeccdd9183989ca71b3b1251c83a74
The 2.41 backport causes a build failure for me on arm-linux-gnueabihf (32-bit ARM) when linking libc.so: ld: /src/sys/glibc/cross/linux-armv7/work/build/libc_pic.os.clean: in function `__gnu_Unwind_Find_exidx': /src/sys/glibc/cross/linux-armv7/work/b861755a84eeccdd9183989ca71b3b1251c83a74/elf/../sysdeps/arm/find_exidx.c:26:(.text+0x12bd64): undefined reference to `__GI___dl_find_object' Looking at the backported patch, it adds dl-find_object to dl-routines in elf/Makefile, but dl-find_object is still in routines in 2.41; does this patch need to be backported too? https://sourceware.org/git/?p=glibc.git;a=commit;h=96429bcc91a14f71b177ddc5e716de3069060f2c
(In reply to Adam Sampson from comment #29) > The 2.41 backport causes a build failure for me on arm-linux-gnueabihf > (32-bit ARM) when linking libc.so: > > ld: /src/sys/glibc/cross/linux-armv7/work/build/libc_pic.os.clean: in > function `__gnu_Unwind_Find_exidx': > /src/sys/glibc/cross/linux-armv7/work/ > b861755a84eeccdd9183989ca71b3b1251c83a74/elf/../sysdeps/arm/find_exidx.c:26: > (.text+0x12bd64): undefined reference to `__GI___dl_find_object' > > Looking at the backported patch, it adds dl-find_object to dl-routines in > elf/Makefile, but dl-find_object is still in routines in 2.41; does this > patch need to be backported too? > > https://sourceware.org/git/?p=glibc.git;a=commit; > h=96429bcc91a14f71b177ddc5e716de3069060f2c Sigh, I had this fixed locally but I forgot to git add before commit. Fixed now.
The master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=0c3425942374e72c3bcac28b2578117d36b0f9df commit 0c3425942374e72c3bcac28b2578117d36b0f9df Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> Date: Thu Apr 24 12:27:44 2025 -0300 nptl: Fix pthread_getattr_np when modules with execstack are allowed (BZ 32897) The BZ 32653 fix (12a497c716f0a06be5946cabb8c3ec22a079771e) kept the stack pointer zeroing from make_main_stack_executable on _dl_make_stack_executable. However, previously the 'stack_endp' pointed to temporary variable created before the call of _dl_map_object_from_fd; while now we use the __libc_stack_end directly. Since pthread_getattr_np relies on correct __libc_stack_end, if _dl_make_stack_executable is called (for instance, when glibc.rtld.execstack=2 is set) __libc_stack_end will be set to zero, and the call will always fail. The __libc_stack_end zero was used a mitigation hardening, but since 52a01100ad011293197637e42b5be1a479a2f4ae it is used solely on pthread_getattr_np code. So there is no point in zeroing anymore. Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: Sam James <sam@gentoo.org>
The release/2.41/master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=5b4c4617016d28569106549dff6f9fec73eed5ce commit 5b4c4617016d28569106549dff6f9fec73eed5ce Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> Date: Thu Apr 24 12:27:44 2025 -0300 nptl: Fix pthread_getattr_np when modules with execstack are allowed (BZ 32897) The BZ 32653 fix (12a497c716f0a06be5946cabb8c3ec22a079771e) kept the stack pointer zeroing from make_main_stack_executable on _dl_make_stack_executable. However, previously the 'stack_endp' pointed to temporary variable created before the call of _dl_map_object_from_fd; while now we use the __libc_stack_end directly. Since pthread_getattr_np relies on correct __libc_stack_end, if _dl_make_stack_executable is called (for instance, when glibc.rtld.execstack=2 is set) __libc_stack_end will be set to zero, and the call will always fail. The __libc_stack_end zero was used a mitigation hardening, but since 52a01100ad011293197637e42b5be1a479a2f4ae it is used solely on pthread_getattr_np code. So there is no point in zeroing anymore. Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: Sam James <sam@gentoo.org> (cherry picked from commit 0c3425942374e72c3bcac28b2578117d36b0f9df)