From 7d69de618e732d343228a07d797a30e39a6363f4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 27 Jun 2005 00:41:16 -0700 Subject: c-cppbuiltin.c (c_cpp_builtins): Add __SSP_ALL__ and __SSP__. * c-cppbuiltin.c (c_cpp_builtins): Add __SSP_ALL__ and __SSP__. * cfgexpand.c: Include params.h. (has_protected_decls, has_short_buffer): New. (expand_stack_vars): Take a predicate to determine what to expand. (defer_stack_allocation): True when flag_stack_protect on. (SPCT_HAS_LARGE_CHAR_ARRAY, SPCT_HAS_SMALL_CHAR_ARRAY): New. (SPCT_HAS_ARRAY, SPCT_HAS_AGGREGATE): New. (stack_protect_classify_type, stack_protect_decl_phase): New. (stack_protect_decl_phase_1, stack_protect_decl_phase_2): New. (add_stack_protection_conflicts, create_stack_guard): New. (expand_used_vars): Add stack protection logic. (tree_expand_cfg): Likewise. * common.opt (Wstack-protector): New. (fstack-protector, fstack-protector-all): New. * function.c: Include predict.h. (assign_parm_adjust_stack_rtl): Zap stack_parm when stack protect wants to copy the parameter into the stack frame. (stack_protect_prologue, stack_protect_epilogue): New. (expand_function_end): Call stack_protect_epilogue. Do sjlj_emit_function_exit_after after naked_return_label. * function.h (struct function): Add stack_protect_guard. * params.def (PARAM_SSP_BUFFER_SIZE): New. * toplev.c (process_options): Disable flag_stack_protect and/or warn_stack_protect based on FRAME_GROWS_DOWNWARD. * tree.h (stack_protect_prologue): Declare. * target-def.h (TARGET_STACK_PROTECT_GUARD): New. (TARGET_STACK_PROTECT_FAIL): New. (TARGET_INITIALIZER): Add them. * target.h (struct gcc_target): Add stack_protect_guard and stack_protect_fail. * targhooks.c: Include ggc.h, gty header. (stack_chk_guard_decl, default_stack_protect_guard): New. (stack_chk_fail_decl, default_external_stack_protect_fail): New. (default_hidden_stack_protect_fail): New. * targhooks.h (default_stack_protect_guard): Declare. (default_external_stack_protect_fail): Declare. (default_hidden_stack_protect_fail): Declare. * config/i386/i386.c (TARGET_STACK_PROTECT_FAIL): New. * config/i386/i386.md (UNSPEC_SP_SET, UNSPEC_SP_TEST): New. (trap): Use ud2. (conditional_trap, conditional_trap_1): Remove. (stack_protect_set, stack_protect_set_si, stack_protect_set_di): New. (stack_protect_test, stack_protect_test_si, stack_protect_test_di): New. * doc/md.texi (stack_protect_set, stack_protect_test): New. * doc/tm.texi (TARGET_STACK_PROTECT_GUARD): New. (TARGET_STACK_PROTECT_FAIL): New. * libgcc-std.ver (GCC_4.1.0): New. * libgcc.h (__stack_chk_guard): Declare. (__stack_chk_fail, __stack_chk_fail_local): Declare. * libgcc2.c (L_stack_chk, L_stack_chk_local): New. * mklibgcc.in (lib2funcs): Add them. From-SVN: r101348 --- gcc/libgcc2.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) (limited to 'gcc/libgcc2.c') diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 3108bff6729..a49c8c128f9 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -2015,3 +2015,141 @@ func_ptr __DTOR_LIST__[2]; #endif #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */ #endif /* L_ctors */ + +#ifdef L_stack_chk +#ifndef TARGET_LIBC_PROVIDES_SSP + +#ifndef inhibit_libc +# include +# include +# include +# ifdef HAVE_PATHS_H +# include +# endif +# ifndef _PATH_TTY +# define _PATH_TTY "/dev/tty" +# endif +# ifdef HAVE_SYSLOG_H +# include +# endif +#endif + +void *__stack_chk_guard = 0; + +static void __attribute__ ((constructor)) +__guard_setup (void) +{ + unsigned char *p; + + if (__stack_chk_guard != 0) + return; + +#ifndef inhibit_libc + { + int fd = open ("/dev/urandom", O_RDONLY); + if (fd != -1) + { + ssize_t size = read (fd, &__stack_chk_guard, + sizeof (__stack_chk_guard)); + close (fd); + if (size == sizeof(__stack_chk_guard)) + return; + } + } +#endif + + /* If a random generator can't be used, the protector switches the guard + to the "terminator canary". */ + p = (unsigned char *)&__stack_chk_guard; + p[sizeof(__stack_chk_guard)-1] = 255; + p[sizeof(__stack_chk_guard)-2] = '\n'; + p[0] = 0; +} + +void +__stack_chk_fail (void) +{ +#ifndef inhibit_libc +# ifdef __GNU_LIBRARY__ + extern char * __progname; +# else + static const char __progname[] = ""; +# endif + + int fd; + + /* Print error message directly to the tty. This avoids Bad Things + happening if stderr is redirected. */ + fd = open (_PATH_TTY, O_WRONLY); + if (fd != -1) + { + static const char msg1[] = "*** stack smashing detected ***: "; + static const char msg2[] = " terminated\n"; + size_t progname_len, len; + char *buf, *p; + + progname_len = strlen (__progname); + len = sizeof(msg1)-1 + progname_len + sizeof(msg2)-1 + 1; + p = buf = alloca (len); + + memcpy (p, msg1, sizeof(msg1)-1); + p += sizeof(msg1)-1; + memcpy (p, __progname, progname_len); + p += progname_len; + memcpy (p, msg2, sizeof(msg2)); + + while (len > 0) + { + ssize_t wrote = write (fd, buf, len); + if (wrote < 0) + break; + len -= wrote; + } + close (fd); + } + +# ifdef HAVE_SYSLOG_H + /* Only send the error to syslog if there was no tty available. */ + else + syslog (LOG_CRIT, "stack smashing detected: terminated"); +# endif /* HAVE_SYSLOG_H */ +#endif /* inhibit_libc */ + + /* Try very hard to exit. Note that signals may be blocked preventing + the first two options from working. The use of volatile is here to + prevent optimizers from "knowing" that __builtin_trap is called first, + and that it doesn't return, and so "obviously" the rest of the code + is dead. */ + { + volatile int state; + for (state = 0; ; state++) + switch (state) + { + case 0: + __builtin_trap (); + break; + case 1: + *(volatile int *)-1L = 0; + break; + case 2: + _exit (127); + break; + } + } +} +#endif /* TARGET_LIBC_PROVIDES_SSP */ +#endif /* L_stack_chk */ + +#ifdef L_stack_chk_local +#ifndef TARGET_LIBC_PROVIDES_SSP +/* Some targets can avoid loading a GP for calls to hidden functions. + Using this entry point may avoid the load of a GP entirely for the + function, making the overall code smaller. */ + +void +__stack_chk_fail_local (void) +{ + __stack_chk_fail (); +} +#endif /* TARGET_LIBC_PROVIDES_SSP */ +#endif /* L_stack_chk_local */ -- cgit v1.2.1