Blame elf/tst-stackguard1.c

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