From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1GjgZD-0004N5-Al for mharc-grub-devel@gnu.org; Mon, 13 Nov 2006 13:29:59 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1GjgZB-0004Kv-RK for grub-devel@gnu.org; Mon, 13 Nov 2006 13:29:57 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1GjgZA-0004Ic-T4 for grub-devel@gnu.org; Mon, 13 Nov 2006 13:29:57 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GjgZ8-0004FY-Fu; Mon, 13 Nov 2006 13:29:54 -0500 Received: from [199.232.76.164] (helo=fencepost.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.52) id 1GjgZ8-0004LJ-EM; Mon, 13 Nov 2006 13:29:54 -0500 Received: from tschwinge by fencepost.gnu.org with local (Exim 4.34) id 1GjgZ7-0005Ka-Ro; Mon, 13 Nov 2006 13:29:53 -0500 Date: Mon, 13 Nov 2006 19:29:53 +0100 From: Thomas Schwinge To: bug-hurd@gnu.org, grub-devel@gnu.org Message-ID: <20061113182953.GC6859@fencepost> References: <20061108214054.GU32338@fencepost> <20061108221419.GA19550@bouh.residence.ens-lyon.fr> <20061108223620.GV32338@fencepost> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="+nBD6E3TurpgldQp" Content-Disposition: inline In-Reply-To: <20061108223620.GV32338@fencepost> X-Homepage: http://nic-nac-project.de/~schwinge/ User-Agent: Mutt/1.5.6+20040907i Cc: Subject: Re: Stack protection via GCC's `-fstack-protector' X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Nov 2006 18:29:58 -0000 --+nBD6E3TurpgldQp Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hello! On Wed, Nov 08, 2006 at 11:36:20PM +0100, I wrote: > On Wed, Nov 08, 2006 at 11:14:19PM +0100, Samuel Thibault wrote: > > Thomas Schwinge, le Wed 08 Nov 2006 22:40:54 +0100, a ?crit : > > > Is it feasible to have the `-fstack-protector' functionality in GNU M= ach > > > and GRUB2 (and how to do that, then) or shall we unconditionally pass > > > `-fno-stack-protector' if available? > >=20 > > I'd say it shouldn't be very hard to provide a stack_chk_fail function, > > even if all it does is just panic(). >=20 > Having had a look at glibc's implementation and its complexity ;-) that > might indeed be a reachable goal (assuming that no other surprises show > up): There were other surprises (namely a GCC bug), but see below: what follows there is a proposal for GNU Mach, the one for GNU GRUB2 would look somewhat similar. To be discussed is the initialization of `__stack_chk_guard'. As I understand it, this is --- in user space programs and the OpenBSD kernel --- done by using some (pseudo)random values or --- if that's not possible in user space or in the DragonflyBSD kernel --- by using some special characters (`nul', `\n', `0x255'), like e.g.: dragonflybsd/src/sys/libkern/stack_protector.c #v+ [...] #if BYTE_ORDER =3D=3D LITTLE_ENDIAN int __guard =3D 0x00000aff; #else int __guard =3D 0xff0a0000; #endif [...] #v- Other examples: openbsd/src/sys/kern/init_main.c #v+ [...] long __guard[8]; [...] { volatile long newguard[8]; int i; arc4random_bytes((long *)newguard, sizeof(newguard)); for (i =3D sizeof(__guard)/sizeof(__guard[0]) - 1; i; i--) __guard[i] =3D newguard[i]; } [...] #v- user space gcc/libssp/ssp.c (the same is basically done in glibc's sysdeps/unix/sysv/linux/dl-osinfo.h, sysdeps/generic/dl-osinfo.h) #v+ [...] void *__stack_chk_guard =3D 0; [...] static void __attribute__ ((constructor)) __guard_setup (void) { unsigned char *p; int fd; if (__stack_chk_guard !=3D 0) return; fd =3D open ("/dev/urandom", O_RDONLY); if (fd !=3D -1) { ssize_t size =3D read (fd, &__stack_chk_guard, sizeof (__stack_chk_guard)); close (fd); if (size =3D=3D sizeof(__stack_chk_guard) && __stack_chk_guard !=3D 0) return; } /* If a random generator can't be used, the protector switches the guard to the "terminator canary". */ p =3D (unsigned char *) &__stack_chk_guard; p[sizeof(__stack_chk_guard)-1] =3D 255; p[sizeof(__stack_chk_guard)-2] =3D '\n'; p[0] =3D 0; } [...] #v- What do we want in GNU Mach? The patch follows: Index: configure.ac =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/hurd/gnumach/Attic/configure.ac,v retrieving revision 1.1.2.6 diff -u -p -r1.1.2.6 configure.ac --- configure.ac 5 Nov 2006 20:50:25 -0000 1.1.2.6 +++ configure.ac 13 Nov 2006 17:54:53 -0000 @@ -83,6 +83,67 @@ dnl See below why we need to patch stuff AC_CHECK_PROG([PATCH], [patch], [patch], [patch-not-found]) =0C # +# Compiler features. +# + +# Smashing stack protector. + +AC_ARG_ENABLE([smashing-stack-protector], + AS_HELP_STRING([--disable-smashing-stack-protector], + [disable the smashing stack protector])) +[# Default to using it, if possible. +enable_smashing_stack_protector=3D${enable_smashing_stack_protector-auto} +ssp_possible=3Dno +# There was a bug in certain versions of GCC that made it emit incorrect c= ode +# when used in a non-glibc environment. +ssp_usable=3Dno +if [ x"$enable_smashing_stack_protector" !=3D xno ]; then] + AC_MSG_CHECKING([whether the compiler accepts `-fstack-protector' and th= e \ +resulting code is suitable in a kernel environment]) + AC_LANG_CONFTEST([[void foo (void) { volatile char a[8]; a[3]; }]]) + [# `$CC -c -o ...' might not be portable. But, oh, well... + # Is calling `ac_compile' like this correct, after all? + if eval "$ac_compile -S -fstack-protector -o conftest.s"; then + ssp_possible=3Dyes + if grep -q '%gs' conftest.s; then] + AC_MSG_RESULT([accepted, but not usable]) + [else] + AC_MSG_RESULT([yes]) + [ssp_usable=3Dyes + fi + # Should we clear up other files as well, having called `AC_LANG_CONFT= EST'? + rm -f conftest.s + else] + AC_MSG_RESULT([not accepted]) + [fi +fi +enable_smashing_stack_protector=3D\ +$enable_smashing_stack_protector-$ssp_possible-$ssp_usable +case $enable_smashing_stack_protector in + no-*) :;; + yes-no-*)] AC_MSG_ERROR([cannot use the smashing stack protector as it's= \ +not supported by the compiler.])[;; + yes-*-no)] AC_MSG_ERROR([cannot use the smashing stack protector as it's= \ +not properly supported by the compiler.])[;; + *-no-*)] AC_MSG_WARN([won't use the smashing stack protector as it's not= \ +supported by the compiler.])[;; + *-*-no)] AC_MSG_WARN([won't use the smashing stack protector as it's not= \ +properly supported by the compiler.])[;; + *-yes-yes) CFLAGS=3D$CFLAGS\ -fstack-protector + enable_smashing_stack_protector=3Dyes + # This definition isn't used anywhere, but it's useful for having + # all files recompiled if an already-built tree is reconfigured + # to switch from using the smashing stack protector to not using + # it and vice versa.] + AC_DEFINE([USING_SMASHING_STACK_PROTECTOR], [], + [Are we using the smashing stack protector?])[;; + *)] AC_MSG_ERROR([please report to <$PACKAGE_BUGREPORT> that `configure.= ac' \ +is buggy w.r.t. smashing stack protector detection.])[;; +esac] +AM_CONDITIONAL([enable_smashing_stack_protector], + [[[ x"$enable_smashing_stack_protector" =3D xyes ]]]) +=0C +# # configure fragments. # =20 Index: Makefrag.am =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/hurd/gnumach/Attic/Makefrag.am,v retrieving revision 1.1.2.6 diff -u -p -r1.1.2.6 Makefrag.am --- Makefrag.am 8 Nov 2006 18:55:24 -0000 1.1.2.6 +++ Makefrag.am 13 Nov 2006 17:54:53 -0000 @@ -111,6 +111,11 @@ libkernel_a_SOURCES +=3D \ util/putchar.c \ util/puts.c =20 +if enable_smashing_stack_protector +libkernel_a_SOURCES +=3D \ + util/stack_chk_fail.c +endif + # Virtual memory implementation. libkernel_a_SOURCES +=3D \ vm/vm_debug.c \ Index: util/stack_chk_fail.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: util/stack_chk_fail.c diff -N util/stack_chk_fail.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ util/stack_chk_fail.c 13 Nov 2006 17:54:53 -0000 @@ -0,0 +1,33 @@ +/* + * Support for the smashing stack protector. + * + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +unsigned int __stack_chk_guard =3D 12345; + +void +__attribute__ ((noreturn)) +__stack_chk_fail (void) +{ + panic ("*** stack smashing detected ***\n" + "TODO: Explain.\n" + "TODO: Please do whatever and report to <" PACKAGE_BUGREPORT + "> or don't."); +} Index: doc/mach.texi =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/hurd/gnumach/doc/mach.texi,v retrieving revision 1.4.2.5 diff -u -p -r1.4.2.5 mach.texi --- doc/mach.texi 23 Sep 2006 20:25:40 -0000 1.4.2.5 +++ doc/mach.texi 13 Nov 2006 17:54:56 -0000 @@ -547,6 +547,11 @@ Sets the prefix to PREFIX. The default=20 is the correct value for the GNU system. The prefix is prepended to all file names at installation time. =20 +@item --disable-smashing-stack-protector +Specifying this, the smashing stack protector is disabled. By +default it is enabled if the compiler has proper support for it. +TODO: Explain what this does. + @item --enable-kdb Enables the in-kernel debugger. This is only useful if you actually anticipate debugging the kernel. It is not enabled by default because What follows now is the snippet I used for testing this... Index: i386/i386at/i386at_ds_routines.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/hurd/gnumach/i386/i386at/Attic/i386at_ds_routines.c,v retrieving revision 1.4.2.5 diff -u -p -r1.4.2.5 i386at_ds_routines.c --- i386/i386at/i386at_ds_routines.c 11 Nov 2006 00:54:05 -0000 1.4.2.5 +++ i386/i386at/i386at_ds_routines.c 13 Nov 2006 17:54:56 -0000 @@ -74,6 +74,16 @@ ds_device_open (ipc_port_t open_port, ip int i; io_return_t err; =20 + void crash_kernel_now (void) + { + volatile char a[8]; + printf ("Preparing to crash the kernel...\n"); + a[8] =3D 42; + } + + if (name && name[0] =3D=3D 'c' && name[1] =3D=3D 0) + crash_kernel_now (); + /* Open must be called on the master device port. */ if (open_port !=3D master_device_port) return D_INVALID_OPERATION; =2E.. that one and then a doughty ``sudo devprobe c'' and I found myself in the kernel debugger and a ``*** stack smashing detected ***[...]'' message on the screen, as expected. Regards, Thomas --+nBD6E3TurpgldQp Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) iD8DBQFFWLmhgfzh735dTTURAgW8AJ9LVIXX3T2JSb4wxbqf5Zt0R7fUYQCdG1Ot qiMwmX2rKQc2CaVHXx7CzLY= =rgxM -----END PGP SIGNATURE----- --+nBD6E3TurpgldQp--