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