diff options
author | Ulrich Drepper <drepper@gmail.com> | 2011-05-15 10:59:07 -0400 |
---|---|---|
committer | Ulrich Drepper <drepper@gmail.com> | 2011-05-15 10:59:07 -0400 |
commit | 15a856b1090669df0aec536edbdf240e71a470ca (patch) | |
tree | 7c5919f3014dd5dfa37fbdfb4be12e1ae78ab921 | |
parent | 05f399e63428b5129ca54f9edefbf2876f82b75c (diff) | |
download | glibc-15a856b1090669df0aec536edbdf240e71a470ca.tar.gz glibc-15a856b1090669df0aec536edbdf240e71a470ca.tar.xz glibc-15a856b1090669df0aec536edbdf240e71a470ca.zip |
Make stack canary value harder to read through read overflow
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | sysdeps/generic/dl-osinfo.h | 30 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-osinfo.h | 41 |
4 files changed, 61 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog index ed1754db23..24606483a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2011-05-15 Ulrich Drepper <drepper@gmail.com> + [BZ #10149] + * sysdeps/unix/sysv/linux/dl-osinfo.h (_dl_setup_stack_chk_guard): + First byte (not low byte) is now always NUL. + * sysdeps/generic/dl-osinfo.h (_dl_setup_stack_chk_guard): Likewise. + * sysdeps/unix/sysv/linux/dl-osinfo.h (_dl_setup_stack_chk_guard): Use non-cancelable interfaces. diff --git a/NEWS b/NEWS index e12672a028..fff94be6d4 100644 --- a/NEWS +++ b/NEWS @@ -9,12 +9,13 @@ Version 2.14 * The following bugs are resolved with this release: - 386, 9809, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, 11901, - 11945, 11947, 11952, 12052, 12083, 12158, 12178, 12200, 12346, 12393, - 12420, 12432, 12445, 12449, 12453, 12454, 12460, 12469, 12489, 12509, - 12510, 12511, 12518, 12527, 12541, 12545, 12551, 12582, 12583, 12587, - 12597, 12601, 12611, 12625, 12626, 12631, 12650, 12653, 12655, 12660, - 12681, 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734, 12738 + 386, 9809, 10149, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, + 11901, 11945, 11947, 11952, 12052, 12083, 12158, 12178, 12200, 12346, + 12393, 12420, 12432, 12445, 12449, 12453, 12454, 12460, 12469, 12489, + 12509, 12510, 12511, 12518, 12527, 12541, 12545, 12551, 12582, 12583, + 12587, 12597, 12601, 12611, 12625, 12626, 12631, 12650, 12653, 12655, + 12660, 12681, 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734, + 12738 * The RPC implementation in libc is obsoleted. Old programs keep working but new programs cannot be linked with the routines in libc anymore. 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 <endian.h> #include <stdint.h> 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 <kernel-features.h> #include <dl-sysdep.h> +#include <endian.h> #include <fcntl.h> #include <stdint.h> #include <not-cancel.h> @@ -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)) |