xref: /dflybsd-src/lib/libc/secure/stack_protector.c (revision 7adf0194ed89f9c2abca05b9503ddfa3cf3ab403)
1*7adf0194SJohn Marino /*
2*7adf0194SJohn Marino  * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.
3*7adf0194SJohn Marino  * All rights reserved.
4*7adf0194SJohn Marino  *
5*7adf0194SJohn Marino  * Redistribution and use in source and binary forms, with or without
6*7adf0194SJohn Marino  * modification, are permitted provided that the following conditions
7*7adf0194SJohn Marino  * are met:
8*7adf0194SJohn Marino  * 1. Redistributions of source code must retain the above copyright
9*7adf0194SJohn Marino  *    notice, this list of conditions and the following disclaimer.
10*7adf0194SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
11*7adf0194SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
12*7adf0194SJohn Marino  *    documentation and/or other materials provided with the distribution.
13*7adf0194SJohn Marino  *
14*7adf0194SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
15*7adf0194SJohn Marino  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16*7adf0194SJohn Marino  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17*7adf0194SJohn Marino  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
18*7adf0194SJohn Marino  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19*7adf0194SJohn Marino  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20*7adf0194SJohn Marino  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*7adf0194SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22*7adf0194SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23*7adf0194SJohn Marino  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24*7adf0194SJohn Marino  * POSSIBILITY OF SUCH DAMAGE.
25*7adf0194SJohn Marino  *
26*7adf0194SJohn Marino  * $OpenBSD: stack_protector.c,v 1.3 2002/12/10 08:53:42 etoh Exp $
27*7adf0194SJohn Marino  */
28*7adf0194SJohn Marino 
29*7adf0194SJohn Marino #include "namespace.h"
30*7adf0194SJohn Marino #include <sys/param.h>
31*7adf0194SJohn Marino #include <sys/sysctl.h>
32*7adf0194SJohn Marino #include <fcntl.h>
33*7adf0194SJohn Marino #include <signal.h>
34*7adf0194SJohn Marino #include <stdio.h>
35*7adf0194SJohn Marino #include <string.h>
36*7adf0194SJohn Marino #include <syslog.h>
37*7adf0194SJohn Marino #include <unistd.h>
38*7adf0194SJohn Marino #include "un-namespace.h"
39*7adf0194SJohn Marino 
40*7adf0194SJohn Marino extern int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
41*7adf0194SJohn Marino 
42*7adf0194SJohn Marino long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43*7adf0194SJohn Marino static void __guard_setup(void) __attribute__ ((constructor));
44*7adf0194SJohn Marino static void __fail(const char *);
45*7adf0194SJohn Marino void __stack_chk_fail(void);
46*7adf0194SJohn Marino void __chk_fail(void);
47*7adf0194SJohn Marino 
48*7adf0194SJohn Marino static void
__guard_setup(void)49*7adf0194SJohn Marino __guard_setup(void)
50*7adf0194SJohn Marino {
51*7adf0194SJohn Marino     int fd;
52*7adf0194SJohn Marino     ssize_t size;
53*7adf0194SJohn Marino 
54*7adf0194SJohn Marino     if (__stack_chk_guard[0] != 0)
55*7adf0194SJohn Marino 	return;
56*7adf0194SJohn Marino     if ((fd = _open ("/dev/urandom", 0)) >= 0) {
57*7adf0194SJohn Marino 	size = _read (fd, (char*)&__stack_chk_guard, sizeof(__stack_chk_guard));
58*7adf0194SJohn Marino 	_close (fd);
59*7adf0194SJohn Marino 	if (size == sizeof(__stack_chk_guard))
60*7adf0194SJohn Marino 	    return;
61*7adf0194SJohn Marino     }
62*7adf0194SJohn Marino 
63*7adf0194SJohn Marino     /*
64*7adf0194SJohn Marino      * If a random generator can't be used, the protector switches the
65*7adf0194SJohn Marino      * guard to the "terminator canary"
66*7adf0194SJohn Marino      */
67*7adf0194SJohn Marino     ((char*)__stack_chk_guard)[0] = 0;
68*7adf0194SJohn Marino     ((char*)__stack_chk_guard)[1] = 0;
69*7adf0194SJohn Marino     ((char*)__stack_chk_guard)[2] = '\n';
70*7adf0194SJohn Marino     ((char*)__stack_chk_guard)[3] = 255;
71*7adf0194SJohn Marino }
72*7adf0194SJohn Marino 
73*7adf0194SJohn Marino static void
__fail(const char * msg)74*7adf0194SJohn Marino __fail(const char *msg)
75*7adf0194SJohn Marino {
76*7adf0194SJohn Marino     struct sigaction sa;
77*7adf0194SJohn Marino     sigset_t mask;
78*7adf0194SJohn Marino 
79*7adf0194SJohn Marino     /* Immediately block all signal handlers from running code */
80*7adf0194SJohn Marino     sigfillset(&mask);
81*7adf0194SJohn Marino     sigdelset(&mask, SIGABRT);
82*7adf0194SJohn Marino     _sigprocmask(SIG_BLOCK, &mask, NULL);
83*7adf0194SJohn Marino 
84*7adf0194SJohn Marino     /* This may fail on a chroot jail... */
85*7adf0194SJohn Marino     syslog(LOG_CRIT, "%s", msg);
86*7adf0194SJohn Marino 
87*7adf0194SJohn Marino     bzero(&sa, sizeof(struct sigaction));
88*7adf0194SJohn Marino     sigemptyset(&sa.sa_mask);
89*7adf0194SJohn Marino     sa.sa_flags = 0;
90*7adf0194SJohn Marino     sa.sa_handler = SIG_DFL;
91*7adf0194SJohn Marino     __sys_sigaction(SIGABRT, &sa, NULL);
92*7adf0194SJohn Marino     kill(getpid(), SIGABRT);
93*7adf0194SJohn Marino     _exit(127);
94*7adf0194SJohn Marino }
95*7adf0194SJohn Marino 
96*7adf0194SJohn Marino void
__stack_chk_fail(void)97*7adf0194SJohn Marino __stack_chk_fail(void)
98*7adf0194SJohn Marino {
99*7adf0194SJohn Marino     __fail("stack overflow detected; terminated");
100*7adf0194SJohn Marino }
101*7adf0194SJohn Marino 
102*7adf0194SJohn Marino void
__chk_fail(void)103*7adf0194SJohn Marino __chk_fail(void)
104*7adf0194SJohn Marino {
105*7adf0194SJohn Marino     __fail("buffer overflow detected; terminated");
106*7adf0194SJohn Marino }
107*7adf0194SJohn Marino 
108*7adf0194SJohn Marino #ifndef PIC
109*7adf0194SJohn Marino __weak_reference(__stack_chk_fail, __stack_chk_fail_local);
110*7adf0194SJohn Marino #endif
111