OSDN Git Service

touchup defines so that we can use same ssp.c in both glibc and uclibc
[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 #ifdef __SSP__
24 # error ssp.c has to be built w/ -fno-stack-protector
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/un.h>
34 #include <sys/syslog.h>
35 #include <sys/time.h>
36 #ifdef __SSP_USE_ERANDOM__
37 # include <sys/sysctl.h>
38 #endif
39
40 #ifdef __PROPOLICE_BLOCK_SEGV__
41 # define SSP_SIGTYPE SIGSEGV
42 #elif __PROPOLICE_BLOCK_KILL__
43 # define SSP_SIGTYPE SIGKILL
44 #else
45 # define SSP_SIGTYPE SIGABRT
46 #endif
47
48 unsigned long __guard = 0UL;
49
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
53  * functions.
54  */
55 #ifdef __UCLIBC__
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);
59 #else
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)
63 #endif
64
65 void __guard_setup(void) __attribute__ ((constructor));
66 void __guard_setup(void)
67 {
68         size_t size;
69         struct timeval tv;
70
71         if (__guard != 0UL)
72                 return;
73
74         /* Start with the "terminator canary". */
75         __guard = 0xFF0A0D00UL;
76
77 #ifndef __SSP_QUICK_CANARY__
78 # ifdef __SSP_USE_ERANDOM__
79         {
80                 int mib[3];
81                 /* Random is another depth in Linux, hence an array of 3. */
82                 mib[0] = CTL_KERN;
83                 mib[1] = KERN_RANDOM;
84                 mib[2] = RANDOM_ERANDOM;
85
86                 size = sizeof(unsigned long);
87                 if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1))
88                         if (__guard != 0UL)
89                                 return;
90         }
91 # endif /* ifdef __SSP_USE_ERANDOM__ */
92         /* 
93          * Attempt to open kernel pseudo random device if one exists before 
94          * opening urandom to avoid system entropy depletion.
95          */
96         {
97                 int fd;
98
99 # ifdef __SSP_USE_ERANDOM__
100                 if ((fd = __libc_open("/dev/erandom", O_RDONLY)) == (-1))
101 # endif
102                         fd = __libc_open("/dev/urandom", O_RDONLY);
103                 if (fd != (-1)) {
104                         size = __libc_read(fd, (char *) &__guard, sizeof(__guard));
105                         __libc_close(fd);
106                         if (size == sizeof(__guard))
107                                 return;
108                 }
109         }
110 #endif /* ifndef __SSP_QUICK_CANARY__ */
111
112         /* Everything failed? Or we are using a weakened model of the 
113          * terminator canary */
114
115         gettimeofday(&tv, NULL);
116         __guard ^= tv.tv_usec ^ tv.tv_sec;
117 }
118
119 void __stack_smash_handler(char func[], int damaged __attribute__ ((unused)));
120 void __stack_smash_handler(char func[], int damaged)
121 {
122         extern char *__progname;
123         const char message[] = ": stack smashing attack in function ";
124         struct sigaction sa;
125         sigset_t mask;
126
127         sigfillset(&mask);
128
129         sigdelset(&mask, SSP_SIGTYPE);  /* Block all signal handlers */
130         sigprocmask(SIG_BLOCK, &mask, NULL);    /* except SSP_SIGTYPE */
131
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);
135
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 */
139         sa.sa_flags = 0;
140         sa.sa_handler = SIG_DFL;
141         sigaction(SSP_SIGTYPE, &sa, NULL);
142         (void) kill(getpid(), SSP_SIGTYPE);
143         _exit(127);
144 }