OSDN Git Service

Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[pf3gnuchains/gcc-fork.git] / libssp / ssp.c
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