Introduce NO_RTLD_HIDDEN, make hurd use it instead of NO_HIDDEN
[glibc.git] / nptl / tst-stackguard1.c
blob0f21d0ddc321ba3095fe90858869b284f30dd3a7
1 /* Copyright (C) 2005-2017 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <errno.h>
20 #include <pthread.h>
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/wait.h>
27 #include <stackguard-macros.h>
28 #include <tls.h>
29 #include <unistd.h>
31 static const char *command;
32 static bool child;
33 static uintptr_t stack_chk_guard_copy;
34 static bool stack_chk_guard_copy_set;
35 static int fds[2];
37 static void __attribute__ ((constructor))
38 con (void)
40 stack_chk_guard_copy = STACK_CHK_GUARD;
41 stack_chk_guard_copy_set = true;
44 static int
45 uintptr_t_cmp (const void *a, const void *b)
47 if (*(uintptr_t *) a < *(uintptr_t *) b)
48 return 1;
49 if (*(uintptr_t *) a > *(uintptr_t *) b)
50 return -1;
51 return 0;
54 static void *
55 tf (void *arg)
57 if (stack_chk_guard_copy != STACK_CHK_GUARD)
59 puts ("STACK_CHK_GUARD changed in thread");
60 return (void *) 1L;
62 return NULL;
65 static int
66 do_test (void)
68 if (!stack_chk_guard_copy_set)
70 puts ("constructor has not been run");
71 return 1;
74 if (stack_chk_guard_copy != STACK_CHK_GUARD)
76 puts ("STACK_CHK_GUARD changed between constructor and do_test");
77 return 1;
80 if (child)
82 int i;
83 pthread_t th[4];
84 void *ret;
85 for (i = 0; i < 4; ++i)
86 if (pthread_create (&th[i], NULL, tf, NULL))
88 puts ("thread creation failed");
89 return 1;
91 for (i = 0; i < 4; ++i)
92 if (pthread_join (th[i], &ret))
94 puts ("thread join failed");
95 return 1;
97 else if (ret != NULL)
98 return 1;
100 write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
101 return 0;
104 if (command == NULL)
106 puts ("missing --command or --child argument");
107 return 1;
110 #define N 16
111 uintptr_t child_stack_chk_guards[N + 1];
112 child_stack_chk_guards[N] = stack_chk_guard_copy;
113 int i;
114 for (i = 0; i < N; ++i)
116 if (pipe (fds) < 0)
118 printf ("couldn't create pipe: %m\n");
119 return 1;
122 pid_t pid = fork ();
123 if (pid < 0)
125 printf ("fork failed: %m\n");
126 return 1;
129 if (!pid)
131 if (stack_chk_guard_copy != STACK_CHK_GUARD)
133 puts ("STACK_CHK_GUARD changed after fork");
134 exit (1);
137 close (fds[0]);
138 close (2);
139 dup2 (fds[1], 2);
140 close (fds[1]);
142 system (command);
143 exit (0);
146 close (fds[1]);
148 if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
149 sizeof (uintptr_t))) != sizeof (uintptr_t))
151 puts ("could not read stack_chk_guard value from child");
152 return 1;
155 close (fds[0]);
157 pid_t termpid;
158 int status;
159 termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
160 if (termpid == -1)
162 printf ("waitpid failed: %m\n");
163 return 1;
165 else if (termpid != pid)
167 printf ("waitpid returned %ld != %ld\n",
168 (long int) termpid, (long int) pid);
169 return 1;
171 else if (!WIFEXITED (status) || WEXITSTATUS (status))
173 puts ("child hasn't exited with exit status 0");
174 return 1;
178 qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
180 uintptr_t default_guard = 0;
181 unsigned char *p = (unsigned char *) &default_guard;
182 p[sizeof (uintptr_t) - 1] = 255;
183 p[sizeof (uintptr_t) - 2] = '\n';
184 p[0] = 0;
186 /* Test if the stack guard canaries are either randomized,
187 or equal to the default stack guard canary value.
188 Even with randomized stack guards it might happen
189 that the random number generator generates the same
190 values, but if that happens in more than half from
191 the 16 runs, something is very wrong. */
192 int ndifferences = 0;
193 int ndefaults = 0;
194 for (i = 0; i < N; ++i)
196 if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
197 ndifferences++;
198 else if (child_stack_chk_guards[i] == default_guard)
199 ndefaults++;
202 printf ("differences %d defaults %d\n", ndifferences, ndefaults);
204 if (ndifferences < N / 2 && ndefaults < N / 2)
206 puts ("stack guard canaries are not randomized enough");
207 puts ("nor equal to the default canary value");
208 return 1;
211 return 0;
214 #define OPT_COMMAND 10000
215 #define OPT_CHILD 10001
216 #define CMDLINE_OPTIONS \
217 { "command", required_argument, NULL, OPT_COMMAND }, \
218 { "child", no_argument, NULL, OPT_CHILD },
219 #define CMDLINE_PROCESS \
220 case OPT_COMMAND: \
221 command = optarg; \
222 break; \
223 case OPT_CHILD: \
224 child = true; \
225 break;
226 #define TEST_FUNCTION do_test ()
227 #include "../test-skeleton.c"