2 * Distributed under the terms of the GNU General Public License v2
3 * $Header: /var/cvs/uClibc/libc/sysdeps/linux/common/ssp.c,v 1.6 2005/01/11 17:01:53 vapier Exp $
5 * This is a modified version of Hiroaki Etoh's stack smashing routines
6 * implemented for glibc.
8 * The following people have contributed input to this code.
9 * Ned Ludd - <solar[@]gentoo.org>
10 * Alexander Gabert - <pappy[@]gentoo.org>
11 * The PaX Team - <pageexec[@]freemail.hu>
12 * Peter S. Mazinger - <ps.m[@]gmx.net>
13 * Yoann Vandoorselaere - <yoann[@]prelude-ids.org>
14 * Robert Connolly - <robert[@]linuxfromscratch.org>
15 * Cory Visi <cory@visi.name>
24 # error ssp.c has to be built w/ -fno-stack-protector
32 #include <sys/types.h>
34 #include <sys/syslog.h>
36 #ifdef __SSP_USE_ERANDOM__
37 # include <sys/sysctl.h>
40 #ifdef __PROPOLICE_BLOCK_SEGV__
41 # define SSP_SIGTYPE SIGSEGV
42 #elif __PROPOLICE_BLOCK_KILL__
43 # define SSP_SIGTYPE SIGKILL
45 # define SSP_SIGTYPE SIGABRT
48 unsigned long __guard = 0UL;
50 /* Use of __* functions from the rest of glibc here avoids
51 * initialisation problems for executables preloaded with
52 * libraries that overload the associated standard library
56 extern int __libc_open(__const char *file, int flags, ...);
57 extern ssize_t __libc_read(int fd, void *buf, size_t count);
58 extern int __libc_close(int fd);
60 # define __libc_open(file, flags) __open(file, flags)
61 # define __libc_read(fd, buf, count) __read(fd, buf, count)
62 # define __libc_close(fd) __close(fd)
65 void __guard_setup(void) __attribute__ ((constructor));
66 void __guard_setup(void)
74 /* Start with the "terminator canary". */
75 __guard = 0xFF0A0D00UL;
77 #ifndef __SSP_QUICK_CANARY__
78 # ifdef __SSP_USE_ERANDOM__
81 /* Random is another depth in Linux, hence an array of 3. */
84 mib[2] = RANDOM_ERANDOM;
86 size = sizeof(unsigned long);
87 if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1))
91 # endif /* ifdef __SSP_USE_ERANDOM__ */
93 * Attempt to open kernel pseudo random device if one exists before
94 * opening urandom to avoid system entropy depletion.
99 # ifdef __SSP_USE_ERANDOM__
100 if ((fd = __libc_open("/dev/erandom", O_RDONLY)) == (-1))
102 fd = __libc_open("/dev/urandom", O_RDONLY);
104 size = __libc_read(fd, (char *) &__guard, sizeof(__guard));
106 if (size == sizeof(__guard))
110 #endif /* ifndef __SSP_QUICK_CANARY__ */
112 /* Everything failed? Or we are using a weakened model of the
113 * terminator canary */
115 gettimeofday(&tv, NULL);
116 __guard ^= tv.tv_usec ^ tv.tv_sec;
119 void __stack_smash_handler(char func[], int damaged __attribute__ ((unused)));
120 void __stack_smash_handler(char func[], int damaged)
122 extern char *__progname;
123 const char message[] = ": stack smashing attack in function ";
129 sigdelset(&mask, SSP_SIGTYPE); /* Block all signal handlers */
130 sigprocmask(SIG_BLOCK, &mask, NULL); /* except SSP_SIGTYPE */
132 /* Print error message to stderr and syslog */
133 fprintf(stderr, "%s%s%s()\n", __progname, message, func);
134 syslog(LOG_INFO, "%s%s%s()", __progname, message, func);
136 /* Make the default handler associated with the signal handler */
137 memset(&sa, 0, sizeof(struct sigaction));
138 sigfillset(&sa.sa_mask); /* Block all signals */
140 sa.sa_handler = SIG_DFL;
141 sigaction(SSP_SIGTYPE, &sa, NULL);
142 (void) kill(getpid(), SSP_SIGTYPE);