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