Re: Stack protection via GCC's `-fstack-protector'

2007-02-03 Thread Thomas Schwinge
Hello!

On Fri, Dec 15, 2006 at 08:36:09PM +0100, I wrote:
> I created the following patch to be able to continue building GRUB2 on
> systems that have `-fstack-protector' enabled by default.  (This patch is
> equal to what we've been using in GNU Mach for some time now.)
> 
> 
> 2006-12-15  Thomas Schwinge  <[EMAIL PROTECTED]>
> 
>   * aclocal.m4 (grub_CHECK_STACK_PROTECTOR): New definition.
>   * configure.ac: Use it for testing the HOST and TARGET compilers.

At Marco's disposition I just checked this in.


Regards,
 Thomas


signature.asc
Description: Digital signature
___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel


Re: Stack protection via GCC's `-fstack-protector'

2006-12-15 Thread Thomas Schwinge
Hello!

On Wed, Nov 08, 2006 at 10:40:54PM +0100, I wrote:
> For some time, GCC now offers the following feature:
> 
> info Gcc
> #v+
> `-fstack-protector'
>  Emit extra code to check for buffer overflows, such as stack
>  smashing attacks.  This is done by adding a guard variable to
>  functions with vulnerable objects.  This includes functions that
>  call alloca, and functions with buffers larger than 8 bytes.  The
>  guards are initialized when a function is entered and then checked
>  when the function exits.  If a guard check fails, an error message
>  is printed and the program exits.
> #v-
> 
> I now happen to be running a GCC 4.1 installation which has that one
> enabled by default.  Unfortunately, building GNU Mach and GRUB2 (didn't
> check GRUB legacy) is affected by that:

To completely support this feature in kernel-like environments, work on
GCC itself is needed, see
, so for the mean time
I created the following patch to be able to continue building GRUB2 on
systems that have `-fstack-protector' enabled by default.  (This patch is
equal to what we've been using in GNU Mach for some time now.)


2006-12-15  Thomas Schwinge  <[EMAIL PROTECTED]>

* aclocal.m4 (grub_CHECK_STACK_PROTECTOR): New definition.
* configure.ac: Use it for testing the HOST and TARGET compilers.

Index: aclocal.m4
===
RCS file: /cvsroot/grub/grub2/aclocal.m4,v
retrieving revision 1.5
diff -u -p -r1.5 aclocal.m4
--- aclocal.m4  13 Aug 2005 18:44:14 -  1.5
+++ aclocal.m4  15 Dec 2006 19:18:18 -
@@ -343,3 +343,23 @@ dnl So use regparm 2 until a better test
[Catch gcc bug])
 fi
 ])
+
+dnl Check if the C compiler supports `-fstack-protector'.
+dnl Written by Thomas Schwinge.
+AC_DEFUN(grub_CHECK_STACK_PROTECTOR,[
+[# Smashing stack protector.
+ssp_possible=yes]
+AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector'])
+# Is this a reliable test case?
+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" 2> /dev/null; then]
+  AC_MSG_RESULT([yes])
+  [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
+  rm -f conftest.s
+else
+  ssp_possible=no]
+  AC_MSG_RESULT([no])
+[fi]
+])
Index: configure.ac
===
RCS file: /cvsroot/grub/grub2/configure.ac,v
retrieving revision 1.35
diff -u -p -r1.35 configure.ac
--- configure.ac13 Dec 2006 22:30:19 -  1.35
+++ configure.ac15 Dec 2006 19:18:18 -
@@ -149,6 +149,19 @@ fi
 AC_CHECK_FUNCS(posix_memalign memalign)
 
 #
+# Compiler features.
+#
+
+# Smashing stack protector.
+grub_CHECK_STACK_PROTECTOR
+[# Need that, because some distributions ship compilers that include
+# `-fstack-protector' in the default specs.
+if [ x"$ssp_possible" = xyes ]; then
+  CFLAGS=$CFLAGS\ -fno-stack-protector
+fi]
+
+
+#
 # Check for target programs.
 #
 
@@ -225,6 +238,18 @@ if test "x$target_m32" = x1; then
   TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
 fi
 
+#
+# Compiler features.
+#
+
+# Smashing stack protector.
+grub_CHECK_STACK_PROTECTOR
+[# Need that, because some distributions ship compilers that include
+# `-fstack-protector' in the default specs.
+if [ x"$ssp_possible" = xyes ]; then
+  TARGET_CFLAGS=$TARGET_CFLAGS\ -fno-stack-protector
+fi]
+
 AC_SUBST(TARGET_CFLAGS)
 AC_SUBST(TARGET_CPPFLAGS)
 AC_SUBST(TARGET_LDFLAGS)


Regards,
 Thomas


signature.asc
Description: Digital signature
___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel


Re: Stack protection via GCC's `-fstack-protector'

2006-11-13 Thread Samuel Thibault
Hi,

Thomas Schwinge, le Mon 13 Nov 2006 19:29:53 +0100, a écrit :
> +unsigned int __stack_chk_guard = 12345;

I'd say this should be something like a value with higher bits set, so
that it wouldn't be a valid pointer, even for reading.

Samuel


___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel


Re: Stack protection via GCC's `-fstack-protector'

2006-11-13 Thread Thomas Schwinge
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 Mach
> > > and GRUB2 (and how to do that, then) or shall we unconditionally pass
> > > `-fno-stack-protector' if available?
> > 
> > I'd say it shouldn't be very hard to provide a stack_chk_fail function,
> > even if all it does is just panic().
> 
> 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 == LITTLE_ENDIAN
int __guard = 0x0aff;
#else
int __guard = 0xff0a;
#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 = sizeof(__guard)/sizeof(__guard[0]) - 1; i; i--)
__guard[i] = 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 = 0;
[...]
static void __attribute__ ((constructor))
__guard_setup (void)
{
  unsigned char *p;
  int fd;

  if (__stack_chk_guard != 0)
return;

  fd = open ("/dev/urandom", O_RDONLY);
  if (fd != -1)
{
  ssize_t size = read (fd, &__stack_chk_guard,
   sizeof (__stack_chk_guard));
  close (fd);
  if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0)
return;
}

  /* If a random generator can't be used, the protector switches the guard
 to the "terminator canary".  */
  p = (unsigned char *) &__stack_chk_guard;
  p[sizeof(__stack_chk_guard)-1] = 255;
  p[sizeof(__stack_chk_guard)-2] = '\n';
  p[0] = 0;
}
[...]
#v-

What do we want in GNU Mach?


The patch follows:

Index: configure.ac
===
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.ac5 Nov 2006 20:50:25 -   1.1.2.6
+++ configure.ac13 Nov 2006 17:54:53 -
@@ -83,6 +83,67 @@ dnl See below why we need to patch stuff
 AC_CHECK_PROG([PATCH], [patch], [patch], [patch-not-found])
 
 #
+# 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=${enable_smashing_stack_protector-auto}
+ssp_possible=no
+# There was a bug in certain versions of GCC that made it emit incorrect code
+# when used in a non-glibc environment.
+ssp_usable=no
+if [ x"$enable_smashing_stack_protector" != xno ]; then]
+  AC_MSG_CHECKING([whether the compiler accepts `-fstack-protector' and the \
+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=yes
+if grep -q '%gs' conftest.s; then]
+  AC_MSG_RESULT([accepted, but not usable])
+[else]
+  AC_MSG_RESULT([yes])
+  [ssp_usable=yes
+fi
+# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
+rm -f conftest.s
+  else]
+AC_MSG_RESULT([not accepted])
+  [fi
+fi
+enable_smashing_stack_protector=\
+$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=$CFLAGS\ -fstack-protector
+ 

Re: Stack protection via GCC's `-fstack-protector'

2006-11-08 Thread Samuel Thibault
Hi,

Stefan Reinauer, le Wed 08 Nov 2006 23:36:44 +0100, a écrit :
> * Samuel Thibault <[EMAIL PROTECTED]> [061108 23:14]:
> > Thomas Schwinge, le Wed 08 Nov 2006 22:40:54 +0100, a écrit :
> > > then cat gnumach-undef-bad; exit 2; else true; fi
> > > stack_chk_fail
> > > 
> > > Is it feasible to have the `-fstack-protector' functionality in GNU Mach
> > > and GRUB2 (and how to do that, then) or shall we unconditionally pass
> > > `-fno-stack-protector' if available?
> > 
> > I'd say it shouldn't be very hard to provide a stack_chk_fail function,
> > even if all it does is just panic().
>  
> wont this add unnecessary bloat to the binary?

Just like to any binary of a distribution that would enable
-fstack-protector by default. That's not our concern, that's the
distribution's.

Samuel


___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel


Re: Stack protection via GCC's `-fstack-protector'

2006-11-08 Thread Stefan Reinauer
Hi,

* Samuel Thibault <[EMAIL PROTECTED]> [061108 23:14]:
> Thomas Schwinge, le Wed 08 Nov 2006 22:40:54 +0100, a écrit :
> > then cat gnumach-undef-bad; exit 2; else true; fi
> > stack_chk_fail
> > 
> > Is it feasible to have the `-fstack-protector' functionality in GNU Mach
> > and GRUB2 (and how to do that, then) or shall we unconditionally pass
> > `-fno-stack-protector' if available?
> 
> I'd say it shouldn't be very hard to provide a stack_chk_fail function,
> even if all it does is just panic().
 
wont this add unnecessary bloat to the binary? No, not the function
calling panic. Or are we seriously concerned about buffer overflows 
in the bootloader?

S.

-- 
coresystems GmbH • Brahmsstr. 16 • D-79104 Freiburg i. Br.
  Tel.: +49 761 7668825 • Fax: +49 761 7664613
Email: [EMAIL PROTECTED]  • http://www.coresystems.de/


___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel


Re: Stack protection via GCC's `-fstack-protector'

2006-11-08 Thread Thomas Schwinge
Hello!

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 Mach
> > and GRUB2 (and how to do that, then) or shall we unconditionally pass
> > `-fno-stack-protector' if available?
> 
> I'd say it shouldn't be very hard to provide a stack_chk_fail function,
> even if all it does is just panic().

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):

debug/stack_chk_fail.c
#v+
[Copyright header.]

#include 
#include 


extern char **__libc_argv attribute_hidden;

void
__attribute__ ((noreturn))
__stack_chk_fail (void)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
__libc_message (1, "*** stack smashing detected ***: %s terminated\n",
__libc_argv[0] ?: "");
}
#v-


I'll give it a try.


Regards,
 Thomas


signature.asc
Description: Digital signature
___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel


Re: Stack protection via GCC's `-fstack-protector'

2006-11-08 Thread Samuel Thibault
Hi,

Thomas Schwinge, le Wed 08 Nov 2006 22:40:54 +0100, a écrit :
> then cat gnumach-undef-bad; exit 2; else true; fi
> stack_chk_fail
> 
> Is it feasible to have the `-fstack-protector' functionality in GNU Mach
> and GRUB2 (and how to do that, then) or shall we unconditionally pass
> `-fno-stack-protector' if available?

I'd say it shouldn't be very hard to provide a stack_chk_fail function,
even if all it does is just panic().

Samuel


___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel


Stack protection via GCC's `-fstack-protector'

2006-11-08 Thread Thomas Schwinge
[Please keep both  and  in the
recipients list.]


Hello!

For some time, GCC now offers the following feature:

info Gcc
#v+
`-fstack-protector'
 Emit extra code to check for buffer overflows, such as stack
 smashing attacks.  This is done by adding a guard variable to
 functions with vulnerable objects.  This includes functions that
 call alloca, and functions with buffers larger than 8 bytes.  The
 guards are initialized when a function is entered and then checked
 when the function exits.  If a guard check fails, an error message
 is printed and the program exits.
#v-

I now happen to be running a GCC 4.1 installation which has that one
enabled by default.  Unfortunately, building GNU Mach and GRUB2 (didn't
check GRUB legacy) is affected by that:

GRUB2
#v+
[...]
gcc -o kernel.exec kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o 
kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o 
kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o 
kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o 
kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o 
kernel_img-kern_i386_pc_init.o kernel_img-kern_parser.o 
kernel_img-kern_partition.o kernel_img-kern_env.o 
kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o 
kernel_img-symlist.o  -nostdlib -Wl,-N,-Ttext,8200 -fno-builtin -mrtd 
-mregparm=3 -m32
kernel_img-kern_device.o: In function `grub_device_iterate':
../kern/device.c:142: undefined reference to `__stack_chk_fail'
kernel_img-kern_disk.o: In function `grub_disk_write':
../kern/disk.c:553: undefined reference to `__stack_chk_fail'
kernel_img-kern_misc.o: In function `grub_vsprintf':
../kern/misc.c:897: undefined reference to `__stack_chk_fail'
kernel_img-kern_rescue.o: In function `grub_rescue_cmd_cat':
../kern/rescue.c:169: undefined reference to `__stack_chk_fail'
kernel_img-kern_i386_pc_init.o: In function `grub_machine_set_prefix':
../kern/i386/pc/init.c:239: undefined reference to `__stack_chk_fail'
kernel_img-kern_parser.o:../kern/parser.c:230: more undefined references to 
`__stack_chk_fail' follow
collect2: ld returned 1 exit status
make: *** [kernel.exec] Error 1
#v-

GNU Mach
#v+
[...]
ld -u _start -r -o gnumach.o --start-group  libkernel.a liblinux.a 
liblinux_pcmcia_cs_modules.a liblinux_pcmcia_cs_clients.a 
liblinux_pcmcia_cs_wireless.a 
nm -u gnumach.o | sed 's/  *U  *//;s/^_*//' | sort -u > gnumach-undef
sed '/^memcpy$/d; /^memmove$/d; /^memset$/d; /^bcopy$/d; /^bzero$/d; 
/^strchr$/d; /^strstr$/d; /^strsep$/d; /^strpbrk$/d; /^strtok$/d; /^htonl$/d; 
/^htons$/d; /^ntohl$/d; /^ntohs$/d; /^etext$/d; /^edata$/d; /^end$/d;' 
gnumach-undef > gnumach-undef-bad
if test -s gnumach-undef-bad; \
then cat gnumach-undef-bad; exit 2; else true; fi
stack_chk_fail
make[2]: *** [clib-routines.o] Error 2
make[2]: Leaving directory 
`/fs/data/mount/home/thomas/tmp/source/gnumach/gnumach-1-branch/build'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory 
`/fs/data/mount/home/thomas/tmp/source/gnumach/gnumach-1-branch/build'
make: *** [all] Error 2
#v-


Is it feasible to have the `-fstack-protector' functionality in GNU Mach
and GRUB2 (and how to do that, then) or shall we unconditionally pass
`-fno-stack-protector' if available?


Regards,
 Thomas


signature.asc
Description: Digital signature
___
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel