wok-current view glibc/stuff/glibc-2.23_ssp.patch @ rev 25775

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