stack_protector.c
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 46 long __stack_chk_guard[GUARD_MAX] = {0, 0, 0, 0, 0, 0, 0, 0}; 47 void __abort(void) __cold __dead2; 48 void __guard_setup(const char *apple[]) __attribute__ ((visibility ("hidden"))); 49 void __stack_chk_fail(void); 50 51 static 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 81 void 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 118 static const char *stackoverflow_msg = "stack buffer overflow"; 119 120 void 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 }