diff options
Diffstat (limited to 'REORG.TODO/elf/tst-stackguard1.c')
-rw-r--r-- | REORG.TODO/elf/tst-stackguard1.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/REORG.TODO/elf/tst-stackguard1.c b/REORG.TODO/elf/tst-stackguard1.c new file mode 100644 index 0000000000..78e33c7083 --- /dev/null +++ b/REORG.TODO/elf/tst-stackguard1.c @@ -0,0 +1,205 @@ +/* Copyright (C) 2005-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/wait.h> +#include <stackguard-macros.h> +#include <tls.h> +#include <unistd.h> + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = STACK_CHK_GUARD; + stack_chk_guard_copy_set = true; +} + +static int +uintptr_t_cmp (const void *a, const void *b) +{ + if (*(uintptr_t *) a < *(uintptr_t *) b) + return 1; + if (*(uintptr_t *) a > *(uintptr_t *) b) + return -1; + return 0; +} + +static int +do_test (void) +{ + if (!stack_chk_guard_copy_set) + { + puts ("constructor has not been run"); + return 1; + } + + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed between constructor and do_test"); + return 1; + } + + if (child) + { + write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); + return 0; + } + + if (command == NULL) + { + puts ("missing --command or --child argument"); + return 1; + } + +#define N 16 + uintptr_t child_stack_chk_guards[N + 1]; + child_stack_chk_guards[N] = stack_chk_guard_copy; + int i; + for (i = 0; i < N; ++i) + { + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed after fork"); + exit (1); + } + + close (fds[0]); + close (2); + dup2 (fds[1], 2); + close (fds[1]); + + system (command); + exit (0); + } + + close (fds[1]); + + if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], + sizeof (uintptr_t))) != sizeof (uintptr_t)) + { + puts ("could not read stack_chk_guard value from child"); + return 1; + } + + close (fds[0]); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + return 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + return 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + return 1; + } + } + + qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); + + uintptr_t default_guard = 0; + unsigned char *p = (unsigned char *) &default_guard; + p[sizeof (uintptr_t) - 1] = 255; + p[sizeof (uintptr_t) - 2] = '\n'; + p[0] = 0; + + /* Test if the stack guard canaries are either randomized, + or equal to the default stack guard canary value. + Even with randomized stack guards it might happen + that the random number generator generates the same + values, but if that happens in more than half from + the 16 runs, something is very wrong. */ + int ndifferences = 0; + int ndefaults = 0; + for (i = 0; i < N; ++i) + { + if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) + ndifferences++; + else if (child_stack_chk_guards[i] == default_guard) + ndefaults++; + } + + printf ("differences %d defaults %d\n", ndifferences, ndefaults); + + if (ndifferences < N / 2 && ndefaults < N / 2) + { + puts ("stack guard canaries are not randomized enough"); + puts ("nor equal to the default canary value"); + return 1; + } + + return 0; +} + +#define OPT_COMMAND 10000 +#define OPT_CHILD 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "child", no_argument, NULL, OPT_CHILD }, + +static void __attribute__((used)) +cmdline_process_function (int c) +{ + switch (c) + { + case OPT_COMMAND: + command = optarg; + break; + case OPT_CHILD: + child = true; + break; + } +} +#define CMDLINE_PROCESS cmdline_process_function + +#include <support/test-driver.c> |