Changeset View
Changeset View
Standalone View
Standalone View
lib/libc/secure/stack_protector.c
Show All 27 Lines | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <errno.h> | #include <secure/security.h> | ||||
#include <link.h> | #include <link.h> | ||||
#include <signal.h> | |||||
#include <string.h> | |||||
#include <syslog.h> | |||||
#include <unistd.h> | |||||
#include "libc_private.h" | #include "libc_private.h" | ||||
extern int __sysctl(const int *name, u_int namelen, void *oldp, | extern int __sysctl(const int *name, u_int namelen, void *oldp, | ||||
size_t *oldlenp, void *newp, size_t newlen); | size_t *oldlenp, void *newp, size_t newlen); | ||||
long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
static void __guard_setup(void) __attribute__((__constructor__, __used__)); | static void __guard_setup(void) __attribute__((__constructor__, __used__)); | ||||
static void __fail(const char *); | void __stack_chk_fail(void) __dead2; | ||||
void __stack_chk_fail(void); | |||||
void __chk_fail(void); | |||||
/*LINTED used*/ | /*LINTED used*/ | ||||
static void | static void | ||||
__guard_setup(void) | __guard_setup(void) | ||||
{ | { | ||||
static const int mib[2] = { CTL_KERN, KERN_ARND }; | static const int mib[2] = { CTL_KERN, KERN_ARND }; | ||||
size_t len; | size_t len; | ||||
int error; | int error; | ||||
Show All 11 Lines | if (__sysctl(mib, nitems(mib), __stack_chk_guard, &len, NULL, 0) == | ||||
/* If sysctl was unsuccessful, use the "terminator canary". */ | /* If sysctl was unsuccessful, use the "terminator canary". */ | ||||
((unsigned char *)(void *)__stack_chk_guard)[0] = 0; | ((unsigned char *)(void *)__stack_chk_guard)[0] = 0; | ||||
((unsigned char *)(void *)__stack_chk_guard)[1] = 0; | ((unsigned char *)(void *)__stack_chk_guard)[1] = 0; | ||||
((unsigned char *)(void *)__stack_chk_guard)[2] = '\n'; | ((unsigned char *)(void *)__stack_chk_guard)[2] = '\n'; | ||||
((unsigned char *)(void *)__stack_chk_guard)[3] = 255; | ((unsigned char *)(void *)__stack_chk_guard)[3] = 255; | ||||
} | } | ||||
} | } | ||||
/*ARGSUSED*/ | |||||
static void | |||||
__fail(const char *msg) | |||||
{ | |||||
struct sigaction sa; | |||||
sigset_t mask; | |||||
/* Immediately block all signal handlers from running code */ | |||||
(void)sigfillset(&mask); | |||||
(void)sigdelset(&mask, SIGABRT); | |||||
(void)sigprocmask(SIG_BLOCK, &mask, NULL); | |||||
/* This may fail on a chroot jail... */ | |||||
syslog(LOG_CRIT, "%s", msg); | |||||
(void)memset(&sa, 0, sizeof(sa)); | |||||
(void)sigemptyset(&sa.sa_mask); | |||||
sa.sa_flags = 0; | |||||
sa.sa_handler = SIG_DFL; | |||||
(void)sigaction(SIGABRT, &sa, NULL); | |||||
(void)kill(getpid(), SIGABRT); | |||||
_exit(127); | |||||
} | |||||
void | void | ||||
__stack_chk_fail(void) | __stack_chk_fail(void) | ||||
{ | { | ||||
__fail("stack overflow detected; terminated"); | |||||
__secure_fail("stack overflow detected; terminated"); | |||||
} | } | ||||
void | void | ||||
__chk_fail(void) | __chk_fail(void) | ||||
{ | { | ||||
__fail("buffer overflow detected; terminated"); | |||||
__secure_fail("buffer overflow detected; terminated"); | |||||
} | } | ||||
#ifndef PIC | #ifndef PIC | ||||
__weak_reference(__stack_chk_fail, __stack_chk_fail_local); | __weak_reference(__stack_chk_fail, __stack_chk_fail_local); | ||||
#endif | #endif |