Back to index

glibc  2.9
Defines | Functions | Variables
tst-stackguard1.c File Reference
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <elf/stackguard-macros.h>
#include <unistd.h>
#include "../test-skeleton.c"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define N   16
#define OPT_COMMAND   10000
#define OPT_CHILD   10001
#define CMDLINE_OPTIONS
#define CMDLINE_PROCESS
#define TEST_FUNCTION   do_test ()

Functions

static void __attribute__ ((constructor))
static int uintptr_t_cmp (const void *a, const void *b)
static void * tf (void *arg)
static int do_test (void)

Variables

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]

Define Documentation

#define CMDLINE_OPTIONS
Value:
{ "command", required_argument, NULL, OPT_COMMAND },  \
  { "child", no_argument, NULL, OPT_CHILD },

Definition at line 215 of file tst-stackguard1.c.

#define CMDLINE_PROCESS
Value:
case OPT_COMMAND:    \
    command = optarg;       \
    break;           \
  case OPT_CHILD:    \
    child = true;    \
    break;

Definition at line 218 of file tst-stackguard1.c.

#define N   16
#define OPT_CHILD   10001

Definition at line 214 of file tst-stackguard1.c.

#define OPT_COMMAND   10000

Definition at line 213 of file tst-stackguard1.c.

#define TEST_FUNCTION   do_test ()

Definition at line 225 of file tst-stackguard1.c.


Function Documentation

static void __attribute__ ( (constructor)  ) [static]
static int do_test ( void  ) [static]

Definition at line 65 of file tst-stackguard1.c.

{
  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)
    {
      int i;
      pthread_t th[4];
      void *ret;
      for (i = 0; i < 4; ++i)
       if (pthread_create (&th[i], NULL, tf, NULL))
         {
           puts ("thread creation failed");
           return 1;
         }
      for (i = 0; i < 4; ++i)
       if (pthread_join (th[i], &ret))
         {
           puts ("thread join failed");
           return 1;
         }
       else if (ret != NULL)
         return 1;

      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;
}

Here is the call graph for this function:

static void* tf ( void *  arg) [static]

Definition at line 54 of file tst-stackguard1.c.

{
  if (stack_chk_guard_copy != STACK_CHK_GUARD)
    {
      puts ("STACK_CHK_GUARD changed in thread");
      return (void *) 1L;
    }
  return NULL;
}

Here is the call graph for this function:

static int uintptr_t_cmp ( const void *  a,
const void *  b 
) [static]

Definition at line 44 of file tst-stackguard1.c.

{
  if (*(uintptr_t *) a < *(uintptr_t *) b)
    return 1;
  if (*(uintptr_t *) a > *(uintptr_t *) b)
    return -1;
  return 0;
}

Here is the caller graph for this function:


Variable Documentation

bool child [static]

Definition at line 31 of file tst-stackguard1.c.

const char* command [static]

Definition at line 30 of file tst-stackguard1.c.

int fds[2] [static]

Definition at line 34 of file tst-stackguard1.c.

Definition at line 32 of file tst-stackguard1.c.

bool stack_chk_guard_copy_set [static]

Definition at line 33 of file tst-stackguard1.c.