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 59257362Ssbruno#include <stdlib.h> 60257362Ssbruno 61169695Skanvoid *__stack_chk_guard = 0; 62169695Skan 63169695Skanstatic void __attribute__ ((constructor)) 64169695Skan__guard_setup (void) 65169695Skan{ 66169695Skan unsigned char *p; 67169695Skan int fd; 68169695Skan 69169695Skan if (__stack_chk_guard != 0) 70169695Skan return; 71169695Skan 72169695Skan fd = open ("/dev/urandom", O_RDONLY); 73169695Skan if (fd != -1) 74169695Skan { 75169695Skan ssize_t size = read (fd, &__stack_chk_guard, 76169695Skan sizeof (__stack_chk_guard)); 77169695Skan close (fd); 78169695Skan if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0) 79169695Skan return; 80169695Skan } 81169695Skan 82169695Skan /* If a random generator can't be used, the protector switches the guard 83169695Skan to the "terminator canary". */ 84169695Skan p = (unsigned char *) &__stack_chk_guard; 85169695Skan p[sizeof(__stack_chk_guard)-1] = 255; 86169695Skan p[sizeof(__stack_chk_guard)-2] = '\n'; 87169695Skan p[0] = 0; 88169695Skan} 89169695Skan 90169695Skanstatic void 91169695Skanfail (const char *msg1, size_t msg1len, const char *msg3) 92169695Skan{ 93169695Skan#ifdef __GNU_LIBRARY__ 94169695Skan extern char * __progname; 95169695Skan#else 96169695Skan static const char __progname[] = ""; 97169695Skan#endif 98169695Skan int fd; 99169695Skan 100169695Skan /* Print error message directly to the tty. This avoids Bad Things 101169695Skan happening if stderr is redirected. */ 102169695Skan fd = open (_PATH_TTY, O_WRONLY); 103169695Skan if (fd != -1) 104169695Skan { 105169695Skan static const char msg2[] = " terminated\n"; 106169695Skan size_t progname_len, len; 107169695Skan char *buf, *p; 108169695Skan 109169695Skan progname_len = strlen (__progname); 110169695Skan len = msg1len + progname_len + sizeof(msg2)-1 + 1; 111169695Skan p = buf = alloca (len); 112169695Skan 113169695Skan memcpy (p, msg1, msg1len); 114169695Skan p += msg1len; 115169695Skan memcpy (p, __progname, progname_len); 116169695Skan p += progname_len; 117169695Skan memcpy (p, msg2, sizeof(msg2)); 118169695Skan 119169695Skan while (len > 0) 120169695Skan { 121169695Skan ssize_t wrote = write (fd, buf, len); 122169695Skan if (wrote < 0) 123169695Skan break; 124169695Skan buf += wrote; 125169695Skan len -= wrote; 126169695Skan } 127169695Skan close (fd); 128169695Skan } 129169695Skan 130169695Skan#ifdef HAVE_SYSLOG_H 131169695Skan /* Only send the error to syslog if there was no tty available. */ 132169695Skan else 133256866Ssbruno syslog (LOG_CRIT, "%s", msg3); 134169695Skan#endif /* HAVE_SYSLOG_H */ 135169695Skan 136169695Skan /* Try very hard to exit. Note that signals may be blocked preventing 137169695Skan the first two options from working. The use of volatile is here to 138169695Skan prevent optimizers from "knowing" that __builtin_trap is called first, 139169695Skan and that it doesn't return, and so "obviously" the rest of the code 140169695Skan is dead. */ 141169695Skan { 142169695Skan volatile int state; 143169695Skan for (state = 0; ; state++) 144169695Skan switch (state) 145169695Skan { 146169695Skan case 0: 147169695Skan __builtin_trap (); 148169695Skan break; 149169695Skan case 1: 150169695Skan *(volatile int *)-1L = 0; 151169695Skan break; 152169695Skan case 2: 153169695Skan _exit (127); 154169695Skan break; 155169695Skan } 156169695Skan } 157169695Skan} 158169695Skan 159169695Skanvoid 160169695Skan__stack_chk_fail (void) 161169695Skan{ 162169695Skan const char *msg = "*** stack smashing detected ***: "; 163169695Skan fail (msg, strlen (msg), "stack smashing detected: terminated"); 164169695Skan} 165169695Skan 166169695Skanvoid 167169695Skan__chk_fail (void) 168169695Skan{ 169169695Skan const char *msg = "*** buffer overflow detected ***: "; 170169695Skan fail (msg, strlen (msg), "buffer overflow detected: terminated"); 171169695Skan} 172169695Skan 173169695Skan#ifdef HAVE_HIDDEN_VISIBILITY 174169695Skanvoid 175169695Skan__attribute__((visibility ("hidden"))) 176169695Skan__stack_chk_fail_local (void) 177169695Skan{ 178169695Skan __stack_chk_fail (); 179169695Skan} 180169695Skan#endif 181