1 /* Stack protector support. 2 Copyright (C) 2005, 2009 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 In addition to the permissions in the GNU General Public License, the 12 Free Software Foundation gives you unlimited permission to link the 13 compiled version of this file into combinations with other programs, 14 and to distribute those combinations without any restriction coming 15 from the use of this file. (The General Public License restrictions 16 do apply in other respects; for example, they cover modification of 17 the file, and distribution when not linked into a combine 18 executable.) 19 20 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 21 WARRANTY; without even the implied warranty of MERCHANTABILITY or 22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 23 for more details. 24 25 Under Section 7 of GPL version 3, you are granted additional 26 permissions described in the GCC Runtime Library Exception, version 27 3.1, as published by the Free Software Foundation. 28 29 You should have received a copy of the GNU General Public License and 30 a copy of the GCC Runtime Library Exception along with this program; 31 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 32 <http://www.gnu.org/licenses/>. */ 33 34 35 #include "config.h" 36 #ifdef HAVE_ALLOCA_H 37 # include <alloca.h> 38 #endif 39 #ifdef HAVE_MALLOC_H 40 # include <malloc.h> 41 #else 42 # include <stdlib.h> 43 #endif 44 #ifdef HAVE_STRING_H 45 # include <string.h> 46 #endif 47 #ifdef HAVE_UNISTD_H 48 # include <unistd.h> 49 #endif 50 #ifdef HAVE_FCNTL_H 51 # include <fcntl.h> 52 #endif 53 #ifdef HAVE_PATHS_H 54 # include <paths.h> 55 #endif 56 #ifndef _PATH_TTY 57 /* Native win32 apps don't know about /dev/tty but can print directly 58 to the console using "CONOUT$" */ 59 #if defined (_WIN32) && !defined (__CYGWIN__) 60 # define _PATH_TTY "CONOUT$" 61 #else 62 # define _PATH_TTY "/dev/tty" 63 #endif 64 #endif 65 #ifdef HAVE_SYSLOG_H 66 # include <syslog.h> 67 #endif 68 69 void *__stack_chk_guard = 0; 70 71 static void __attribute__ ((constructor)) 72 __guard_setup (void) 73 { 74 unsigned char *p; 75 int fd; 76 77 if (__stack_chk_guard != 0) 78 return; 79 80 fd = open ("/dev/urandom", O_RDONLY); 81 if (fd != -1) 82 { 83 ssize_t size = read (fd, &__stack_chk_guard, 84 sizeof (__stack_chk_guard)); 85 close (fd); 86 if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0) 87 return; 88 } 89 90 /* If a random generator can't be used, the protector switches the guard 91 to the "terminator canary". */ 92 p = (unsigned char *) &__stack_chk_guard; 93 p[sizeof(__stack_chk_guard)-1] = 255; 94 p[sizeof(__stack_chk_guard)-2] = '\n'; 95 p[0] = 0; 96 } 97 98 static void 99 fail (const char *msg1, size_t msg1len, const char *msg3) 100 { 101 #ifdef __GNU_LIBRARY__ 102 extern char * __progname; 103 #else 104 static const char __progname[] = ""; 105 #endif 106 int fd; 107 108 /* Print error message directly to the tty. This avoids Bad Things 109 happening if stderr is redirected. */ 110 fd = open (_PATH_TTY, O_WRONLY); 111 if (fd != -1) 112 { 113 static const char msg2[] = " terminated\n"; 114 size_t progname_len, len; 115 char *buf, *p; 116 117 progname_len = strlen (__progname); 118 len = msg1len + progname_len + sizeof(msg2)-1 + 1; 119 p = buf = alloca (len); 120 121 memcpy (p, msg1, msg1len); 122 p += msg1len; 123 memcpy (p, __progname, progname_len); 124 p += progname_len; 125 memcpy (p, msg2, sizeof(msg2)); 126 127 while (len > 0) 128 { 129 ssize_t wrote = write (fd, buf, len); 130 if (wrote < 0) 131 break; 132 buf += wrote; 133 len -= wrote; 134 } 135 close (fd); 136 } 137 138 #ifdef HAVE_SYSLOG_H 139 /* Only send the error to syslog if there was no tty available. */ 140 else 141 syslog (LOG_CRIT, msg3); 142 #endif /* HAVE_SYSLOG_H */ 143 144 /* Try very hard to exit. Note that signals may be blocked preventing 145 the first two options from working. The use of volatile is here to 146 prevent optimizers from "knowing" that __builtin_trap is called first, 147 and that it doesn't return, and so "obviously" the rest of the code 148 is dead. */ 149 { 150 volatile int state; 151 for (state = 0; ; state++) 152 switch (state) 153 { 154 case 0: 155 __builtin_trap (); 156 break; 157 case 1: 158 *(volatile int *)-1L = 0; 159 break; 160 case 2: 161 _exit (127); 162 break; 163 } 164 } 165 } 166 167 void 168 __stack_chk_fail (void) 169 { 170 const char *msg = "*** stack smashing detected ***: "; 171 fail (msg, strlen (msg), "stack smashing detected: terminated"); 172 } 173 174 void 175 __chk_fail (void) 176 { 177 const char *msg = "*** buffer overflow detected ***: "; 178 fail (msg, strlen (msg), "buffer overflow detected: terminated"); 179 } 180 181 #ifdef HAVE_HIDDEN_VISIBILITY 182 void 183 __attribute__((visibility ("hidden"))) 184 __stack_chk_fail_local (void) 185 { 186 __stack_chk_fail (); 187 } 188 #endif 189