Bug 12225 - pthread_attr_getstack result can change after dlopen of object requiring execstack
Summary: pthread_attr_getstack result can change after dlopen of object requiring exec...
Status: RESOLVED DUPLICATE of bug 12416
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.12
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-17 21:14 UTC by Julian Seward
Modified: 2014-06-27 14:02 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
small test case (tar file containing try1.c and try1so.c) (812 bytes, application/x-tar)
2010-11-17 21:14 UTC, Julian Seward
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Julian Seward 2010-11-17 21:14:30 UTC
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.
Comment 1 Andreas Schwab 2010-12-16 13:01:36 UTC
The arguments and environment strings are located above the initial stack pointer.
Comment 2 Ulrich Drepper 2010-12-20 03:34:03 UTC
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.
Comment 3 Julian Seward 2011-01-03 14:02:18 UTC
(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.
Comment 4 Igor Bukanov 2011-07-20 11:59:12 UTC
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.
Comment 5 Siddhesh Poyarekar 2012-10-03 18:17:49 UTC
This has been fixed with the fix to bug 12416.

*** This bug has been marked as a duplicate of bug 12416 ***