X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/7c78c5292a74d7cc20fc03e02fbfc976e072f928..refs/heads/master:/sys/OpenBSD/stack_protector.c diff --git a/sys/OpenBSD/stack_protector.c b/sys/OpenBSD/stack_protector.c index 368e365..7ac7c7b 100644 --- a/sys/OpenBSD/stack_protector.c +++ b/sys/OpenBSD/stack_protector.c @@ -1,3 +1,5 @@ +/* $OpenBSD: stack_protector.c,v 1.10 2006/03/31 05:34:44 deraadt Exp $ */ + /* * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat. * All rights reserved. @@ -25,51 +27,106 @@ * */ -#if defined(LIBC_SCCS) && !defined(list) -static char rcsid[] = "$OpenBSD: stack_protector.c,v 1.3 2002/12/10 08:53:42 etoh Exp $"; -#endif - #include -#include -#include +#include +#include +#include +#include +#include +#include +#if __has_include() +#include +#else +#define CRSetCrashLogMessage(...) +#endif +#include "libproc.h" +#include "_simple.h" -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))); +#define GUARD_MAX 8 +long __stack_chk_guard[GUARD_MAX] = {0, 0, 0, 0, 0, 0, 0, 0}; +void __abort(void) __cold __dead2; +void __guard_setup(const char *apple[]) __attribute__ ((visibility ("hidden"))); +void __stack_chk_fail(void); static void -__guard_setup(void) +__guard_from_kernel(const char *str) { - int fd; - if (__guard[0]!=0) return; - fd = open ("/dev/urandom", 0); - if (fd != -1) { - ssize_t size = read (fd, (char*)&__guard, sizeof(__guard)); - close (fd) ; - if (size == sizeof(__guard)) return; - } - /* If a random generator can't be used, the protector switches the guard - to the "terminator canary" */ - ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0; - ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255; + 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++; + + 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++; + } } void -__stack_smash_handler(char func[], int damaged) +__guard_setup(const char *apple[]) { - const char message[] = "stack overflow in function %s"; - struct sigaction sa; + int fd; + size_t len; + const char **p; + + if (__stack_chk_guard[0] != 0) + return; - /* this may fail on a chroot jail, though luck */ - syslog(LOG_CRIT, message, func); + for (p = apple; p && *p; p++) { + if (strstr(*p, "stack_guard") == *p) { + __guard_from_kernel(*p); + bzero((void*)*p, strlen(*p)); + if (__stack_chk_guard[0] != 0) { + return; + } + } + } - bzero(&sa, sizeof(struct sigaction)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGABRT, &sa, NULL); + 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; +} + +static const char *stackoverflow_msg = "stack buffer overflow"; + +void +__stack_chk_fail() +{ + CRSetCrashLogMessage(stackoverflow_msg); - kill(getpid(), SIGABRT); + /* This may fail on a chroot jail... */ + char prog[2*MAXCOMLEN+1] = {0}; + proc_name(getpid(), prog, 2*MAXCOMLEN); + prog[2*MAXCOMLEN] = 0; + _simple_asl_log_prog(ASL_LEVEL_CRIT, "user", stackoverflow_msg, prog); - _exit(127); + __abort(); }