Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | --- stack_protector.c.orig 2010-10-07 09:55:01.000000000 -0700 +++ stack_protector.c 2010-10-07 09:55:30.000000000 -0700 @@ -28,65 +28,112 @@ */ #include <sys/param.h> -#include <sys/sysctl.h> #include <signal.h> #include <string.h> -#include <syslog.h> +#include <stdlib.h> +#include <asl.h> #include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include "CrashReporterClient.h" +#include "libproc.h" +#include "_simple.h" + +#define GUARD_MAX 8 +long __stack_chk_guard[GUARD_MAX] = {0, 0, 0, 0, 0, 0, 0, 0}; +void __abort(void) __dead2; +void __guard_setup(const char *apple[]) __attribute__ ((visibility ("hidden"))); +void __stack_chk_fail(void); -extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t); +static void +__guard_from_kernel(const char *str) +{ + unsigned long long val; + char tmp[20], *p; + int idx = 0; + + /* Skip over the 'stack_guard=' key to the list of values */ + str = strchr(str, '='); + if (str == NULL) + return; + str++; -long __guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -static void __guard_setup(void) __attribute__ ((constructor)); -void __stack_smash_handler(char func[], int damaged __attribute__((unused))); + while (str && idx < GUARD_MAX) { + /* + * Pull the next numeric string out of the list and convert it to + * a real number. + */ + strlcpy(tmp, str, 20); + p = strchr(tmp, ','); + if (p) + *p = '\0'; + val = strtoull(tmp, NULL, 0); + __stack_chk_guard[idx] = (long)(val & ((unsigned long) -1)); + idx++; + if ((str = strchr(str, ',')) != NULL) + str++; + } +} -static void -__guard_setup(void) +void +__guard_setup(const char *apple[]) { - int mib[2]; + int fd; size_t len; + const char **p; - if (__guard[0] != 0) + if (__stack_chk_guard[0] != 0) return; - mib[0] = CTL_KERN; - mib[1] = KERN_ARND; + for (p = apple; p && *p; p++) { + if (strstr(*p, "stack_guard") == *p) { + __guard_from_kernel(*p); + if (__stack_chk_guard[0] != 0) + return; + } + } - len = sizeof(__guard); - if (__sysctl(mib, 2, __guard, &len, NULL, 0) == -1 || - len != sizeof(__guard)) { - /* If sysctl was unsuccessful, use the "terminator canary". */ - ((unsigned char *)__guard)[0] = 0; - ((unsigned char *)__guard)[1] = 0; - ((unsigned char *)__guard)[2] = '\n'; - ((unsigned char *)__guard)[3] = 255; + fd = open ("/dev/urandom", 0); + if (fd != -1) { + len = read (fd, (char*)&__stack_chk_guard, sizeof(__stack_chk_guard)); + close(fd); + if (len == sizeof(__stack_chk_guard) && + *__stack_chk_guard != 0) + return; } + + /* If If a random generator can't be used, the protector switches the guard + to the "terminator canary" */ + ((unsigned char *)__stack_chk_guard)[0] = 0; + ((unsigned char *)__stack_chk_guard)[1] = 0; + ((unsigned char *)__stack_chk_guard)[2] = '\n'; + ((unsigned char *)__stack_chk_guard)[3] = 255; } -/*ARGSUSED*/ +#define STACKOVERFLOW "] stack overflow" + void -__stack_smash_handler(char func[], int damaged) +__stack_chk_fail() { - struct syslog_data sdata = SYSLOG_DATA_INIT; - const char message[] = "stack overflow in function %s"; - struct sigaction sa; - sigset_t mask; - - /* Immediately block all signal handlers from running code */ - sigfillset(&mask); - sigdelset(&mask, SIGABRT); - sigprocmask(SIG_BLOCK, &mask, NULL); - + char n[16]; // bigger than will hold the digits in a pid_t + char *np; + int pid = getpid(); + char message[sizeof(n) + sizeof(STACKOVERFLOW)] = "["; + char prog[2*MAXCOMLEN+1] = {0}; + + proc_name(pid, prog, 2*MAXCOMLEN); + prog[2*MAXCOMLEN] = 0; + np = n + sizeof(n); + *--np = 0; + while(pid > 0) { + *--np = (pid % 10) + '0'; + pid /= 10; + } + strlcat(message, np, sizeof(message)); + strlcat(message, STACKOVERFLOW, sizeof(message)); /* This may fail on a chroot jail... */ - syslog_r(LOG_CRIT, &sdata, message, func); - - bzero(&sa, sizeof(struct sigaction)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGABRT, &sa, NULL); - - kill(getpid(), SIGABRT); + _simple_asl_log_prog(ASL_LEVEL_CRIT, "user", message, prog); - _exit(127); + CRSetCrashLogMessage(message); + __abort(); } |