chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / elf / tst-execstack.c
1 /* Test program for making nonexecutable stacks executable
2    on load of a DSO that requires executable stacks.  */
3
4 #include <dlfcn.h>
5 #include <stdbool.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <error.h>
10
11 static void
12 print_maps (void)
13 {
14 #if 0
15   char *cmd = NULL;
16   asprintf (&cmd, "cat /proc/%d/maps", getpid ());
17   system (cmd);
18   free (cmd);
19 #endif
20 }
21
22 static void deeper (void (*f) (void));
23
24 #if USE_PTHREADS
25 # include <pthread.h>
26
27 static void *
28 tryme_thread (void *f)
29 {
30   (*((void (*) (void)) f)) ();
31
32   return 0;
33 }
34
35 static pthread_barrier_t startup_barrier, go_barrier;
36 static void *
37 waiter_thread (void *arg)
38 {
39   void **f = arg;
40   pthread_barrier_wait (&startup_barrier);
41   pthread_barrier_wait (&go_barrier);
42
43   (*((void (*) (void)) *f)) ();
44
45   return 0;
46 }
47 #endif
48
49
50 static bool allow_execstack = true;
51
52
53 static int
54 do_test (void)
55 {
56   /* Check whether SELinux is enabled and disallows executable stacks.  */
57   FILE *fp = fopen ("/selinux/enforce", "r");
58   if (fp != NULL)
59     {
60       char *line = NULL;
61       size_t linelen = 0;
62
63       bool enabled = false;
64       ssize_t n = getline (&line, &linelen, fp);
65       if (n > 0 && line[0] != '0')
66         enabled = true;
67
68       fclose (fp);
69
70       if (enabled)
71         {
72           fp = fopen ("/selinux/booleans/allow_execstack", "r");
73           if (fp != NULL)
74             {
75               n = getline (&line, &linelen, fp);
76               if (n > 0 && line[0] == '0')
77                 allow_execstack = false;
78             }
79
80           fclose (fp);
81         }
82     }
83
84   printf ("executable stacks %sallowed\n", allow_execstack ? "" : "not ");
85
86   static void *f;               /* Address of this is used in other threads. */
87
88 #if USE_PTHREADS
89   /* Create some threads while stacks are nonexecutable.  */
90   #define N 5
91   pthread_t thr[N];
92
93   pthread_barrier_init (&startup_barrier, NULL, N + 1);
94   pthread_barrier_init (&go_barrier, NULL, N + 1);
95
96   for (int i = 0; i < N; ++i)
97     {
98       int rc = pthread_create (&thr[i], NULL, &waiter_thread, &f);
99       if (rc)
100         error (1, rc, "pthread_create");
101     }
102
103   /* Make sure they are all there using their stacks.  */
104   pthread_barrier_wait (&startup_barrier);
105   puts ("threads waiting");
106 #endif
107
108   print_maps ();
109
110   /* Loading this module should force stacks to become executable.  */
111   void *h = dlopen ("tst-execstack-mod.so", RTLD_LAZY);
112   if (h == NULL)
113     {
114       printf ("cannot load: %s\n", dlerror ());
115       return allow_execstack;
116     }
117
118   f = dlsym (h, "tryme");
119   if (f == NULL)
120     {
121       printf ("symbol not found: %s\n", dlerror ());
122       return 1;
123     }
124
125   /* Test if that really made our stack executable.
126      The `tryme' function should crash if not.  */
127
128   (*((void (*) (void)) f)) ();
129
130   print_maps ();
131
132   /* Test that growing the stack region gets new executable pages too.  */
133   deeper ((void (*) (void)) f);
134
135   print_maps ();
136
137 #if USE_PTHREADS
138   /* Test that a fresh thread now gets an executable stack.  */
139   {
140     pthread_t th;
141     int rc = pthread_create (&th, NULL, &tryme_thread, f);
142     if (rc)
143       error (1, rc, "pthread_create");
144   }
145
146   puts ("threads go");
147   /* The existing threads' stacks should have been changed.
148      Let them run to test it.  */
149   pthread_barrier_wait (&go_barrier);
150
151   pthread_exit ((void *) (long int) (! allow_execstack));
152 #endif
153
154   return ! allow_execstack;
155 }
156
157 static void
158 deeper (void (*f) (void))
159 {
160   char stack[1100 * 1024];
161   memfrob (stack, sizeof stack);
162   (*f) ();
163   memfrob (stack, sizeof stack);
164 }
165
166
167 #define TEST_FUNCTION do_test ()
168 #include "../test-skeleton.c"