1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/*
* Distributed under the terms of the GNU General Public License v2
* $Header: /var/cvs/uClibc/libc/sysdeps/linux/common/ssp.c,v 1.6 2005/01/11 17:01:53 vapier Exp $
*
* This is a modified version of Hiroaki Etoh's stack smashing routines
* implemented for glibc.
*
* The following people have contributed input to this code.
* Ned Ludd - <solar[@]gentoo.org>
* Alexander Gabert - <pappy[@]gentoo.org>
* The PaX Team - <pageexec[@]freemail.hu>
* Peter S. Mazinger - <ps.m[@]gmx.net>
* Yoann Vandoorselaere - <yoann[@]prelude-ids.org>
* Robert Connolly - <robert[@]linuxfromscratch.org>
* Cory Visi <cory@visi.name>
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef __SSP__
#error ssp.c has to be built w/ -fno-stack-protector
#endif
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/syslog.h>
#include <sys/time.h>
#ifdef __SSP_USE_ERANDOM__
# include <sys/sysctl.h>
#endif
#ifdef __PROPOLICE_BLOCK_SEGV__
# define SSP_SIGTYPE SIGSEGV
#elif __PROPOLICE_BLOCK_KILL__
# define SSP_SIGTYPE SIGKILL
#else
# define SSP_SIGTYPE SIGABRT
#endif
/* prototypes */
extern int __libc_open (__const char *file, int oflag, ...);
extern ssize_t __libc_read(int fd, void *buf, size_t count);
extern int __libc_close (int fd);
unsigned long __guard = 0UL;
void __guard_setup(void) __attribute__ ((constructor));
void __guard_setup(void)
{
size_t size;
struct timeval tv;
if (__guard != 0UL)
return;
/* Start with the "terminator canary". */
__guard = 0xFF0A0D00UL;
#ifndef __SSP_QUICK_CANARY__
# ifdef __SSP_USE_ERANDOM__
int mib[3];
/* Random is another depth in Linux, hence an array of 3. */
mib[0] = CTL_KERN;
mib[1] = KERN_RANDOM;
mib[2] = RANDOM_ERANDOM;
size = sizeof(unsigned long);
if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1))
if (__guard != 0UL)
return;
# endif /* ifdef __SSP_USE_ERANDOM__ */
/*
* Attempt to open kernel pseudo random device if one exists before
* opening urandom to avoid system entropy depletion.
*/
{
int fd;
# ifdef __SSP_USE_ERANDOM__
if ((fd = __libc_open("/dev/erandom", O_RDONLY)) == (-1))
# endif
fd = __libc_open("/dev/urandom", O_RDONLY);
if (fd != (-1)) {
size = __libc_read(fd, (char *) &__guard, sizeof(__guard));
__libc_close(fd);
if (size == sizeof(__guard))
return;
}
}
#endif /* ifndef __SSP_QUICK_CANARY__ */
/* Everything failed? Or we are using a weakened model of the
* terminator canary */
gettimeofday(&tv, NULL);
__guard ^= tv.tv_usec ^ tv.tv_sec;
}
void __stack_smash_handler(char func[], int damaged __attribute__ ((unused)));
void __stack_smash_handler(char func[], int damaged)
{
extern char *__progname;
const char message[] = ": stack smashing attack in function ";
struct sigaction sa;
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SSP_SIGTYPE); /* Block all signal handlers */
sigprocmask(SIG_BLOCK, &mask, NULL); /* except SSP_SIGTYPE */
/* Print error message to stderr and syslog */
fprintf(stderr, "%s%s%s()\n", __progname, message, func);
syslog(LOG_INFO, "%s%s%s()", __progname, message, func);
/* Make the default handler associated with the signal handler */
memset(&sa, 0, sizeof(struct sigaction));
sigfillset(&sa.sa_mask); /* Block all signals */
sa.sa_flags = 0;
sa.sa_handler = SIG_DFL;
sigaction(SSP_SIGTYPE, &sa, NULL);
(void) kill(getpid(), SSP_SIGTYPE);
_exit(127);
}
|