diff options
Diffstat (limited to 'debug')
-rw-r--r-- | debug/Makefile | 7 | ||||
-rw-r--r-- | debug/Versions | 3 | ||||
-rw-r--r-- | debug/longjmp_chk.c | 28 | ||||
-rw-r--r-- | debug/tst-longjmp_chk.c | 86 |
4 files changed, 122 insertions, 2 deletions
diff --git a/debug/Makefile b/debug/Makefile index ece7ee6bd7..181169b90d 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2001,2004-2008 Free Software Foundation, Inc. +# Copyright (C) 1998-2001,2004-2008, 2009 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -43,6 +43,7 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \ wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ wcstombs_chk asprintf_chk vasprintf_chk dprintf_chk \ vdprintf_chk obprintf_chk \ + longjmp_chk ____longjmp_chk \ stack_chk_fail fortify_fail \ $(static-only-routines) static-only-routines := warning-nop stack_chk_fail_local @@ -79,6 +80,8 @@ CFLAGS-pread_chk.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-pread64_chk.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-recv_chk.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-recvfrom_chk.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-tst-longjmp_chk.c = -fexceptions -fasynchronous-unwind-tables \ + -D_FORTIFY_SOURCE=1 # We know these tests have problems with format strings, this is what # we are testing. Disable that warning. @@ -113,7 +116,7 @@ LDFLAGS-tst-lfschk4 = -lstdc++ LDFLAGS-tst-lfschk5 = -lstdc++ LDFLAGS-tst-lfschk6 = -lstdc++ -tests = backtrace-tst tst-chk1 tst-chk2 tst-chk3 \ +tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 diff --git a/debug/Versions b/debug/Versions index ef6b08b7b3..ff40107b77 100644 --- a/debug/Versions +++ b/debug/Versions @@ -46,6 +46,9 @@ libc { __asprintf_chk; __vasprintf_chk; __dprintf_chk; __vdprintf_chk; __obstack_printf_chk; __obstack_vprintf_chk; } + GLIBC_2.11 { + __longjmp_chk; + } GLIBC_PRIVATE { __fortify_fail; } diff --git a/debug/longjmp_chk.c b/debug/longjmp_chk.c new file mode 100644 index 0000000000..7de2a98a30 --- /dev/null +++ b/debug/longjmp_chk.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <setjmp.h> + +// XXX Should move to include/setjmp.h +extern void ____longjmp_chk (__jmp_buf __env, int __val) + __attribute__ ((__noreturn__)); + +#define __longjmp ____longjmp_chk +#define __libc_siglongjmp __longjmp_chk + +#include <setjmp/longjmp.c> diff --git a/debug/tst-longjmp_chk.c b/debug/tst-longjmp_chk.c new file mode 100644 index 0000000000..8892974cc7 --- /dev/null +++ b/debug/tst-longjmp_chk.c @@ -0,0 +1,86 @@ +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <setjmp.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static jmp_buf b; + + +static void +__attribute__ ((noinline)) +f (void) +{ + char buf[1000]; + asm volatile ("" : "=m" (buf)); + + if (setjmp (b) != 0) + { + puts ("second longjmp succeeded"); + exit (1); + } +} + + +static bool expected_to_fail; + + +static void +handler (int sig) +{ + if (expected_to_fail) + _exit (0); + else + { + static const char msg[] = "unexpected longjmp failure\n"; + TEMP_FAILURE_RETRY (write (STDOUT_FILENO, msg, sizeof (msg) - 1)); + _exit (1); + } +} + + +int +main (void) +{ + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + sigaction (SIGABRT, &sa, NULL); + + /* Avoid all the buffer overflow messages on stderr. */ + int fd = open (_PATH_DEVNULL, O_WRONLY); + if (fd == -1) + close (STDERR_FILENO); + else + { + dup2 (fd, STDERR_FILENO); + close (fd); + } + setenv ("LIBC_FATAL_STDERR_", "1", 1); + + + expected_to_fail = false; + + if (setjmp (b) == 0) + { + longjmp (b, 1); + /* NOTREACHED */ + printf ("first longjmp returned\n"); + return 1; + } + + + expected_to_fail = true; + + f (); + longjmp (b, 1); + + puts ("second longjmp returned"); + return 1; +} |