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>
[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.

13
NEWS
View file

@ -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.

View file

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

View file

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