Make stack canary value harder to read through read overflow

This commit is contained in:
Ulrich Drepper 2011-05-15 10:59:07 -04:00
parent 05f399e634
commit 15a856b109
4 changed files with 61 additions and 28 deletions

View File

@ -1,5 +1,10 @@
2011-05-15 Ulrich Drepper <drepper@gmail.com> 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): * sysdeps/unix/sysv/linux/dl-osinfo.h (_dl_setup_stack_chk_guard):
Use non-cancelable interfaces. Use non-cancelable interfaces.

13
NEWS
View File

@ -9,12 +9,13 @@ Version 2.14
* The following bugs are resolved with this release: * The following bugs are resolved with this release:
386, 9809, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, 11901, 386, 9809, 10149, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724,
11945, 11947, 11952, 12052, 12083, 12158, 12178, 12200, 12346, 12393, 11901, 11945, 11947, 11952, 12052, 12083, 12158, 12178, 12200, 12346,
12420, 12432, 12445, 12449, 12453, 12454, 12460, 12469, 12489, 12509, 12393, 12420, 12432, 12445, 12449, 12453, 12454, 12460, 12469, 12489,
12510, 12511, 12518, 12527, 12541, 12545, 12551, 12582, 12583, 12587, 12509, 12510, 12511, 12518, 12527, 12541, 12545, 12551, 12582, 12583,
12597, 12601, 12611, 12625, 12626, 12631, 12650, 12653, 12655, 12660, 12587, 12597, 12601, 12611, 12625, 12626, 12631, 12650, 12653, 12655,
12681, 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734, 12738 12660, 12681, 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734,
12738
* The RPC implementation in libc is obsoleted. Old programs keep working * The RPC implementation in libc is obsoleted. Old programs keep working
but new programs cannot be linked with the routines in libc anymore. but new programs cannot be linked with the routines in libc anymore.

View File

@ -1,5 +1,5 @@
/* Operating system specific code for generic dynamic loader functions. /* 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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#include <endian.h>
#include <stdint.h> #include <stdint.h>
static inline uintptr_t __attribute__ ((always_inline)) static inline uintptr_t __attribute__ ((always_inline))
_dl_setup_stack_chk_guard (void *dl_random) _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) if (dl_random == NULL)
{ {
ret = 0; ret.bytes[sizeof (ret) - 2] = 255;
unsigned char *p = (unsigned char *) &ret; ret.bytes[sizeof (ret) - 3] = '\n';
p[sizeof (ret) - 1] = 255;
p[sizeof (ret) - 2] = '\n';
p[0] = 0;
} }
else 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)) static inline uintptr_t __attribute__ ((always_inline))

View File

@ -19,6 +19,7 @@
#include <kernel-features.h> #include <kernel-features.h>
#include <dl-sysdep.h> #include <dl-sysdep.h>
#include <endian.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdint.h> #include <stdint.h>
#include <not-cancel.h> #include <not-cancel.h>
@ -63,32 +64,46 @@ dl_fatal (const char *str)
static inline uintptr_t __attribute__ ((always_inline)) static inline uintptr_t __attribute__ ((always_inline))
_dl_setup_stack_chk_guard (void *dl_random) _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 #ifndef __ASSUME_AT_RANDOM
if (__builtin_expect (dl_random == NULL, 0)) if (__builtin_expect (dl_random == NULL, 0))
{ {
const size_t filllen = sizeof (ret.bytes) - 1;
ret.num = 0;
# ifdef ENABLE_STACKGUARD_RANDOMIZE # ifdef ENABLE_STACKGUARD_RANDOMIZE
int fd = open_not_cancel_2 ("/dev/urandom", O_RDONLY); int fd = open_not_cancel_2 ("/dev/urandom", O_RDONLY);
if (fd >= 0) 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); close_not_cancel_no_status (fd);
if (reslen == (ssize_t) sizeof (ret)) if (reslen == (ssize_) filllen)
return ret; return ret.num;
} }
# endif # endif
ret = 0; ret.bytes[filllen - 2] = 255;
unsigned char *p = (unsigned char *) &ret; ret.bytes[filllen - 3] = '\n';
p[sizeof (ret) - 1] = 255;
p[sizeof (ret) - 2] = '\n';
} }
else else
#endif #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 /* We need in the moment only 8 bytes on 32-bit platforms and 16
directly and not use the kernel-provided data to seed a PRNG. */ bytes on 64-bit platforms. Therefore we can use the data
memcpy (&ret, dl_random, sizeof (ret)); directly and not use the kernel-provided data to seed a PRNG. */
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)) static inline uintptr_t __attribute__ ((always_inline))