Submitted By: Robert Connolly (ashes) Date: 2005-04-24 Initial Package Version: 2.3.4 Upstream Status: Not submitted Origin: http://www.research.ibm.com/trl/projects/security/ssp/ http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/sys/stack_protector.c http://uclibc.org/cgi-bin/viewcvs.cgi/trunk/uClibc/libc/sysdeps/linux/common/ssp.c Description: Stack Smashing Protector - This patch adds SSP functions to Glibc. This patch depends on the Glibc arc4random patch. Also see: http://www.linuxfromscratch.org/hlfs/ http://www.linuxfromscratch.org/hints/downloads/files/ssp.txt diff -Naur glibc-2.3.4.orig/sysdeps/generic/libc-start.c glibc-2.3.4/sysdeps/generic/libc-start.c --- glibc-2.3.4.orig/sysdeps/generic/libc-start.c 2004-03-31 01:46:43.000000000 +0000 +++ glibc-2.3.4/sysdeps/generic/libc-start.c 2005-02-12 17:26:49.470416840 +0000 @@ -188,6 +188,9 @@ GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]); #endif + void __guard_setup(void) __attribute__ ((constructor)); + __guard_setup (); + #ifdef HAVE_CLEANUP_JMP_BUF /* Memory for the cancellation buffer. */ struct pthread_unwind_buf unwind_buf; diff -Naur glibc-2.3.4.orig/sysdeps/unix/sysv/linux/Dist glibc-2.3.4/sysdeps/unix/sysv/linux/Dist --- glibc-2.3.4.orig/sysdeps/unix/sysv/linux/Dist 2004-06-30 07:58:38.000000000 +0000 +++ glibc-2.3.4/sysdeps/unix/sysv/linux/Dist 2005-02-12 17:26:49.473416384 +0000 @@ -1,3 +1,4 @@ +stack_protector.c bits/initspin.h cmsg_nxthdr.c dl-brk.c diff -Naur glibc-2.3.4.orig/sysdeps/unix/sysv/linux/Makefile glibc-2.3.4/sysdeps/unix/sysv/linux/Makefile --- glibc-2.3.4.orig/sysdeps/unix/sysv/linux/Makefile 2004-10-04 23:29:06.000000000 +0000 +++ glibc-2.3.4/sysdeps/unix/sysv/linux/Makefile 2005-02-12 17:26:49.476415928 +0000 @@ -1,5 +1,5 @@ ifeq ($(subdir),csu) -sysdep_routines += errno-loc +sysdep_routines += errno-loc stack_protector endif ifeq ($(subdir),assert) diff -Naur glibc-2.3.4.orig/sysdeps/unix/sysv/linux/Versions glibc-2.3.4/sysdeps/unix/sysv/linux/Versions --- glibc-2.3.4.orig/sysdeps/unix/sysv/linux/Versions 2004-10-22 19:57:45.000000000 +0000 +++ glibc-2.3.4/sysdeps/unix/sysv/linux/Versions 2005-02-12 17:26:49.479415472 +0000 @@ -108,6 +108,7 @@ GLIBC_2.3.2 { # New kernel interfaces. epoll_create; epoll_ctl; epoll_wait; + __guard; __guard_setup; __stack_smash_handler; } GLIBC_2.3.3 { gnu_dev_major; gnu_dev_minor; gnu_dev_makedev; diff -Naur glibc-2.3.4.orig/sysdeps/unix/sysv/linux/stack_protector.c glibc-2.3.4/sysdeps/unix/sysv/linux/stack_protector.c --- glibc-2.3.4.orig/sysdeps/unix/sysv/linux/stack_protector.c 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.3.4/sysdeps/unix/sysv/linux/stack_protector.c 2005-02-12 18:00:25.757512648 +0000 @@ -0,0 +1,131 @@ +/* $hlfs: stack_protector.c,v 1.7 2005/04/24 robert Exp $ */ + +/* + * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* One of these things is not like the other... */ + +/* + * Distributed under the terms of the GNU General Public License v2 + * $Header: $ + * + * 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 - + * Alexander Gabert - + * The PaX Team - + * Peter S. Mazinger - + * Yoann Vandoorselaere - + * Robert Connolly - + * Cory Visi + * + */ + +#include +#include +#include /* For arc4random() */ +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __PROPOLICE_BLOCK_SEGV__ +#define SSP_SIGTYPE SIGSEGV +#elif __PROPOLICE_BLOCK_KILL__ +#define SSP_SIGTYPE SIGKILL +#else +#define SSP_SIGTYPE SIGABRT +#endif + +unsigned long __guard = 0UL; + +//void __guard_setup(void) __attribute__ ((constructor)); +void __guard_setup(void) +{ + int i=0, fd=0; + size_t size; + struct timeval tv; + + if (__guard != 0UL) + return; + + __guard = 0xFF0A0D00UL; + /* Always start with the time. */ + gettimeofday(&tv, NULL); + __guard ^= tv.tv_usec ^ tv.tv_sec; + +#if defined(HAVE_ARC4RANDOM) /* From */ + for (i = 0; i < sizeof(__guard) / 4; i ++) { + size = sizeof(unsigned long); + if ((__guard = (int)(arc4randomII())) == (-1)) + break; + } +#else + if (i < sizeof(__guard) / 4) { + fd = open("/dev/urandom", O_RDONLY); + if (fd != (-1)) { + size = read(fd, (char *) &__guard, sizeof(__guard)); + close(fd); + if (size == sizeof(__guard)) + return; + } + } +#endif +} + +//void __stack_smash_handler(char func[], int damaged __attribute__ ((unused))); +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(LOG_INFO, "%s%s%s()", __progname, message, func); + + /* Make the default handler is associated with the 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); +}