xref: /dflybsd-src/contrib/gcc-4.7/libssp/ssp.c (revision 67c744ecd15f590c78d183d567cc0077469be152)
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