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