1 /* $OpenBSD: stack_protector.c,v 1.10 2006/03/31 05:34:44 deraadt Exp $ */
2
3 /*
4 * Copyright © 2009, 2011, 2013, 2014
5 * Thorsten “mirabilos” Glaser <tg@mirbsd.org>
6 * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32 #include <sys/param.h>
33 #include <signal.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <syslog.h>
37 #include <unistd.h>
38
39 __RCSID("$MirOS: src/lib/libc/sys/stack_protector.c,v 1.14 2014/02/19 22:47:52 tg Exp $");
40
41 #if (defined(__SSP__) || defined(__SSP_ALL__)) && \
42 !defined(__IN_MKDEP) && !defined(lint)
43 #error "You must compile this file with -fno-stack-protector"
44 #endif
45
46 #ifdef lint
47 #define CONSTRUCTOR
48 #elif defined(__PCC__)
49 #define CONSTRUCTOR _Pragma("init")
50 #else
51 #define CONSTRUCTOR static __attribute__((__constructor__))
52 #endif
53
54 extern void _thread_sys__exit__(int) __dead;
55 extern void arc4random_atexit(void);
56
57 long __guard[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* gcc (3.4 ProPolice) */
58 int __stack_chk_guard = 0; /* gcc4 libssp and pcc */
59 CONSTRUCTOR void __guard_setup(void);
60 __dead void __stack_smash_handler(const char func[], int damaged);
61 __dead void __stack_chk_fail(void);
62
63 static const char message[] = "stack overflow in function %s (damaged: %d)";
64
65 CONSTRUCTOR void
__guard_setup(void)66 __guard_setup(void)
67 {
68 uint8_t newguard[MAX(sizeof(__guard), sizeof(__stack_chk_guard))];
69
70 while (__stack_chk_guard == 0) {
71 arc4random_buf(newguard, sizeof(__stack_chk_guard));
72 memcpy(&__stack_chk_guard, newguard, sizeof(__stack_chk_guard));
73 }
74
75 while (__guard[0] == 0) {
76 arc4random_buf(newguard, sizeof(__guard));
77 newguard[17] = 0;
78 newguard[18] = '\n';
79 newguard[19] = 255;
80 memcpy(__guard, newguard, sizeof(__guard));
81 }
82 }
83
84 /* ARGSUSED1 */
85 void
__stack_smash_handler(const char func[],int damaged)86 __stack_smash_handler(const char func[], int damaged)
87 {
88 struct syslog_data sdata = SYSLOG_DATA_INIT;
89 struct sigaction sa;
90 sigset_t mask;
91
92 /* Immediately block all signal handlers from running code */
93 sigfillset(&mask);
94 sigdelset(&mask, SIGABRT);
95 sigprocmask(SIG_BLOCK, &mask, NULL);
96
97 /* This may fail on a chroot jail... */
98 syslog_r(LOG_CRIT, &sdata, message, func, damaged);
99
100 memset(&sa, 0, sizeof(struct sigaction));
101 sigemptyset(&sa.sa_mask);
102 sa.sa_flags = 0;
103 sa.sa_handler = SIG_DFL;
104 sigaction(SIGABRT, &sa, NULL);
105
106 arc4random_atexit();
107
108 kill(getpid(), SIGABRT);
109
110 _thread_sys__exit__(127);
111 }
112
113 void
__stack_chk_fail(void)114 __stack_chk_fail(void)
115 {
116 __stack_smash_handler("unknown (libssp or pcc)", 0);
117 }
118