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