OSDN Git Service

one reloc less, uninline, should save some space
[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
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 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 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 attribute_noreturn void terminate(void)
72 {
73         (void) kill(__getpid(), SSP_SIGTYPE);
74         _exit_internal(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         static const char message[] = ": stack smashing attack in function ";
81
82         block_signals();
83
84         ssp_write(STDERR_FILENO, __uclibc_progname, message, func);
85
86         /* The loop is added only to keep gcc happy. */
87         while(1)
88                 terminate();
89 }
90
91 void attribute_noreturn attribute_hidden __stack_chk_fail_internal(void)
92 {
93         static const char msg1[] = "stack smashing detected: ";
94         static const char msg3[] = " terminated";
95
96         block_signals();
97
98         ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3);
99
100         /* The loop is added only to keep gcc happy. */
101         while(1)
102                 terminate();
103 }
104 strong_alias(__stack_chk_fail_internal,__stack_chk_fail)
105
106 #if 0
107 void attribute_noreturn __chk_fail(void)
108 {
109         static const char msg1[] = "buffer overflow detected: ";
110         static const char msg3[] = " terminated";
111
112         block_signals();
113
114         ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3);
115
116         /* The loop is added only to keep gcc happy. */
117         while(1)
118                 terminate();
119 }
120 #endif