diff options
| -rw-r--r-- | libc/sysdeps/linux/common/ssp.c | 176 | 
1 files changed, 100 insertions, 76 deletions
diff --git a/libc/sysdeps/linux/common/ssp.c b/libc/sysdeps/linux/common/ssp.c index c7a863d53..5ce4d831e 100644 --- a/libc/sysdeps/linux/common/ssp.c +++ b/libc/sysdeps/linux/common/ssp.c @@ -1,97 +1,121 @@ +/* + * Distributed under the terms of the GNU General Public License v2 + * $Header: /var/cvs/uClibc/libc/sysdeps/linux/common/ssp.c,v 1.3 2004/11/11 03:12:37 solar Exp $ + * + * This is a modified version of Hiroaki Etoh's stack smashing routines + * implemented for glibc. + * + * The following people have contributed input to this code. + * Ned Ludd - <solar[@]gentoo.org> + * Alexander Gabert - <pappy[@]gentoo.org> + * The PaX Team - <pageexec[@]freemail.hu> + * Peter S. Mazinger - <ps.m[@]gmx.net> + * Yoann Vandoorselaere - <yoann[@]prelude-ids.org> + * Robert Connolly - <robert[@]linuxfromscratch.org> + * Cory Visi <cory@visi.name> + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +  #include <stdio.h>  #include <string.h>  #include <fcntl.h>  #include <unistd.h> - -#ifdef _POSIX_SOURCE  #include <signal.h> -#endif - -#if defined(HAVE_SYSLOG)  #include <sys/types.h> -#include <sys/socket.h>  #include <sys/un.h> -  #include <sys/syslog.h> -#ifndef _PATH_LOG -#define _PATH_LOG "/dev/log" -#endif +#include <sys/time.h> +#include <sys/sysctl.h> + +#ifdef __PROPOLICE_BLOCK_SEGV__ +#define SSP_SIGTYPE SIGSEGV +#elif __PROPOLICE_BLOCK_KILL__ +#define SSP_SIGTYPE SIGKILL +#else +#define SSP_SIGTYPE SIGABRT  #endif -long __guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +unsigned long __guard = 0UL; -void __guard_setup (void) +void __guard_setup(void)  { -  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; -} +	size_t size; +	struct timeval tv; -void __stack_smash_handler (char func[], int damaged) -{ -#if defined (__GNU_LIBRARY__) -  extern char * __progname; -#endif -  const char message[] = ": stack smashing attack in function "; -  int bufsz = 512, len; -  char buf[bufsz]; -#if defined(HAVE_SYSLOG) -  int LogFile; -  struct sockaddr_un SyslogAddr;  /* AF_UNIX address of local logger */ +#ifdef HAVE_DEV_ERANDOM +	int mib[3];  #endif -#ifdef _POSIX_SOURCE -  { -    sigset_t mask; -    sigfillset(&mask); -    sigdelset(&mask, SIGABRT);  /* Block all signal handlers */ -    sigprocmask(SIG_BLOCK, &mask, NULL); /* except SIGABRT */ -  } + +	if (__guard != 0UL) +		return; + +#ifndef __SSP_QUICK_CANARY__ +#ifdef HAVE_DEV_ERANDOM +	/* Random is another depth in Linux, hence an array of 3. */ +	mib[0] = CTL_KERN; +	mib[1] = KERN_RANDOM; +	mib[2] = RANDOM_ERANDOM; + +	size = sizeof(unsigned long); +	if (__sysctl(mib, 3, &__guard, &size, NULL, 0) != (-1)) +		if (__guard != 0UL) +			return;  #endif +	/*  +	 * Attempt to open kernel pseudo random device if one exists before  +	 * opening urandom to avoid system entropy depletion. +	 */ +	{ +		int fd; -  strcpy(buf, "<2>"); len=3;    /* send LOG_CRIT */ -#if defined (__GNU_LIBRARY__) -  strncat(buf, __progname, bufsz-len-1); len = strlen(buf); +#ifdef HAVE_DEV_ERANDOM +		if ((fd = open("/dev/erandom", O_RDONLY)) == (-1))  #endif -  if (bufsz>len) {strncat(buf, message, bufsz-len-1); len = strlen(buf);} -  if (bufsz>len) {strncat(buf, func, bufsz-len-1); len = strlen(buf);} -  /* print error message */ -  write (STDERR_FILENO, buf+3, len-3); -#if defined(HAVE_SYSLOG) -  if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) != -1) { - -    /* -     * Send "found" message to the "/dev/log" path -     */ -    SyslogAddr.sun_family = AF_UNIX; -    (void)strncpy(SyslogAddr.sun_path, _PATH_LOG, -          sizeof(SyslogAddr.sun_path) - 1); -    SyslogAddr.sun_path[sizeof(SyslogAddr.sun_path) - 1] = '\0'; -    sendto(LogFile, buf, len, 0, (struct sockaddr *)&SyslogAddr, -       sizeof(SyslogAddr)); -  } +			fd = open("/dev/urandom", O_RDONLY); +		if (fd != (-1)) { +			size = read(fd, (char *) &__guard, sizeof(__guard)); +			close(fd); +			if (size == sizeof(__guard)) +				return; +		} +	}  #endif +	/* If sysctl was unsuccessful, use the "terminator canary". */ +	__guard = 0xFF0A0D00UL; -#ifdef _POSIX_SOURCE -  { /* Make sure the default handler is associated with SIGABRT */ -    struct sigaction sa; - -    memset(&sa, 0, sizeof(struct sigaction)); -    sigfillset(&sa.sa_mask);    /* Block all signals */ -    sa.sa_flags = 0; -    sa.sa_handler = SIG_DFL; -    sigaction(SIGABRT, &sa, NULL); -    (void)kill(getpid(), SIGABRT); -  } -#endif -  _exit(127); +	/* Everything failed? Or we are using a weakened model of the  +	 * terminator canary */ + +	gettimeofday(&tv, NULL); +	__guard ^= tv.tv_usec ^ tv.tv_sec;  } +void __stack_smash_handler(char func[], int damaged) +{ +	extern char *__progname; +	const char message[] = ": stack smashing attack in function "; +	struct sigaction sa; +	sigset_t mask; + +	sigfillset(&mask); + +	sigdelset(&mask, SSP_SIGTYPE);	/* Block all signal handlers */ +	sigprocmask(SIG_BLOCK, &mask, NULL);	/* except SIGABRT */ + +	/* print error message to stderr and syslog */ +	fprintf(stderr, "%s%s%s()\n", __progname, message, func); +	syslog(KERN_INFO, "%s%s%s()", __progname, message, func); + +	/* Make sure the default handler is associated with the our signal handler */ +	memset(&sa, 0, sizeof(struct sigaction)); +	sigfillset(&sa.sa_mask);	/* Block all signals */ +	sa.sa_flags = 0; +	sa.sa_handler = SIG_DFL; +	sigaction(SSP_SIGTYPE, &sa, NULL); +	(void) kill(getpid(), SSP_SIGTYPE); +	_exit(127); +}  | 
