ssp.c revision 169695
1169695Skan/* Stack protector support. 2169695Skan Copyright (C) 2005 Free Software Foundation, Inc. 3169695Skan 4169695SkanThis file is part of GCC. 5169695Skan 6169695SkanGCC is free software; you can redistribute it and/or modify it under 7169695Skanthe terms of the GNU General Public License as published by the Free 8169695SkanSoftware Foundation; either version 2, or (at your option) any later 9169695Skanversion. 10169695Skan 11169695SkanIn addition to the permissions in the GNU General Public License, the 12169695SkanFree Software Foundation gives you unlimited permission to link the 13169695Skancompiled version of this file into combinations with other programs, 14169695Skanand to distribute those combinations without any restriction coming 15169695Skanfrom the use of this file. (The General Public License restrictions 16169695Skando apply in other respects; for example, they cover modification of 17169695Skanthe file, and distribution when not linked into a combine 18169695Skanexecutable.) 19169695Skan 20169695SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 21169695SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 22169695SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 23169695Skanfor more details. 24169695Skan 25169695SkanYou should have received a copy of the GNU General Public License 26169695Skanalong with GCC; see the file COPYING. If not, write to the Free 27169695SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 28169695Skan02110-1301, USA. */ 29169695Skan 30169695Skan/* As a special exception, if you link this library with files compiled with 31169695Skan GCC to produce an executable, this does not cause the resulting executable 32169695Skan to be covered by the GNU General Public License. This exception does not 33169695Skan however invalidate any other reasons why the executable file might be 34169695Skan covered by the GNU General Public License. */ 35169695Skan 36169695Skan#include "config.h" 37169695Skan#ifdef HAVE_ALLOCA_H 38169695Skan# include <alloca.h> 39169695Skan#endif 40169695Skan#ifdef HAVE_STRING_H 41169695Skan# include <string.h> 42169695Skan#endif 43169695Skan#ifdef HAVE_UNISTD_H 44169695Skan# include <unistd.h> 45169695Skan#endif 46169695Skan#ifdef HAVE_FCNTL_H 47169695Skan# include <fcntl.h> 48169695Skan#endif 49169695Skan#ifdef HAVE_PATHS_H 50169695Skan# include <paths.h> 51169695Skan#endif 52169695Skan#ifndef _PATH_TTY 53169695Skan# define _PATH_TTY "/dev/tty" 54169695Skan#endif 55169695Skan#ifdef HAVE_SYSLOG_H 56169695Skan# include <syslog.h> 57169695Skan#endif 58169695Skan 59169695Skanvoid *__stack_chk_guard = 0; 60169695Skan 61169695Skanstatic void __attribute__ ((constructor)) 62169695Skan__guard_setup (void) 63169695Skan{ 64169695Skan unsigned char *p; 65169695Skan int fd; 66169695Skan 67169695Skan if (__stack_chk_guard != 0) 68169695Skan return; 69169695Skan 70169695Skan fd = open ("/dev/urandom", O_RDONLY); 71169695Skan if (fd != -1) 72169695Skan { 73169695Skan ssize_t size = read (fd, &__stack_chk_guard, 74169695Skan sizeof (__stack_chk_guard)); 75169695Skan close (fd); 76169695Skan if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0) 77169695Skan return; 78169695Skan } 79169695Skan 80169695Skan /* If a random generator can't be used, the protector switches the guard 81169695Skan to the "terminator canary". */ 82169695Skan p = (unsigned char *) &__stack_chk_guard; 83169695Skan p[sizeof(__stack_chk_guard)-1] = 255; 84169695Skan p[sizeof(__stack_chk_guard)-2] = '\n'; 85169695Skan p[0] = 0; 86169695Skan} 87169695Skan 88169695Skanstatic void 89169695Skanfail (const char *msg1, size_t msg1len, const char *msg3) 90169695Skan{ 91169695Skan#ifdef __GNU_LIBRARY__ 92169695Skan extern char * __progname; 93169695Skan#else 94169695Skan static const char __progname[] = ""; 95169695Skan#endif 96169695Skan int fd; 97169695Skan 98169695Skan /* Print error message directly to the tty. This avoids Bad Things 99169695Skan happening if stderr is redirected. */ 100169695Skan fd = open (_PATH_TTY, O_WRONLY); 101169695Skan if (fd != -1) 102169695Skan { 103169695Skan static const char msg2[] = " terminated\n"; 104169695Skan size_t progname_len, len; 105169695Skan char *buf, *p; 106169695Skan 107169695Skan progname_len = strlen (__progname); 108169695Skan len = msg1len + progname_len + sizeof(msg2)-1 + 1; 109169695Skan p = buf = alloca (len); 110169695Skan 111169695Skan memcpy (p, msg1, msg1len); 112169695Skan p += msg1len; 113169695Skan memcpy (p, __progname, progname_len); 114169695Skan p += progname_len; 115169695Skan memcpy (p, msg2, sizeof(msg2)); 116169695Skan 117169695Skan while (len > 0) 118169695Skan { 119169695Skan ssize_t wrote = write (fd, buf, len); 120169695Skan if (wrote < 0) 121169695Skan break; 122169695Skan buf += wrote; 123169695Skan len -= wrote; 124169695Skan } 125169695Skan close (fd); 126169695Skan } 127169695Skan 128169695Skan#ifdef HAVE_SYSLOG_H 129169695Skan /* Only send the error to syslog if there was no tty available. */ 130169695Skan else 131169695Skan syslog (LOG_CRIT, msg3); 132169695Skan#endif /* HAVE_SYSLOG_H */ 133169695Skan 134169695Skan /* Try very hard to exit. Note that signals may be blocked preventing 135169695Skan the first two options from working. The use of volatile is here to 136169695Skan prevent optimizers from "knowing" that __builtin_trap is called first, 137169695Skan and that it doesn't return, and so "obviously" the rest of the code 138169695Skan is dead. */ 139169695Skan { 140169695Skan volatile int state; 141169695Skan for (state = 0; ; state++) 142169695Skan switch (state) 143169695Skan { 144169695Skan case 0: 145169695Skan __builtin_trap (); 146169695Skan break; 147169695Skan case 1: 148169695Skan *(volatile int *)-1L = 0; 149169695Skan break; 150169695Skan case 2: 151169695Skan _exit (127); 152169695Skan break; 153169695Skan } 154169695Skan } 155169695Skan} 156169695Skan 157169695Skanvoid 158169695Skan__stack_chk_fail (void) 159169695Skan{ 160169695Skan const char *msg = "*** stack smashing detected ***: "; 161169695Skan fail (msg, strlen (msg), "stack smashing detected: terminated"); 162169695Skan} 163169695Skan 164169695Skanvoid 165169695Skan__chk_fail (void) 166169695Skan{ 167169695Skan const char *msg = "*** buffer overflow detected ***: "; 168169695Skan fail (msg, strlen (msg), "buffer overflow detected: terminated"); 169169695Skan} 170169695Skan 171169695Skan#ifdef HAVE_HIDDEN_VISIBILITY 172169695Skanvoid 173169695Skan__attribute__((visibility ("hidden"))) 174169695Skan__stack_chk_fail_local (void) 175169695Skan{ 176169695Skan __stack_chk_fail (); 177169695Skan} 178169695Skan#endif 179