Created attachment 5126 [details] small test case (tar file containing try1.c and try1so.c) When glibc dlopens an object that requires executable stack, it honours that request by using mprotect to change the perms on the main thread stack + probably various others from rw- to rwx (at sysdeps/unix/sysv/linux/dl-execstack.c:57) For the main thread stack, it quite often misses out the last (highest addressed) page of the stack, or the last 2 pages of the stack. You can see this by looking at /proc/../maps for the process before and after the dlopen -- the [stack] entry is split into two pieces by the call. The number of pages missed by the mprotect changes from run to run in an apparently random way (ASLR induced, perhaps) but is always either 0, 1 or 2. For code which tries to determine the last page in the stack by calling pthread_attr_getstack and adding the returned stackaddr and stacksize values, this causes different values before and after the call. This causes debug builds of Firefox to assert during Javascript garbage collection (requiring stack scanning) if the Firefox process has previously dlopened any object requiring execstack, as some graphics drivers do. See https://bugzilla.mozilla.org/show_bug.cgi?id=608526 If the loaded object is not marked as requiring execstack then none of these inconsistencies happen. Small test case attached (tar file with try1.c and try1so.c): $ gcc -g -Wall -shared -o try1so.so try1so.c $ gcc -g -Wall -o try1 try1.c -ldl -lpthread $ execstack -q ./try1so.so - ./try1so.so $ ./try1 ## the two stack base numbers are always the same $ execstack -s ./try1so.so $ execstack -q ./try1so.so X ./try1so.so $ ./try1 ## the two stack base numbers differ by 0, 1 or 2 ## pages Confirmed on Ubuntu 10.04 (x86_64), 10.10 (x86_64) and Fedora 13 (x86_64). These last two are glibc-2.12.1.
The arguments and environment strings are located above the initial stack pointer.
There is nothing wrong. Only the parts of the stack which have to be executable are made executable. There is a lot of other data on the stack. Making that code executable would just create potential security problem especially since the environment variables are there and those are controlled by the user.
(In reply to comment #2) > There is nothing wrong. Only the parts of the stack which have to be > executable are made executable. That's fair enough -- I suspected that was the reason. The problem is not that the mprotect is wrong. The problem is that after the mprotect happens, pthread_attr_getstack produces values that are different from what it produced before the mprotect happened. In this case we have an application (Firefox 4 beta) computing the address for the top end of the stack by adding the .stackaddr and .stacksize values returned from pthread_attr_getstack, and being confused because this value changes when the stack becomes executable.
I reopen the bug and change the title to reflect the precise nature of this bug. It would be nice if pthread_attr_getstack returns consistent results.
This has been fixed with the fix to bug 12416. *** This bug has been marked as a duplicate of bug 12416 ***