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