]> git.saurik.com Git - apple/libc.git/blame_incremental - sys/OpenBSD/stack_protector.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / sys / OpenBSD / stack_protector.c
... / ...
CommitLineData
1/* $OpenBSD: stack_protector.c,v 1.10 2006/03/31 05:34:44 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#include <sys/param.h>
31#include <signal.h>
32#include <string.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <sys/types.h>
36#include <fcntl.h>
37#if __has_include(<CrashReporterClient.h>)
38#include <CrashReporterClient.h>
39#else
40#define CRSetCrashLogMessage(...)
41#endif
42#include "libproc.h"
43#include "_simple.h"
44
45#define GUARD_MAX 8
46long __stack_chk_guard[GUARD_MAX] = {0, 0, 0, 0, 0, 0, 0, 0};
47void __abort(void) __cold __dead2;
48void __guard_setup(const char *apple[]) __attribute__ ((visibility ("hidden")));
49void __stack_chk_fail(void);
50
51static void
52__guard_from_kernel(const char *str)
53{
54 unsigned long long val;
55 char tmp[20], *p;
56 int idx = 0;
57
58 /* Skip over the 'stack_guard=' key to the list of values */
59 str = strchr(str, '=');
60 if (str == NULL)
61 return;
62 str++;
63
64 while (str && idx < GUARD_MAX) {
65 /*
66 * Pull the next numeric string out of the list and convert it to
67 * a real number.
68 */
69 strlcpy(tmp, str, 20);
70 p = strchr(tmp, ',');
71 if (p)
72 *p = '\0';
73 val = strtoull(tmp, NULL, 0);
74 __stack_chk_guard[idx] = (long)(val & ((unsigned long) -1));
75 idx++;
76 if ((str = strchr(str, ',')) != NULL)
77 str++;
78 }
79}
80
81void
82__guard_setup(const char *apple[])
83{
84 int fd;
85 size_t len;
86 const char **p;
87
88 if (__stack_chk_guard[0] != 0)
89 return;
90
91 for (p = apple; p && *p; p++) {
92 if (strstr(*p, "stack_guard") == *p) {
93 __guard_from_kernel(*p);
94 bzero((void*)*p, strlen(*p));
95 if (__stack_chk_guard[0] != 0) {
96 return;
97 }
98 }
99 }
100
101 fd = open ("/dev/urandom", 0);
102 if (fd != -1) {
103 len = read (fd, (char*)&__stack_chk_guard, sizeof(__stack_chk_guard));
104 close(fd);
105 if (len == sizeof(__stack_chk_guard) &&
106 *__stack_chk_guard != 0)
107 return;
108 }
109
110 /* If If a random generator can't be used, the protector switches the guard
111 to the "terminator canary" */
112 ((unsigned char *)__stack_chk_guard)[0] = 0;
113 ((unsigned char *)__stack_chk_guard)[1] = 0;
114 ((unsigned char *)__stack_chk_guard)[2] = '\n';
115 ((unsigned char *)__stack_chk_guard)[3] = 255;
116}
117
118static const char *stackoverflow_msg = "stack buffer overflow";
119
120void
121__stack_chk_fail()
122{
123 CRSetCrashLogMessage(stackoverflow_msg);
124
125 /* This may fail on a chroot jail... */
126 char prog[2*MAXCOMLEN+1] = {0};
127 proc_name(getpid(), prog, 2*MAXCOMLEN);
128 prog[2*MAXCOMLEN] = 0;
129 _simple_asl_log_prog(ASL_LEVEL_CRIT, "user", stackoverflow_msg, prog);
130
131 __abort();
132}