OSDN Git Service

- 2/NN patches for ssp. Updates from Peter S. Mazinger and Robert Connolly
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / common / ssp.c
1 /*
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 $
4  *
5  * This is a modified version of Hiroaki Etoh's stack smashing routines
6  * implemented for glibc.
7  *
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>
16  *
17  */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <sys/types.h>
29 #include <sys/un.h>
30 #include <sys/syslog.h>
31 #include <sys/time.h>
32 #ifdef __SSP_USE_ERANDOM__
33 #include <sys/sysctl.h>
34 #endif
35
36 #ifdef __PROPOLICE_BLOCK_SEGV__
37 #define SSP_SIGTYPE SIGSEGV
38 #elif __PROPOLICE_BLOCK_KILL__
39 #define SSP_SIGTYPE SIGKILL
40 #else
41 #define SSP_SIGTYPE SIGABRT
42 #endif
43
44 unsigned long __guard = 0UL;
45
46 void __guard_setup(void) __attribute__ ((constructor));
47 void __guard_setup(void)
48 {
49         size_t size;
50         struct timeval tv;
51
52         if (__guard != 0UL)
53                 return;
54
55         /* Start with the "terminator canary". */
56         __guard = 0xFF0A0D00UL;
57
58 #ifndef __SSP_QUICK_CANARY__
59 #ifdef __SSP_USE_ERANDOM__
60         int mib[3];
61         /* Random is another depth in Linux, hence an array of 3. */
62         mib[0] = CTL_KERN;
63         mib[1] = KERN_RANDOM;
64         mib[2] = RANDOM_ERANDOM;
65
66         size = sizeof(unsigned long);
67         if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1))
68                 if (__guard != 0UL)
69                         return;
70 #endif
71         /* 
72          * Attempt to open kernel pseudo random device if one exists before 
73          * opening urandom to avoid system entropy depletion.
74          */
75         {
76                 int fd;
77
78 #ifdef __SSP_USE_ERANDOM__
79                 if ((fd = __libc_open("/dev/erandom", O_RDONLY)) == (-1))
80 #endif
81                         fd = __libc_open("/dev/urandom", O_RDONLY);
82                 if (fd != (-1)) {
83                         size = __libc_read(fd, (char *) &__guard, sizeof(__guard));
84                         __libc_close(fd);
85                         if (size == sizeof(__guard))
86                                 return;
87                 }
88         }
89 #endif
90
91         /* Everything failed? Or we are using a weakened model of the 
92          * terminator canary */
93
94         gettimeofday(&tv, NULL);
95         __guard ^= tv.tv_usec ^ tv.tv_sec;
96 }
97
98 void __stack_smash_handler(char func[], int damaged __attribute__ ((unused)));
99 void __stack_smash_handler(char func[], int damaged)
100 {
101         extern char *__progname;
102         const char message[] = ": stack smashing attack in function ";
103         struct sigaction sa;
104         sigset_t mask;
105
106         sigfillset(&mask);
107
108         sigdelset(&mask, SSP_SIGTYPE);  /* Block all signal handlers */
109         sigprocmask(SIG_BLOCK, &mask, NULL);    /* except SSP_SIGTYPE */
110
111         /* Print error message to stderr and syslog */
112         fprintf(stderr, "%s%s%s()\n", __progname, message, func);
113         syslog(LOG_INFO, "%s%s%s()", __progname, message, func);
114
115         /* Make the default handler associated with the signal handler */
116         memset(&sa, 0, sizeof(struct sigaction));
117         sigfillset(&sa.sa_mask);        /* Block all signals */
118         sa.sa_flags = 0;
119         sa.sa_handler = SIG_DFL;
120         sigaction(SSP_SIGTYPE, &sa, NULL);
121         (void) kill(getpid(), SSP_SIGTYPE);
122         _exit(127);
123 }