From 15a856b1090669df0aec536edbdf240e71a470ca Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 15 May 2011 10:59:07 -0400 Subject: Make stack canary value harder to read through read overflow --- sysdeps/generic/dl-osinfo.h | 30 +++++++++++++++++++-------- sysdeps/unix/sysv/linux/dl-osinfo.h | 41 +++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 22 deletions(-) (limited to 'sysdeps') diff --git a/sysdeps/generic/dl-osinfo.h b/sysdeps/generic/dl-osinfo.h index 4b880dae34..3af064cf54 100644 --- a/sysdeps/generic/dl-osinfo.h +++ b/sysdeps/generic/dl-osinfo.h @@ -1,5 +1,5 @@ /* Operating system specific code for generic dynamic loader functions. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,23 +17,35 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include static inline uintptr_t __attribute__ ((always_inline)) _dl_setup_stack_chk_guard (void *dl_random) { - uintptr_t ret; + union + { + uintptr_t num; + unsigned char bytes[sizeof (uintptr_t)]; + } ret = { 0 }; + if (dl_random == NULL) { - ret = 0; - unsigned char *p = (unsigned char *) &ret; - p[sizeof (ret) - 1] = 255; - p[sizeof (ret) - 2] = '\n'; - p[0] = 0; + ret.bytes[sizeof (ret) - 2] = 255; + ret.bytes[sizeof (ret) - 3] = '\n'; } else - memcpy (&ret, dl_random, sizeof (ret)); - return ret; + { + memcpy (ret.bytes, dl_random, sizeof (ret)); +#if BYTE_ORDER == LITTLE_ENDIAN + ret.num &= ~0xff; +#elif BYTE_ORDER == BIG_ENDIAN + ret.num &= ~(0xff << (8 * (sizeof (ret) - 1))); +#else +# error "BYTE_ORDER unknown" +#endif + } + return ret.num; } static inline uintptr_t __attribute__ ((always_inline)) diff --git a/sysdeps/unix/sysv/linux/dl-osinfo.h b/sysdeps/unix/sysv/linux/dl-osinfo.h index ffe5d586b5..eb7fedc077 100644 --- a/sysdeps/unix/sysv/linux/dl-osinfo.h +++ b/sysdeps/unix/sysv/linux/dl-osinfo.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -63,32 +64,46 @@ dl_fatal (const char *str) static inline uintptr_t __attribute__ ((always_inline)) _dl_setup_stack_chk_guard (void *dl_random) { - uintptr_t ret; + union + { + uintptr_t num; + unsigned char bytes[sizeof (uintptr_t)]; + } ret; + #ifndef __ASSUME_AT_RANDOM if (__builtin_expect (dl_random == NULL, 0)) { + const size_t filllen = sizeof (ret.bytes) - 1; + ret.num = 0; # ifdef ENABLE_STACKGUARD_RANDOMIZE int fd = open_not_cancel_2 ("/dev/urandom", O_RDONLY); if (fd >= 0) { - ssize_t reslen = read_not_cancel (fd, &ret, sizeof (ret)); + ssize_t reslen = read_not_cancel (fd, ret.bytes + 1, filllen); close_not_cancel_no_status (fd); - if (reslen == (ssize_t) sizeof (ret)) - return ret; + if (reslen == (ssize_) filllen) + return ret.num; } # endif - ret = 0; - unsigned char *p = (unsigned char *) &ret; - p[sizeof (ret) - 1] = 255; - p[sizeof (ret) - 2] = '\n'; + ret.bytes[filllen - 2] = 255; + ret.bytes[filllen - 3] = '\n'; } else #endif - /* We need in the moment only 8 bytes on 32-bit platforms and 16 - bytes on 64-bit platforms. Therefore we can use the data - directly and not use the kernel-provided data to seed a PRNG. */ - memcpy (&ret, dl_random, sizeof (ret)); - return ret; + { + /* We need in the moment only 8 bytes on 32-bit platforms and 16 + bytes on 64-bit platforms. Therefore we can use the data + directly and not use the kernel-provided data to seed a PRNG. */ + memcpy (ret.bytes, dl_random, sizeof (ret)); +#if BYTE_ORDER == LITTLE_ENDIAN + ret.num &= ~0xff; +#elif BYTE_ORDER == BIG_ENDIAN + ret.num &= ~(0xff << (8 * (sizeof (ret) - 1))); +#else +# error "BYTE_ORDER unknown" +#endif + } + return ret.num; } static inline uintptr_t __attribute__ ((always_inline)) -- cgit 1.4.1