OSDN Git Service

49d2cbf6541c59844f1acfb7ece9d29381a78237
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / common / ssp.c
1 /*
2  * Distributed under the terms of the GNU Lesser General Public License
3  * $Header: $
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  * Mike Frysinger <vapier[@]gentoo.org>
17  */
18
19 #if defined __SSP__ || defined __SSP_ALL__
20 #error "file must not be compiled with stack protection enabled on it. Use -fno-stack-protector"
21 #endif
22
23 #ifdef __PROPOLICE_BLOCK_SEGV__
24 # define SSP_SIGTYPE SIGSEGV
25 #else
26 # define SSP_SIGTYPE SIGABRT
27 #endif
28
29 #define openlog __openlog
30 #define syslog __syslog
31 #define closelog __closelog
32 #define sigfillset __sigfillset_internal
33 #define sigdelset __sigdelset_internal
34 #define sigaction __sigaction_internal
35 #define kill __kill
36
37 #include <string.h>
38 #include <unistd.h>
39 #include <signal.h>
40 #include <sys/syslog.h>
41
42 static __always_inline void block_signals(void)
43 {
44         struct sigaction sa;
45         sigset_t mask;
46
47         sigfillset(&mask);
48
49         sigdelset(&mask, SSP_SIGTYPE);  /* Block all signal handlers */
50         __sigprocmask(SIG_BLOCK, &mask, NULL);  /* except SSP_SIGTYPE */
51
52         /* Make the default handler associated with the signal handler */
53         __memset(&sa, 0, sizeof(struct sigaction));
54         sigfillset(&sa.sa_mask);        /* Block all signals */
55         sa.sa_flags = 0;
56         sa.sa_handler = SIG_DFL;
57         sigaction(SSP_SIGTYPE, &sa, NULL);
58 }
59
60 static __always_inline void ssp_write(int fd, const char *msg1, const char *msg2, const char *msg3)
61 {
62         __write(fd, msg1, __strlen(msg1));
63         __write(fd, msg2, __strlen(msg2));
64         __write(fd, msg3, __strlen(msg3));
65         __write(fd, "()\n", 3);
66         openlog("ssp", LOG_CONS | LOG_PID, LOG_USER);
67         syslog(LOG_INFO, "%s%s%s()", msg1, msg2, msg3);
68         closelog();
69 }
70
71 static __always_inline attribute_noreturn void terminate(void)
72 {
73         (void) kill(__getpid(), SSP_SIGTYPE);
74         _exit(127);
75 }
76
77 void attribute_noreturn __stack_smash_handler(char func[], int damaged __attribute__ ((unused)));
78 void attribute_noreturn __stack_smash_handler(char func[], int damaged)
79 {
80         extern char *__progname;
81         static const char message[] = ": stack smashing attack in function ";
82
83         block_signals();
84
85         ssp_write(STDERR_FILENO, __progname, message, func);
86
87         /* The loop is added only to keep gcc happy. */
88         while(1)
89                 terminate();
90 }
91
92 void attribute_noreturn __stack_chk_fail(void)
93 {
94         extern char *__progname;
95         static const char msg1[] = "stack smashing detected: ";
96         static const char msg3[] = " terminated";
97
98         block_signals();
99
100         ssp_write(STDERR_FILENO, msg1, __progname, msg3);
101
102         /* The loop is added only to keep gcc happy. */
103         while(1)
104                 terminate();
105 }
106
107 #if 0
108 void attribute_noreturn __chk_fail(void)
109 {
110         extern char *__progname;
111         static const char msg1[] = "buffer overflow detected: ";
112         static const char msg3[] = " terminated";
113
114         block_signals();
115
116         ssp_write(STDERR_FILENO, msg1, __progname, msg3);
117
118         /* The loop is added only to keep gcc happy. */
119         while(1)
120                 terminate();
121 }
122 #endif