Browse Source

misc cleanups of __stack_smash_handler() function when ssp support is enabled. syslog() support should now work both inside and outside of chroots. erandom code left in but remains #ifdef out by default. May remove erandom completely in the future for uClibc unless the LFS guys and gals want to keep it.

Ned Ludd 20 years ago
parent
commit
1aea77e162
1 changed files with 100 additions and 76 deletions
  1. 100 76
      libc/sysdeps/linux/common/ssp.c

+ 100 - 76
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);
+}