1 /* Copyright (C) 2005-2020 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 <https://www.gnu.org/licenses/>. */
27 #include <stackguard-macros.h>
31 static const char *command
;
33 static uintptr_t stack_chk_guard_copy
;
34 static bool stack_chk_guard_copy_set
;
37 static void __attribute__ ((constructor
))
40 stack_chk_guard_copy
= STACK_CHK_GUARD
;
41 stack_chk_guard_copy_set
= true;
45 uintptr_t_cmp (const void *a
, const void *b
)
47 if (*(uintptr_t *) a
< *(uintptr_t *) b
)
49 if (*(uintptr_t *) a
> *(uintptr_t *) b
)
57 if (stack_chk_guard_copy
!= STACK_CHK_GUARD
)
59 puts ("STACK_CHK_GUARD changed in thread");
68 if (!stack_chk_guard_copy_set
)
70 puts ("constructor has not been run");
74 if (stack_chk_guard_copy
!= STACK_CHK_GUARD
)
76 puts ("STACK_CHK_GUARD changed between constructor and do_test");
85 for (i
= 0; i
< 4; ++i
)
86 if (pthread_create (&th
[i
], NULL
, tf
, NULL
))
88 puts ("thread creation failed");
91 for (i
= 0; i
< 4; ++i
)
92 if (pthread_join (th
[i
], &ret
))
94 puts ("thread join failed");
100 write (2, &stack_chk_guard_copy
, sizeof (stack_chk_guard_copy
));
106 puts ("missing --command or --child argument");
111 uintptr_t child_stack_chk_guards
[N
+ 1];
112 child_stack_chk_guards
[N
] = stack_chk_guard_copy
;
114 for (i
= 0; i
< N
; ++i
)
118 printf ("couldn't create pipe: %m\n");
125 printf ("fork failed: %m\n");
131 if (stack_chk_guard_copy
!= STACK_CHK_GUARD
)
133 puts ("STACK_CHK_GUARD changed after fork");
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");
159 termpid
= TEMP_FAILURE_RETRY (waitpid (pid
, &status
, 0));
162 printf ("waitpid failed: %m\n");
165 else if (termpid
!= pid
)
167 printf ("waitpid returned %ld != %ld\n",
168 (long int) termpid
, (long int) pid
);
171 else if (!WIFEXITED (status
) || WEXITSTATUS (status
))
173 puts ("child hasn't exited with exit status 0");
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';
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;
194 for (i
= 0; i
< N
; ++i
)
196 if (child_stack_chk_guards
[i
] != child_stack_chk_guards
[i
+1])
198 else if (child_stack_chk_guards
[i
] == default_guard
)
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");
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 \
226 #define TEST_FUNCTION do_test ()
227 #include "../test-skeleton.c"