diff options
Diffstat (limited to 'libc/sysdeps/linux/common')
-rw-r--r-- | libc/sysdeps/linux/common/ssp.c | 121 |
1 files changed, 66 insertions, 55 deletions
diff --git a/libc/sysdeps/linux/common/ssp.c b/libc/sysdeps/linux/common/ssp.c index 07513e7c4..8dcc3dc59 100644 --- a/libc/sysdeps/linux/common/ssp.c +++ b/libc/sysdeps/linux/common/ssp.c @@ -20,102 +20,113 @@ #error "file must not be compiled with stack protection enabled on it. Use -fno-stack-protector" #endif +#include <string.h> +#include <unistd.h> +#include <signal.h> +#ifdef __UCLIBC_HAS_SYSLOG__ +#include <sys/syslog.h> +#endif + #ifdef __PROPOLICE_BLOCK_SEGV__ # define SSP_SIGTYPE SIGSEGV #else # define SSP_SIGTYPE SIGABRT #endif -#include <string.h> -#include <unistd.h> -#include <signal.h> -#if defined __UCLIBC_HAS_SYSLOG__ -#include <sys/syslog.h> +static void do_write(const char *msg) +{ + /* could use inlined syscall here to be sure ... */ + return (void) write(STDERR_FILENO, msg, strlen(msg)); +} +static void __cold do_msg(const char *msg1, const char *msg2, const char *msg3) +{ + do_write(msg1); + do_write(msg2); + do_write(msg3); + do_write("\n"); +#ifdef __UCLIBC_HAS_SYSLOG__ + syslog(LOG_INFO, "%s%s%s()", msg1, msg2, msg3); #endif +} - -static void block_signals(void) +static void __cold attribute_noreturn +#ifdef __UCLIBC_HAS_SSP_COMPAT__ +ssp_handler(char func[]) +#else +ssp_handler(void) +#endif { + pid_t pid; + static const char msg_ssd[] = "*** stack smashing detected ***: "; + static const char msg_terminated[] = " terminated"; +#ifdef __UCLIBC_HAS_SSP_COMPAT__ + static const char msg_ssa[] = ": stack smashing attack in function "; +#endif + +#ifdef __DODEBUG__ struct sigaction sa; sigset_t mask; __sigfillset(&mask); __sigdelset(&mask, SSP_SIGTYPE); /* Block all signal handlers */ sigprocmask(SIG_BLOCK, &mask, NULL); /* except SSP_SIGTYPE */ +#endif + +#ifdef __UCLIBC_HAS_SSP_COMPAT__ + if (func != NULL) + do_msg(__uclibc_progname, msg_ssa, func); + else +#endif + do_msg(msg_ssd, __uclibc_progname, msg_terminated); + pid = getpid(); +#ifdef __DODEBUG__ /* Make the default handler associated with the signal handler */ memset(&sa, 0, sizeof(sa)); __sigfillset(&sa.sa_mask); /* Block all signals */ if (SIG_DFL) /* if it's constant zero, it's already done */ sa.sa_handler = SIG_DFL; - sigaction(SSP_SIGTYPE, &sa, NULL); -} - -static void __cold ssp_write(int fd, const char *msg1, const char *msg2, const char *msg3) -{ - write(fd, msg1, strlen(msg1)); - write(fd, msg2, strlen(msg2)); - write(fd, msg3, strlen(msg3)); - write(fd, "()\n", 3); -#if defined __UCLIBC_HAS_SYSLOG__ - openlog("ssp", LOG_CONS | LOG_PID, LOG_USER); - syslog(LOG_INFO, "%s%s%s()", msg1, msg2, msg3); - closelog(); + if (sigaction(SSP_SIGTYPE, &sa, NULL) == 0) + (void)kill(pid, SSP_SIGTYPE); #endif -} - -static attribute_noreturn void terminate(void) -{ - (void) kill(getpid(), SSP_SIGTYPE); - _exit(127); + (void)kill(pid, SIGKILL); + /* The loop is added only to keep gcc happy. */ + while(1) + _exit(127); } #ifdef __UCLIBC_HAS_SSP_COMPAT__ -void __stack_smash_handler(char func[], int damaged __attribute__ ((unused))) attribute_noreturn __cold; -void __stack_smash_handler(char func[], int damaged) +void __stack_smash_handler(char func[], int damaged) attribute_noreturn __cold; +void __stack_smash_handler(char func[], int damaged attribute_unused) { - static const char message[] = ": stack smashing attack in function "; - - block_signals(); - - ssp_write(STDERR_FILENO, __uclibc_progname, message, func); - - /* The loop is added only to keep gcc happy. */ - while(1) - terminate(); + ssp_handler(func); } -#endif -#ifdef __UCLIBC_HAS_SSP__ void __stack_chk_fail(void) { - static const char msg1[] = "stack smashing detected: "; - static const char msg3[] = " terminated"; - - block_signals(); - - ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3); - - /* The loop is added only to keep gcc happy. */ - while(1) - terminate(); + ssp_handler(NULL); } +#else +strong_alias(ssp_handler,__stack_chk_fail) #endif #ifdef __UCLIBC_HAS_FORTIFY__ +/* should be redone when activated to use common code above. + * for now, it works without debugging support */ void __chk_fail(void) { - static const char msg1[] = "buffer overflow detected: "; - static const char msg3[] = " terminated"; - - block_signals(); + static const char msg_fail[] = "*** buffer overflow detected ***: "; + static const char msg_terminated[] = " terminated"; + pid_t pid; - ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3); + do_msg(msg_fail, __uclibc_progname, msg_terminated); + pid = getpid(); + (void)kill(pid, SIGKILL); /* The loop is added only to keep gcc happy. */ while(1) - terminate(); + _exit(127); } libc_hidden_def(__chk_fail) #endif |