]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp.c
Inital import
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / 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 #include <string.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #if defined __UCLIBC_HAS_SYSLOG__
33 #include <sys/syslog.h>
34
35 #endif
36
37
38 static void block_signals(void)
39 {
40         struct sigaction sa;
41         sigset_t mask;
42
43         __sigfillset(&mask);
44         __sigdelset(&mask, SSP_SIGTYPE);        /* Block all signal handlers */
45         sigprocmask(SIG_BLOCK, &mask, NULL);    /* except SSP_SIGTYPE */
46
47         /* Make the default handler associated with the signal handler */
48         memset(&sa, 0, sizeof(sa));
49         __sigfillset(&sa.sa_mask);      /* Block all signals */
50         if (SIG_DFL) /* if it's constant zero, it's already done */
51                 sa.sa_handler = SIG_DFL;
52         sigaction(SSP_SIGTYPE, &sa, NULL);
53 }
54
55 static void __cold ssp_write(int fd, const char *msg1, const char *msg2, const char *msg3)
56 {
57         write(fd, msg1, strlen(msg1));
58         write(fd, msg2, strlen(msg2));
59         write(fd, msg3, strlen(msg3));
60         write(fd, "()\n", 3);
61 #if defined __UCLIBC_HAS_SYSLOG__
62         openlog("ssp", LOG_CONS | LOG_PID, LOG_USER);
63         syslog(LOG_INFO, "%s%s%s()", msg1, msg2, msg3);
64         closelog();
65 #endif
66 }
67
68 static attribute_noreturn void terminate(void)
69 {
70         (void) kill(getpid(), SSP_SIGTYPE);
71         _exit(127);
72 }
73
74 void __stack_smash_handler(char func[], int damaged __attribute__ ((unused))) attribute_noreturn __cold;
75 void __stack_smash_handler(char func[], int damaged)
76 {
77         static const char message[] = ": stack smashing attack in function ";
78
79         block_signals();
80
81         ssp_write(STDERR_FILENO, __uclibc_progname, message, func);
82
83         /* The loop is added only to keep gcc happy. */
84         while(1)
85                 terminate();
86 }
87
88 void __stack_chk_fail(void) attribute_noreturn __cold;
89 void __stack_chk_fail(void)
90 {
91         static const char msg1[] = "stack smashing detected: ";
92         static const char msg3[] = " terminated";
93
94         block_signals();
95
96         ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3);
97
98         /* The loop is added only to keep gcc happy. */
99         while(1)
100                 terminate();
101 }
102
103 void __chk_fail(void) attribute_noreturn;
104 void __chk_fail(void)
105 {
106         static const char msg1[] = "buffer overflow detected: ";
107         static const char msg3[] = " terminated";
108
109         block_signals();
110
111         ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3);
112
113         /* The loop is added only to keep gcc happy. */
114         while(1)
115                 terminate();
116 }
117