diff options
author | Roland McGrath <roland@gnu.org> | 2003-09-23 12:07:26 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2003-09-23 12:07:26 +0000 |
commit | 2abf9ff11384a47dc456c138a8faf6b1469aac2b (patch) | |
tree | d0ccba6b9bf3096c8d1d2d209984bf4d28597408 /elf/tst-execstack.c | |
parent | ecdeaac05f73c29eca92eecd55ad4fb8513c7771 (diff) | |
download | glibc-2abf9ff11384a47dc456c138a8faf6b1469aac2b.zip glibc-2abf9ff11384a47dc456c138a8faf6b1469aac2b.tar.gz glibc-2abf9ff11384a47dc456c138a8faf6b1469aac2b.tar.bz2 |
* sysdeps/i386/dl-machine.h (RTLD_START): Set __libc_stack_end before
calling _dl_start, using GOTOFF access.
* configure.in (libc_cv_z_execstack): New check.
* configure: Regenerated.
* config.make.in (have-z-execstack): New variable set by it.
* elf/tst-execstack.c: New file.
* elf/tst-execstack-mod.c: New file.
* elf/tst-execstack-needed.c: New file.
* elf/Makefile (tests-execstack-yes, modules-execstack-yes): New
variables.
(tests, modules-names): Conditionally include them.
(distribute): Add tst-execstack-mod.c here.
($(objpfx)tst-execstack, $(objpfx)tst-execstack.out): New targets.
(LDFLAGS-tst-execstack, LDFLAGS-tst-execstack-mod): New variables.
($(objpfx)tst-execstack-needed): New target.
(LDFLAGS-tst-execstack-needed): New variable.
* sysdeps/generic/ldsodefs.h (struct rtld_global): Add _dl_stack_flags
and _dl_make_stack_executable_hook. Declare _dl_make_stack_executable.
* elf/rtld.c (_rtld_global): Add initializer for _dl_stack_flags.
(dl_main): Reset _dl_stack_flags according to PT_GNU_STACK phdr.
Initialize _dl_make_stack_executable_hook.
* elf/dl-support.c: Define those new variables.
(_dl_non_dynamic_init): Scan phdrs for PT_GNU_STACK.
(_dl_phdr): Fix type.
* elf/dl-load.c (_dl_map_object_from_fd): Grok PT_GNU_STACK phdr and
enable execute permission for the stack if necessary.
* sysdeps/generic/dl-execstack.c: New file.
* elf/Makefile (dl-routines): Add it.
* elf/Versions (ld: GLIBC_PRIVATE): Add _dl_make_stack_executable.
* sysdeps/unix/sysv/linux/dl-execstack.c: New file.
Diffstat (limited to 'elf/tst-execstack.c')
-rw-r--r-- | elf/tst-execstack.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/elf/tst-execstack.c b/elf/tst-execstack.c new file mode 100644 index 0000000..21eaa9b --- /dev/null +++ b/elf/tst-execstack.c @@ -0,0 +1,133 @@ +/* Test program for making nonexecutable stacks executable + on load of a DSO that requires executable stacks. */ + +#include <dlfcn.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <error.h> + +static void +print_maps (void) +{ +#if 0 + char *cmd = NULL; + asprintf (&cmd, "cat /proc/%d/maps", getpid ()); + system (cmd); + free (cmd); +#endif +} + +static void deeper (void (*f) (void)); + +#if USE_PTHREADS +# include <pthread.h> + +static void * +tryme_thread (void *f) +{ + (*((void (*) (void)) f)) (); + + return 0; +} + +static pthread_barrier_t startup_barrier, go_barrier; +static void * +waiter_thread (void *arg) +{ + void **f = arg; + pthread_barrier_wait (&startup_barrier); + pthread_barrier_wait (&go_barrier); + + (*((void (*) (void)) *f)) (); + + return 0; +} +#endif + +static int +do_test (void) +{ + void *f; + +#if USE_PTHREADS + /* Create some threads while stacks are nonexecutable. */ + #define N 5 + pthread_t thr[N]; + + pthread_barrier_init (&startup_barrier, NULL, N + 1); + pthread_barrier_init (&go_barrier, NULL, N + 1); + + for (int i = 0; i < N; ++i) + { + int rc = pthread_create (&thr[i], NULL, &waiter_thread, &f); + if (rc) + error (1, rc, "pthread_create"); + } + + /* Make sure they are all there using their stacks. */ + pthread_barrier_wait (&startup_barrier); + puts ("threads waiting"); +#endif + + print_maps (); + + /* Loading this module should force stacks to become executable. */ + void *h = dlopen ("tst-execstack-mod.so", RTLD_LAZY); + if (h == NULL) + { + printf ("cannot load: %s\n", dlerror ()); + return 1; + } + + f = dlsym (h, "tryme"); + if (f == NULL) + { + printf ("symbol not found: %s\n", dlerror ()); + return 1; + } + + /* Test if that really made our stack executable. + The `tryme' function should crash if not. */ + + (*((void (*) (void)) f)) (); + + print_maps (); + + /* Test that growing the stack region gets new executable pages too. */ + deeper ((void (*) (void)) f); + + print_maps (); + +#if USE_PTHREADS + /* Test that a fresh thread now gets an executable stack. */ + { + pthread_t th; + int rc = pthread_create (&th, NULL, &tryme_thread, f); + if (rc) + error (1, rc, "pthread_create"); + } + + puts ("threads go"); + /* The existing threads' stacks should have been changed. + Let them run to test it. */ + pthread_barrier_wait (&go_barrier); + + pthread_exit (0); +#endif + + return 0; +} + +static void +deeper (void (*f) (void)) +{ + char stack[1100 * 1024]; + memfrob (stack, sizeof stack); + (*f) (); + memfrob (stack, sizeof stack); +} + + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |