]> git.ipfire.org Git - ipfire-3.x.git/blob - pkgs/core/glibc/glibc-2.10.1-stack_chk_fail.c
naoki: Initial checkin.
[ipfire-3.x.git] / pkgs / core / glibc / glibc-2.10.1-stack_chk_fail.c
1 /* Copyright (C) 2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19 /* Copyright (C) 2006-2007 Gentoo Foundation Inc.
20 * License terms as above.
21 *
22 * Hardened Gentoo SSP handler
23 *
24 * An SSP failure handler that does not use functions from the rest of
25 * glibc; it uses the INTERNAL_SYSCALL methods directly. This ensures
26 * no possibility of recursion into the handler.
27 *
28 * Direct all bug reports to http://bugs.gentoo.org/
29 *
30 * Re-written from the glibc-2.3 Hardened Gentoo SSP handler
31 * by Kevin F. Quinn - <kevquinn[@]gentoo.org>
32 *
33 * The following people contributed to the glibc-2.3 Hardened
34 * Gentoo SSP handler, from which this implementation draws much:
35 *
36 * Ned Ludd - <solar[@]gentoo.org>
37 * Alexander Gabert - <pappy[@]gentoo.org>
38 * The PaX Team - <pageexec[@]freemail.hu>
39 * Peter S. Mazinger - <ps.m[@]gmx.net>
40 * Yoann Vandoorselaere - <yoann[@]prelude-ids.org>
41 * Robert Connolly - <robert[@]linuxfromscratch.org>
42 * Cory Visi <cory[@]visi.name>
43 * Mike Frysinger <vapier[@]gentoo.org>
44 */
45
46 #include <errno.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <signal.h>
50
51 #include <sys/types.h>
52
53 #include <sysdep-cancel.h>
54 #include <sys/syscall.h>
55 #include <bp-checks.h>
56
57 #include <kernel-features.h>
58
59 #include <alloca.h>
60 /* from sysdeps */
61 #include <socketcall.h>
62 /* for the stuff in bits/socket.h */
63 #include <sys/socket.h>
64 #include <sys/un.h>
65
66
67 /* Sanity check on SYSCALL macro names - force compilation
68 * failure if the names used here do not exist
69 */
70 #if !defined __NR_socketcall && !defined __NR_socket
71 # error Cannot do syscall socket or socketcall
72 #endif
73 #if !defined __NR_socketcall && !defined __NR_connect
74 # error Cannot do syscall connect or socketcall
75 #endif
76 #ifndef __NR_write
77 # error Cannot do syscall write
78 #endif
79 #ifndef __NR_close
80 # error Cannot do syscall close
81 #endif
82 #ifndef __NR_getpid
83 # error Cannot do syscall getpid
84 #endif
85 #ifndef __NR_kill
86 # error Cannot do syscall kill
87 #endif
88 #ifndef __NR_exit
89 # error Cannot do syscall exit
90 #endif
91 #ifdef SSP_SMASH_DUMPS_CORE
92 # define ENABLE_SSP_SMASH_DUMPS_CORE 1
93 # if !defined _KERNEL_NSIG && !defined _NSIG
94 # error No _NSIG or _KERNEL_NSIG for rt_sigaction
95 # endif
96 # if !defined __NR_sigaction && !defined __NR_rt_sigaction
97 # error Cannot do syscall sigaction or rt_sigaction
98 # endif
99 /* Although rt_sigaction expects sizeof(sigset_t) - it expects the size
100 * of the _kernel_ sigset_t which is not the same as the user sigset_t.
101 * Most arches have this as _NSIG bits - mips has _KERNEL_NSIG bits for
102 * some reason.
103 */
104 # ifdef _KERNEL_NSIG
105 # define _SSP_NSIG _KERNEL_NSIG
106 # else
107 # define _SSP_NSIG _NSIG
108 # endif
109 #else
110 # define _SSP_NSIG 0
111 # define ENABLE_SSP_SMASH_DUMPS_CORE 0
112 #endif
113
114 /* Define DO_SIGACTION - default to newer rt signal interface but
115 * fallback to old as needed.
116 */
117 #ifdef __NR_rt_sigaction
118 # define DO_SIGACTION(signum, act, oldact) \
119 INLINE_SYSCALL(rt_sigaction, 4, signum, act, oldact, _SSP_NSIG/8)
120 #else
121 # define DO_SIGACTION(signum, act, oldact) \
122 INLINE_SYSCALL(sigaction, 3, signum, act, oldact)
123 #endif
124
125 /* Define DO_SOCKET/DO_CONNECT functions to deal with socketcall vs socket/connect */
126 #if defined(__NR_socket) && defined(__NR_connect)
127 # define USE_OLD_SOCKETCALL 0
128 #else
129 # define USE_OLD_SOCKETCALL 1
130 #endif
131 /* stub out the __NR_'s so we can let gcc optimize away dead code */
132 #ifndef __NR_socketcall
133 # define __NR_socketcall 0
134 #endif
135 #ifndef __NR_socket
136 # define __NR_socket 0
137 #endif
138 #ifndef __NR_connect
139 # define __NR_connect 0
140 #endif
141 #define DO_SOCKET(result, domain, type, protocol) \
142 do { \
143 if (USE_OLD_SOCKETCALL) { \
144 socketargs[0] = domain; \
145 socketargs[1] = type; \
146 socketargs[2] = protocol; \
147 socketargs[3] = 0; \
148 result = INLINE_SYSCALL(socketcall, 2, SOCKOP_socket, socketargs); \
149 } else \
150 result = INLINE_SYSCALL(socket, 3, domain, type, protocol); \
151 } while (0)
152 #define DO_CONNECT(result, sockfd, serv_addr, addrlen) \
153 do { \
154 if (USE_OLD_SOCKETCALL) { \
155 socketargs[0] = sockfd; \
156 socketargs[1] = (unsigned long int)serv_addr; \
157 socketargs[2] = addrlen; \
158 socketargs[3] = 0; \
159 result = INLINE_SYSCALL(socketcall, 2, SOCKOP_connect, socketargs); \
160 } else \
161 result = INLINE_SYSCALL(connect, 3, sockfd, serv_addr, addrlen); \
162 } while (0)
163
164 #ifndef _PATH_LOG
165 # define _PATH_LOG "/dev/log"
166 #endif
167
168 static const char path_log[] = _PATH_LOG;
169
170 /* For building glibc with SSP switched on, define __progname to a
171 * constant if building for the run-time loader, to avoid pulling
172 * in more of libc.so into ld.so
173 */
174 #ifdef IS_IN_rtld
175 static char *__progname = "<rtld>";
176 #else
177 extern char *__progname;
178 #endif
179
180
181 /* Common handler code, used by stack_chk_fail and __stack_smash_handler
182 * Inlined to ensure no self-references to the handler within itself.
183 * Data static to avoid putting more than necessary on the stack,
184 * to aid core debugging.
185 */
186 __attribute__ ((__noreturn__ , __always_inline__))
187 static inline void
188 __hardened_gentoo_stack_chk_fail(char func[], int damaged)
189 {
190 #define MESSAGE_BUFSIZ 256
191 static pid_t pid;
192 static int plen, i;
193 static char message[MESSAGE_BUFSIZ];
194 static const char msg_ssa[] = ": stack smashing attack";
195 static const char msg_inf[] = " in function ";
196 static const char msg_ssd[] = "*** stack smashing detected ***: ";
197 static const char msg_terminated[] = " - terminated\n";
198 static const char msg_report[] = "Report to http://bugs.gentoo.org/\n";
199 static const char msg_unknown[] = "<unknown>";
200 static int log_socket, connect_result;
201 static struct sockaddr_un sock;
202 static unsigned long int socketargs[4];
203
204 /* Build socket address
205 */
206 sock.sun_family = AF_UNIX;
207 i = 0;
208 while ((path_log[i] != '\0') && (i<(sizeof(sock.sun_path)-1))) {
209 sock.sun_path[i] = path_log[i];
210 i++;
211 }
212 sock.sun_path[i] = '\0';
213
214 /* Try SOCK_DGRAM connection to syslog */
215 connect_result = -1;
216 DO_SOCKET(log_socket, AF_UNIX, SOCK_DGRAM, 0);
217 if (log_socket != -1)
218 DO_CONNECT(connect_result, log_socket, &sock, sizeof(sock));
219 if (connect_result == -1) {
220 if (log_socket != -1)
221 INLINE_SYSCALL(close, 1, log_socket);
222 /* Try SOCK_STREAM connection to syslog */
223 DO_SOCKET(log_socket, AF_UNIX, SOCK_STREAM, 0);
224 if (log_socket != -1)
225 DO_CONNECT(connect_result, log_socket, &sock, sizeof(sock));
226 }
227
228 /* Build message. Messages are generated both in the old style and new style,
229 * so that log watchers that are configured for the old-style message continue
230 * to work.
231 */
232 #define strconcat(str) \
233 {i=0; while ((str[i] != '\0') && ((i+plen)<(MESSAGE_BUFSIZ-1))) \
234 {\
235 message[plen+i]=str[i];\
236 i++;\
237 }\
238 plen+=i;}
239
240 /* R.Henderson post-gcc-4 style message */
241 plen = 0;
242 strconcat(msg_ssd);
243 if (__progname != (char *)0)
244 strconcat(__progname)
245 else
246 strconcat(msg_unknown);
247 strconcat(msg_terminated);
248
249 /* Write out error message to STDERR, to syslog if open */
250 INLINE_SYSCALL(write, 3, STDERR_FILENO, message, plen);
251 if (connect_result != -1)
252 INLINE_SYSCALL(write, 3, log_socket, message, plen);
253
254 /* Dr. Etoh pre-gcc-4 style message */
255 plen = 0;
256 if (__progname != (char *)0)
257 strconcat(__progname)
258 else
259 strconcat(msg_unknown);
260 strconcat(msg_ssa);
261 strconcat(msg_inf);
262 if (func != NULL)
263 strconcat(func)
264 else
265 strconcat(msg_unknown);
266 strconcat(msg_terminated);
267 /* Write out error message to STDERR, to syslog if open */
268 INLINE_SYSCALL(write, 3, STDERR_FILENO, message, plen);
269 if (connect_result != -1)
270 INLINE_SYSCALL(write, 3, log_socket, message, plen);
271
272 /* Direct reports to bugs.gentoo.org */
273 plen=0;
274 strconcat(msg_report);
275 message[plen++]='\0';
276
277 /* Write out error message to STDERR, to syslog if open */
278 INLINE_SYSCALL(write, 3, STDERR_FILENO, message, plen);
279 if (connect_result != -1)
280 INLINE_SYSCALL(write, 3, log_socket, message, plen);
281
282 if (log_socket != -1)
283 INLINE_SYSCALL(close, 1, log_socket);
284
285 /* Suicide */
286 pid = INLINE_SYSCALL(getpid, 0);
287
288 if (ENABLE_SSP_SMASH_DUMPS_CORE) {
289 static struct sigaction default_abort_act;
290 /* Remove any user-supplied handler for SIGABRT, before using it */
291 default_abort_act.sa_handler = SIG_DFL;
292 default_abort_act.sa_sigaction = NULL;
293 __sigfillset(&default_abort_act.sa_mask);
294 default_abort_act.sa_flags = 0;
295 if (DO_SIGACTION(SIGABRT, &default_abort_act, NULL) == 0)
296 INLINE_SYSCALL(kill, 2, pid, SIGABRT);
297 }
298
299 /* Note; actions cannot be added to SIGKILL */
300 INLINE_SYSCALL(kill, 2, pid, SIGKILL);
301
302 /* In case the kill didn't work, exit anyway
303 * The loop prevents gcc thinking this routine returns
304 */
305 while (1)
306 INLINE_SYSCALL(exit, 0);
307 }
308
309 __attribute__ ((__noreturn__))
310 void __stack_chk_fail(void)
311 {
312 __hardened_gentoo_stack_chk_fail(NULL, 0);
313 }
314
315 #ifdef ENABLE_OLD_SSP_COMPAT
316 __attribute__ ((__noreturn__))
317 void __stack_smash_handler(char func[], int damaged)
318 {
319 __hardened_gentoo_stack_chk_fail(func, damaged);
320 }
321 #endif