0
|
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_STRING_H
|
|
40 # include <string.h>
|
|
41 #endif
|
|
42 #ifdef HAVE_UNISTD_H
|
|
43 # include <unistd.h>
|
|
44 #endif
|
|
45 #ifdef HAVE_FCNTL_H
|
|
46 # include <fcntl.h>
|
|
47 #endif
|
|
48 #ifdef HAVE_PATHS_H
|
|
49 # include <paths.h>
|
|
50 #endif
|
|
51 #ifndef _PATH_TTY
|
|
52 /* Native win32 apps don't know about /dev/tty but can print directly
|
|
53 to the console using "CONOUT$" */
|
|
54 #if defined (_WIN32) && !defined (__CYGWIN__)
|
|
55 # define _PATH_TTY "CONOUT$"
|
|
56 #else
|
|
57 # define _PATH_TTY "/dev/tty"
|
|
58 #endif
|
|
59 #endif
|
|
60 #ifdef HAVE_SYSLOG_H
|
|
61 # include <syslog.h>
|
|
62 #endif
|
|
63
|
|
64 void *__stack_chk_guard = 0;
|
|
65
|
|
66 static void __attribute__ ((constructor))
|
|
67 __guard_setup (void)
|
|
68 {
|
|
69 unsigned char *p;
|
|
70 int fd;
|
|
71
|
|
72 if (__stack_chk_guard != 0)
|
|
73 return;
|
|
74
|
|
75 fd = open ("/dev/urandom", O_RDONLY);
|
|
76 if (fd != -1)
|
|
77 {
|
|
78 ssize_t size = read (fd, &__stack_chk_guard,
|
|
79 sizeof (__stack_chk_guard));
|
|
80 close (fd);
|
|
81 if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0)
|
|
82 return;
|
|
83 }
|
|
84
|
|
85 /* If a random generator can't be used, the protector switches the guard
|
|
86 to the "terminator canary". */
|
|
87 p = (unsigned char *) &__stack_chk_guard;
|
|
88 p[sizeof(__stack_chk_guard)-1] = 255;
|
|
89 p[sizeof(__stack_chk_guard)-2] = '\n';
|
|
90 p[0] = 0;
|
|
91 }
|
|
92
|
|
93 static void
|
|
94 fail (const char *msg1, size_t msg1len, const char *msg3)
|
|
95 {
|
|
96 #ifdef __GNU_LIBRARY__
|
|
97 extern char * __progname;
|
|
98 #else
|
|
99 static const char __progname[] = "";
|
|
100 #endif
|
|
101 int fd;
|
|
102
|
|
103 /* Print error message directly to the tty. This avoids Bad Things
|
|
104 happening if stderr is redirected. */
|
|
105 fd = open (_PATH_TTY, O_WRONLY);
|
|
106 if (fd != -1)
|
|
107 {
|
|
108 static const char msg2[] = " terminated\n";
|
|
109 size_t progname_len, len;
|
|
110 char *buf, *p;
|
|
111
|
|
112 progname_len = strlen (__progname);
|
|
113 len = msg1len + progname_len + sizeof(msg2)-1 + 1;
|
|
114 p = buf = alloca (len);
|
|
115
|
|
116 memcpy (p, msg1, msg1len);
|
|
117 p += msg1len;
|
|
118 memcpy (p, __progname, progname_len);
|
|
119 p += progname_len;
|
|
120 memcpy (p, msg2, sizeof(msg2));
|
|
121
|
|
122 while (len > 0)
|
|
123 {
|
|
124 ssize_t wrote = write (fd, buf, len);
|
|
125 if (wrote < 0)
|
|
126 break;
|
|
127 buf += wrote;
|
|
128 len -= wrote;
|
|
129 }
|
|
130 close (fd);
|
|
131 }
|
|
132
|
|
133 #ifdef HAVE_SYSLOG_H
|
|
134 /* Only send the error to syslog if there was no tty available. */
|
|
135 else
|
|
136 syslog (LOG_CRIT, msg3);
|
|
137 #endif /* HAVE_SYSLOG_H */
|
|
138
|
|
139 /* Try very hard to exit. Note that signals may be blocked preventing
|
|
140 the first two options from working. The use of volatile is here to
|
|
141 prevent optimizers from "knowing" that __builtin_trap is called first,
|
|
142 and that it doesn't return, and so "obviously" the rest of the code
|
|
143 is dead. */
|
|
144 {
|
|
145 volatile int state;
|
|
146 for (state = 0; ; state++)
|
|
147 switch (state)
|
|
148 {
|
|
149 case 0:
|
|
150 __builtin_trap ();
|
|
151 break;
|
|
152 case 1:
|
|
153 *(volatile int *)-1L = 0;
|
|
154 break;
|
|
155 case 2:
|
|
156 _exit (127);
|
|
157 break;
|
|
158 }
|
|
159 }
|
|
160 }
|
|
161
|
|
162 void
|
|
163 __stack_chk_fail (void)
|
|
164 {
|
|
165 const char *msg = "*** stack smashing detected ***: ";
|
|
166 fail (msg, strlen (msg), "stack smashing detected: terminated");
|
|
167 }
|
|
168
|
|
169 void
|
|
170 __chk_fail (void)
|
|
171 {
|
|
172 const char *msg = "*** buffer overflow detected ***: ";
|
|
173 fail (msg, strlen (msg), "buffer overflow detected: terminated");
|
|
174 }
|
|
175
|
|
176 #ifdef HAVE_HIDDEN_VISIBILITY
|
|
177 void
|
|
178 __attribute__((visibility ("hidden")))
|
|
179 __stack_chk_fail_local (void)
|
|
180 {
|
|
181 __stack_chk_fail ();
|
|
182 }
|
|
183 #endif
|