aboutsummaryrefslogtreecommitdiff
path: root/libssp/ssp.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-02 08:52:21 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-02 08:52:21 +0000
commit0d55f4d0aeaeb16629a2c07c96a190695b83a7e6 (patch)
tree1cb854702400de0149fb900c82b137e5603e222b /libssp/ssp.c
parentc656b4ab03db593f6251031bbdcf8fa2e7324ee0 (diff)
* Makefile.def (target_modules): Add libssp.
* configure.in (target_libraries): Add target-libssp. * configure: Rebuilt. * Makefile.in: Rebuilt. gcc/ * gcc.c (LINK_SSP_SPEC): Define. (link_ssp_spec): New variable. (LINK_COMMAND_SPEC): Add %(link_ssp). (static_specs): Add link_ssp_spec. * configure.ac (TARGET_LIBC_PROVIDES_SSP): New test. * configure: Rebuilt. * config.in: Rebuilt. * config/rs6000/linux.h (TARGET_THREAD_SSP_OFFSET): Define. * config/rs6000/linux64.h (TARGET_THREAD_SSP_OFFSET): Likewise. * config/i386/linux.h (TARGET_THREAD_SSP_OFFSET): Likewise. * config/i386/linux64.h (TARGET_THREAD_SSP_OFFSET): Likewise. * config/rs6000/rs6000.md (stack_protect_set, stack_protect_test): If TARGET_THREAD_SSP_OFFSET is defined, use -0x7010(13) resp. -0x7008(2) instead of reading __stack_chk_guard variable. * config/i386/i386.md (UNSPEC_SP_SET, UNSPEC_SP_TEST): Change number. (UNSPEC_SP_TLS_SET, UNSPEC_SP_TLS_TEST): New constants. (stack_protect_set, stack_protect_test): Use *_tls* patterns if TARGET_THREAD_SSP_OFFSET is defined. (stack_tls_protect_set_si, stack_tls_protect_set_di, stack_tls_protect_test_si, stack_tls_protect_test_di): New insns. Revert: 2005-06-27 Richard Henderson <rth@redhat.com> * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101531 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libssp/ssp.c')
-rw-r--r--libssp/ssp.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/libssp/ssp.c b/libssp/ssp.c
new file mode 100644
index 00000000000..6c565363b75
--- /dev/null
+++ b/libssp/ssp.c
@@ -0,0 +1,178 @@
+/* Stack protector support.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* As a special exception, if you link this library with files compiled with
+ GCC to produce an executable, this does not cause the resulting executable
+ to be covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU General Public License. */
+
+#include "config.h"
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+#ifndef _PATH_TTY
+# define _PATH_TTY "/dev/tty"
+#endif
+#ifdef HAVE_SYSLOG_H
+# include <syslog.h>
+#endif
+
+void *__stack_chk_guard = 0;
+
+static void __attribute__ ((constructor))
+__guard_setup (void)
+{
+ unsigned char *p;
+ int fd;
+
+ if (__stack_chk_guard != 0)
+ return;
+
+ 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) && __stack_chk_guard != 0)
+ return;
+ }
+
+ /* 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;
+}
+
+static void
+fail (const char *msg1, size_t msg1len, const char *msg3)
+{
+#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 msg2[] = " terminated\n";
+ size_t progname_len, len;
+ char *buf, *p;
+
+ progname_len = strlen (__progname);
+ len = msg1len + progname_len + sizeof(msg2)-1 + 1;
+ p = buf = alloca (len);
+
+ memcpy (p, msg1, msg1len);
+ p += msg1len;
+ 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;
+ buf += wrote;
+ len -= wrote;
+ }
+ close (fd);
+ }
+
+#ifdef HAVE_SYSLOG_H
+ /* Only send the error to syslog if there was no tty available. */
+ else
+ syslog (LOG_CRIT, msg3);
+#endif /* HAVE_SYSLOG_H */
+
+ /* 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;
+ }
+ }
+}
+
+void
+__stack_chk_fail (void)
+{
+ const char *msg = "*** stack smashing detected ***: ";
+ fail (msg, strlen (msg), "stack smashing detected: terminated");
+}
+
+void
+__chk_fail (void)
+{
+ const char *msg = "*** buffer overflow detected ***: ";
+ fail (msg, strlen (msg), "buffer overflow detected: terminated");
+}
+
+#ifdef HAVE_HIDDEN_VISIBILITY
+void
+__attribute__((visibility ("hidden")))
+__stack_chk_fail_local (void)
+{
+ __stack_chk_fail ();
+}
+#endif