mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-26 23:10:06 +00:00
* Versions.def (ld): Add GLIBC_2.4.
* configure.in: Add --enable-stackguard-randomization option. (ENABLE_STACKGUARD_RANDOMIZE): New define. * config.h.in (ENABLE_STACKGUARD_RANDOMIZE): Add. * sysdeps/unix/sysv/linux/dl-osinfo.h: Include stdint.h. (_dl_setup_stack_chk_guard): New inline function. * sysdeps/generic/dl-osinfo.h: Include stdint.h. (_dl_setup_stack_chk_guard): New inline function. * elf/rtld.c (__stack_chk_guard): New variable. (dl_main): Remove all traces of TLS_INIT_TP_EXPENSIVE. Set __stack_chk_guard to _dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined. * elf/Versions (ld): Export __stack_chk_guard@@GLIBC_2.4. * sysdeps/generic/libc-start.c (__stack_chk_guard): New variable. (__libc_start_main): Set __stack_chk_guard to _dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined. * sysdeps/generic/libc-tls.c (__libc_setup_tls): Remove all traces of TLS_INIT_TP_EXPENSIVE. * debug/Versions (libc): Export __stack_chk_fail@@GLIBC_2.4. * debug/Makefile (routines): Add stack_chk_fail. (static-only-routines): Add stack_chk_fail_local. * debug/stack_chk_fail_local.c: New file. * debug/stack_chk_fail.c: New file. * elf/Makefile: Add rules to build and run tst-stackguard1{,-static} tests. * elf/tst-stackguard1.c: New file. * elf/tst-stackguard1-static.c: New file. * elf/stackguard-macros.h: New file.
This commit is contained in:
parent
2f37117b01
commit
35f1e82763
31
ChangeLog
31
ChangeLog
@ -1,3 +1,34 @@
|
||||
2005-06-25 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* Versions.def (ld): Add GLIBC_2.4.
|
||||
* configure.in: Add --enable-stackguard-randomization option.
|
||||
(ENABLE_STACKGUARD_RANDOMIZE): New define.
|
||||
* config.h.in (ENABLE_STACKGUARD_RANDOMIZE): Add.
|
||||
* sysdeps/unix/sysv/linux/dl-osinfo.h: Include stdint.h.
|
||||
(_dl_setup_stack_chk_guard): New inline function.
|
||||
* sysdeps/generic/dl-osinfo.h: Include stdint.h.
|
||||
(_dl_setup_stack_chk_guard): New inline function.
|
||||
* elf/rtld.c (__stack_chk_guard): New variable.
|
||||
(dl_main): Remove all traces of TLS_INIT_TP_EXPENSIVE.
|
||||
Set __stack_chk_guard to _dl_setup_stack_chk_guard (),
|
||||
use THREAD_SET_STACK_GUARD if defined.
|
||||
* elf/Versions (ld): Export __stack_chk_guard@@GLIBC_2.4.
|
||||
* sysdeps/generic/libc-start.c (__stack_chk_guard): New variable.
|
||||
(__libc_start_main): Set __stack_chk_guard to
|
||||
_dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined.
|
||||
* sysdeps/generic/libc-tls.c (__libc_setup_tls): Remove all
|
||||
traces of TLS_INIT_TP_EXPENSIVE.
|
||||
* debug/Versions (libc): Export __stack_chk_fail@@GLIBC_2.4.
|
||||
* debug/Makefile (routines): Add stack_chk_fail.
|
||||
(static-only-routines): Add stack_chk_fail_local.
|
||||
* debug/stack_chk_fail_local.c: New file.
|
||||
* debug/stack_chk_fail.c: New file.
|
||||
* elf/Makefile: Add rules to build and run tst-stackguard1{,-static}
|
||||
tests.
|
||||
* elf/tst-stackguard1.c: New file.
|
||||
* elf/tst-stackguard1-static.c: New file.
|
||||
* elf/stackguard-macros.h: New file.
|
||||
|
||||
2005-06-21 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* resource/Makefile (tests): Add tst-getrlimit.
|
||||
|
@ -102,6 +102,7 @@ ld {
|
||||
GLIBC_2.0
|
||||
GLIBC_2.1
|
||||
GLIBC_2.3
|
||||
GLIBC_2.4
|
||||
GLIBC_PRIVATE
|
||||
}
|
||||
libthread_db {
|
||||
|
@ -223,6 +223,9 @@
|
||||
/* Define if your assembler and linker support R_PPC_REL16* relocs. */
|
||||
#undef HAVE_ASM_PPC_REL16
|
||||
|
||||
/* Define if __stack_chk_guard canary should be randomized at program startup. */
|
||||
#undef ENABLE_STACKGUARD_RANDOMIZE
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
|
17
configure
vendored
17
configure
vendored
@ -873,6 +873,9 @@ Optional Features:
|
||||
objects [default=yes if supported]
|
||||
--enable-oldest-abi=ABI configure the oldest ABI supported [e.g. 2.2]
|
||||
[default=glibc default]
|
||||
--enable-stackguard-randomization
|
||||
initialize __stack_chk_guard canary with a random
|
||||
number at program start
|
||||
--enable-add-ons[=DIRS...]
|
||||
configure and build add-ons in DIR1,DIR2,... search
|
||||
for add-ons if no parameter given
|
||||
@ -1597,6 +1600,20 @@ _ACEOF
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-stackguard-randomization or --disable-stackguard-randomization was given.
|
||||
if test "${enable_stackguard_randomization+set}" = set; then
|
||||
enableval="$enable_stackguard_randomization"
|
||||
enable_stackguard_randomize=$enableval
|
||||
else
|
||||
enable_stackguard_randomize=no
|
||||
fi;
|
||||
if test "$enable_stackguard_randomize" = yes; then
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define ENABLE_STACKGUARD_RANDOMIZE 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --enable-add-ons or --disable-add-ons was given.
|
||||
if test "${enable_add_ons+set}" = set; then
|
||||
enableval="$enable_add_ons"
|
||||
|
@ -174,6 +174,15 @@ else
|
||||
fi
|
||||
AC_SUBST(oldest_abi)
|
||||
|
||||
AC_ARG_ENABLE([stackguard-randomization],
|
||||
AC_HELP_STRING([--enable-stackguard-randomization],
|
||||
[initialize __stack_chk_guard canary with a random number at program start]),
|
||||
[enable_stackguard_randomize=$enableval],
|
||||
[enable_stackguard_randomize=no])
|
||||
if test "$enable_stackguard_randomize" = yes; then
|
||||
AC_DEFINE(ENABLE_STACKGUARD_RANDOMIZE)
|
||||
fi
|
||||
|
||||
dnl Generic infrastructure for drop-in additions to libc.
|
||||
AC_ARG_ENABLE([add-ons],
|
||||
AC_HELP_STRING([--enable-add-ons@<:@=DIRS...@:>@],
|
||||
|
@ -31,9 +31,9 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \
|
||||
printf_chk fprintf_chk vprintf_chk vfprintf_chk \
|
||||
gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \
|
||||
read_chk pread_chk pread64_chk recv_chk recvfrom_chk \
|
||||
readlink_chk getwd_chk getcwd_chk \
|
||||
readlink_chk getwd_chk getcwd_chk stack_chk_fail \
|
||||
$(static-only-routines)
|
||||
static-only-routines := warning-nop
|
||||
static-only-routines := warning-nop stack_chk_fail_local
|
||||
|
||||
CFLAGS-backtrace.c = -fno-omit-frame-pointer
|
||||
CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO
|
||||
|
@ -23,5 +23,7 @@ libc {
|
||||
__read_chk; __pread_chk; __pread64_chk;
|
||||
__readlink_chk; __getcwd_chk; __getwd_chk;
|
||||
__recv_chk; __recvfrom_chk;
|
||||
|
||||
__stack_chk_fail;
|
||||
}
|
||||
}
|
||||
|
33
debug/stack_chk_fail.c
Normal file
33
debug/stack_chk_fail.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* Copyright (C) 2005 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
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
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] ?: "<unknown>");
|
||||
}
|
30
debug/stack_chk_fail_local.c
Normal file
30
debug/stack_chk_fail_local.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* Copyright (C) 2005 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
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
extern void __stack_chk_fail (void) __attribute__ ((noreturn));
|
||||
|
||||
/* On some architectures, this helps needless PIC pointer setup
|
||||
that would be needed just for the __stack_chk_fail call. */
|
||||
|
||||
void __attribute__ ((noreturn)) attribute_hidden
|
||||
__stack_chk_fail_local (void)
|
||||
{
|
||||
__stack_chk_fail ();
|
||||
}
|
11
elf/Makefile
11
elf/Makefile
@ -87,7 +87,8 @@ distribute := rtld-Rules \
|
||||
unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \
|
||||
unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
|
||||
unload6mod1.c unload6mod2.c unload6mod3.c tst-auditmod1.c \
|
||||
order2mod1.c order2mod2.c order2mod3.c order2mod4.c
|
||||
order2mod1.c order2mod2.c order2mod3.c order2mod4.c \
|
||||
tst-stackguard1.c tst-stackguard1-static.c
|
||||
|
||||
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
|
||||
CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
|
||||
@ -140,7 +141,7 @@ ifeq (yes,$(have-initfini-array))
|
||||
tests += tst-array1 tst-array2 tst-array3 tst-array4
|
||||
endif
|
||||
ifeq (yes,$(build-static))
|
||||
tests-static = tst-tls1-static tst-tls2-static
|
||||
tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static
|
||||
ifeq (yesyesyes,$(build-static)$(build-shared)$(elf))
|
||||
tests-static += tst-tls9-static
|
||||
tst-tls9-static-ENV = \
|
||||
@ -162,7 +163,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \
|
||||
tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
|
||||
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
|
||||
unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2
|
||||
unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 \
|
||||
tst-stackguard1
|
||||
# reldep9
|
||||
test-srcs = tst-pathopt
|
||||
tests-vis-yes = vismain
|
||||
@ -843,3 +845,6 @@ $(objpfx)order2mod1.so: $(objpfx)order2mod4.so
|
||||
$(objpfx)order2mod4.so: $(objpfx)order2mod3.so
|
||||
$(objpfx)order2mod2.so: $(objpfx)order2mod3.so
|
||||
order2mod2.so-no-z-defs = yes
|
||||
|
||||
tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
|
||||
tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
|
||||
|
@ -43,6 +43,10 @@ ld {
|
||||
# runtime interface to TLS
|
||||
__tls_get_addr;
|
||||
}
|
||||
GLIBC_2.4 {
|
||||
# stack canary
|
||||
__stack_chk_guard;
|
||||
}
|
||||
GLIBC_PRIVATE {
|
||||
# Those are in the dynamic linker, but used by libc.so.
|
||||
__libc_enable_secure;
|
||||
|
26
elf/rtld.c
26
elf/rtld.c
@ -80,6 +80,12 @@ char **_dl_argv attribute_relro = NULL;
|
||||
#endif
|
||||
INTDEF(_dl_argv)
|
||||
|
||||
#ifndef THREAD_SET_STACK_GUARD
|
||||
/* Only exported for architectures that don't store the stack guard canary
|
||||
in thread local area. */
|
||||
uintptr_t __stack_chk_guard attribute_relro;
|
||||
#endif
|
||||
|
||||
/* Nonzero if we were run directly. */
|
||||
unsigned int _dl_skip_args attribute_relro attribute_hidden;
|
||||
|
||||
@ -1398,9 +1404,6 @@ ld.so does not support TLS, but program uses it!\n");
|
||||
always allocate the static block, we never defer it even if
|
||||
no DF_STATIC_TLS bit is set. The reason is that we know
|
||||
glibc will use the static model. */
|
||||
# ifndef TLS_INIT_TP_EXPENSIVE
|
||||
# define TLS_INIT_TP_EXPENSIVE 0
|
||||
# endif
|
||||
|
||||
/* Since we start using the auditing DSOs right away we need to
|
||||
initialize the data structures now. */
|
||||
@ -1807,10 +1810,18 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
used. Trying to do it lazily is too hairy to try when there could be
|
||||
multiple threads (from a non-TLS-using libpthread). */
|
||||
bool was_tls_init_tp_called = tls_init_tp_called;
|
||||
if (tcbp == NULL && (!TLS_INIT_TP_EXPENSIVE || GL(dl_tls_max_dtv_idx) > 0))
|
||||
if (tcbp == NULL)
|
||||
tcbp = init_tls ();
|
||||
#endif
|
||||
|
||||
/* Set up the stack checker's canary. */
|
||||
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
|
||||
#ifdef THREAD_SET_STACK_GUARD
|
||||
THREAD_SET_STACK_GUARD (stack_chk_guard);
|
||||
#else
|
||||
__stack_chk_guard = stack_chk_guard;
|
||||
#endif
|
||||
|
||||
if (__builtin_expect (mode, normal) != normal)
|
||||
{
|
||||
/* We were run just to list the shared libraries. It is
|
||||
@ -2230,8 +2241,6 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD || !TLS_INIT_TP_EXPENSIVE)
|
||||
{
|
||||
if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
|
||||
++GL(dl_tls_generation);
|
||||
|
||||
@ -2249,10 +2258,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
_dl_fatal_printf ("cannot set up thread-local storage: %s\n",
|
||||
lossage);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#else
|
||||
NONTLS_INIT_TP;
|
||||
#endif
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have added all objects. */
|
||||
|
30
elf/stackguard-macros.h
Normal file
30
elf/stackguard-macros.h
Normal file
@ -0,0 +1,30 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __i386__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; })
|
||||
#elif defined __x86_64__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("movq %%fs:0x28, %0" : "=r" (x)); x; })
|
||||
#elif defined __powerpc64__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; })
|
||||
#elif defined __powerpc__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; })
|
||||
#elif defined __sparc__ && defined __arch64__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; })
|
||||
#elif defined __sparc__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; })
|
||||
#elif defined __s390x__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("ear %0,%a0; sllg %0,%0,32; ear %0,%a1; lg %0,0x28(%0)" : "=r" (x)); x; })
|
||||
#elif defined __s390__
|
||||
# define STACK_CHK_GUARD \
|
||||
({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=r" (x)); x; })
|
||||
#else
|
||||
extern uintptr_t __stack_chk_guard;
|
||||
# define STACK_CHK_GUARD __stack_chk_guard
|
||||
#endif
|
1
elf/tst-stackguard1-static.c
Normal file
1
elf/tst-stackguard1-static.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-stackguard1.c"
|
196
elf/tst-stackguard1.c
Normal file
196
elf/tst-stackguard1.c
Normal file
@ -0,0 +1,196 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stackguard-macros.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char *command;
|
||||
static bool child;
|
||||
static uintptr_t stack_chk_guard_copy;
|
||||
static bool stack_chk_guard_copy_set;
|
||||
static int fds[2];
|
||||
|
||||
static void __attribute__ ((constructor))
|
||||
con (void)
|
||||
{
|
||||
stack_chk_guard_copy = STACK_CHK_GUARD;
|
||||
stack_chk_guard_copy_set = true;
|
||||
}
|
||||
|
||||
static int
|
||||
uintptr_t_cmp (const void *a, const void *b)
|
||||
{
|
||||
if (*(uintptr_t *) a < *(uintptr_t *) b)
|
||||
return 1;
|
||||
if (*(uintptr_t *) a > *(uintptr_t *) b)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (!stack_chk_guard_copy_set)
|
||||
{
|
||||
puts ("constructor has not been run");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||
{
|
||||
puts ("STACK_CHK_GUARD changed between constructor and do_test");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (child)
|
||||
{
|
||||
write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (command == NULL)
|
||||
{
|
||||
puts ("missing --command or --child argument");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define N 16
|
||||
uintptr_t child_stack_chk_guards[N + 1];
|
||||
child_stack_chk_guards[N] = stack_chk_guard_copy;
|
||||
int i;
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
if (pipe (fds) < 0)
|
||||
{
|
||||
printf ("couldn't create pipe: %m\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t pid = fork ();
|
||||
if (pid < 0)
|
||||
{
|
||||
printf ("fork failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pid)
|
||||
{
|
||||
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||
{
|
||||
puts ("STACK_CHK_GUARD changed after fork");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fds[0]);
|
||||
close (2);
|
||||
dup2 (fds[1], 2);
|
||||
close (fds[1]);
|
||||
|
||||
system (command);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
close (fds[1]);
|
||||
|
||||
if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
|
||||
sizeof (uintptr_t))) != sizeof (uintptr_t))
|
||||
{
|
||||
puts ("could not read stack_chk_guard value from child");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close (fds[0]);
|
||||
|
||||
pid_t termpid;
|
||||
int status;
|
||||
termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
|
||||
if (termpid == -1)
|
||||
{
|
||||
printf ("waitpid failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
else if (termpid != pid)
|
||||
{
|
||||
printf ("waitpid returned %ld != %ld\n",
|
||||
(long int) termpid, (long int) pid);
|
||||
return 1;
|
||||
}
|
||||
else if (!WIFEXITED (status) || WEXITSTATUS (status))
|
||||
{
|
||||
puts ("child hasn't exited with exit status 0");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
|
||||
|
||||
uintptr_t default_guard = 0;
|
||||
unsigned char *p = (unsigned char *) &default_guard;
|
||||
p[sizeof (uintptr_t) - 1] = 255;
|
||||
p[sizeof (uintptr_t) - 2] = '\n';
|
||||
p[0] = 0;
|
||||
|
||||
/* Test if the stack guard canaries are either randomized,
|
||||
or equal to the default stack guard canary value.
|
||||
Even with randomized stack guards it might happen
|
||||
that the random number generator generates the same
|
||||
values, but if that happens in more than half from
|
||||
the 16 runs, something is very wrong. */
|
||||
int ndifferences = 0;
|
||||
int ndefaults = 0;
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
|
||||
ndifferences++;
|
||||
else if (child_stack_chk_guards[i] == default_guard)
|
||||
ndefaults++;
|
||||
}
|
||||
|
||||
printf ("differences %d defaults %d\n", ndifferences, ndefaults);
|
||||
|
||||
if (ndifferences < N / 2 && ndefaults < N / 2)
|
||||
{
|
||||
puts ("stack guard canaries are not randomized enough");
|
||||
puts ("nor equal to the default canary value");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OPT_COMMAND 10000
|
||||
#define OPT_CHILD 10001
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "command", required_argument, NULL, OPT_COMMAND }, \
|
||||
{ "child", no_argument, NULL, OPT_CHILD },
|
||||
#define CMDLINE_PROCESS \
|
||||
case OPT_COMMAND: \
|
||||
command = optarg; \
|
||||
break; \
|
||||
case OPT_CHILD: \
|
||||
child = true; \
|
||||
break;
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -269,7 +269,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
|
||||
tst-oncex3 tst-oncex4
|
||||
endif
|
||||
ifeq ($(build-shared),yes)
|
||||
tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1
|
||||
tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \
|
||||
tst-stackguard1
|
||||
tests-nolibpthread += tst-fini1
|
||||
ifeq ($(have-z-execstack),yes)
|
||||
tests += tst-execstack
|
||||
@ -337,7 +338,8 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \
|
||||
$(common-objpfx)libc.a
|
||||
|
||||
ifeq ($(build-static),yes)
|
||||
tests-static += tst-locale1 tst-locale2
|
||||
tests-static += tst-locale1 tst-locale2 tst-stackguard1-static
|
||||
tests += tst-stackguard1-static
|
||||
xtests-static += tst-setuid1-static
|
||||
endif
|
||||
# These tests are linked with libc before libpthread
|
||||
@ -586,6 +588,9 @@ LDFLAGS-tst-execstack = -Wl,-z,noexecstack
|
||||
|
||||
$(objpfx)tst-fini1mod.so: $(shared-thread-library)
|
||||
|
||||
tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
|
||||
tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
|
||||
|
||||
# The tests here better do not run in parallel
|
||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
||||
.NOTPARALLEL:
|
||||
|
@ -399,6 +399,11 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
|
||||
pd->schedpolicy = self->schedpolicy;
|
||||
pd->schedparam = self->schedparam;
|
||||
|
||||
/* Copy the stack guard canary. */
|
||||
#ifdef THREAD_COPY_STACK_GUARD
|
||||
THREAD_COPY_STACK_GUARD (pd);
|
||||
#endif
|
||||
|
||||
/* Determine scheduling parameters for the thread. */
|
||||
if (attr != NULL
|
||||
&& __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
|
||||
|
@ -49,6 +49,7 @@ typedef struct
|
||||
void *self; /* Pointer to the thread descriptor. */
|
||||
int multiple_threads;
|
||||
uintptr_t sysinfo;
|
||||
uintptr_t stack_guard;
|
||||
} tcbhead_t;
|
||||
|
||||
# define TLS_MULTIPLE_THREADS_IN_TCB 1
|
||||
@ -416,6 +417,14 @@ union user_desc_init
|
||||
__res; })
|
||||
|
||||
|
||||
/* Set the stack guard field in TCB head. */
|
||||
#define THREAD_SET_STACK_GUARD(value) \
|
||||
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||
#define THREAD_COPY_STACK_GUARD(descr) \
|
||||
((descr)->header.stack_guard \
|
||||
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* tls.h */
|
||||
|
@ -65,11 +65,11 @@ typedef union dtv
|
||||
/* Get the thread descriptor definition. */
|
||||
# include <nptl/descr.h>
|
||||
|
||||
/* This layout is actually wholly private and not affected by the ABI.
|
||||
Nor does it overlap the pthread data structure, so we need nothing
|
||||
extra here at all. */
|
||||
/* The stack_guard is accessed directly by GCC -fstack-protector code,
|
||||
so it is a part of public ABI. The dtv field is private. */
|
||||
typedef struct
|
||||
{
|
||||
uintptr_t stack_guard;
|
||||
dtv_t *dtv;
|
||||
} tcbhead_t;
|
||||
|
||||
@ -156,6 +156,16 @@ register void *__thread_register __asm__ ("r13");
|
||||
# define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||
((void)(descr), (THREAD_SELF)->member[idx] = (value))
|
||||
|
||||
/* Set the stack guard field in TCB head. */
|
||||
# define THREAD_SET_STACK_GUARD(value) \
|
||||
(((tcbhead_t *) ((char *) __thread_register \
|
||||
- TLS_TCB_OFFSET))[-1].stack_guard = (value))
|
||||
# define THREAD_COPY_STACK_GUARD(descr) \
|
||||
(((tcbhead_t *) ((char *) (descr) \
|
||||
+ TLS_PRE_TCB_SIZE))[-1].stack_guard \
|
||||
= ((tcbhead_t *) ((char *) __thread_register \
|
||||
- TLS_TCB_OFFSET))[-1].stack_guard)
|
||||
|
||||
/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some
|
||||
different value to mean unset l_tls_offset. */
|
||||
# define NO_TLS_OFFSET -1
|
||||
|
@ -48,9 +48,8 @@ typedef struct
|
||||
dtv_t *dtv;
|
||||
void *self; /* Pointer to the thread descriptor. */
|
||||
int multiple_threads;
|
||||
# ifdef NEED_DL_SYSINFO
|
||||
uintptr_t sysinfo;
|
||||
# endif
|
||||
uintptr_t stack_guard;
|
||||
} tcbhead_t;
|
||||
|
||||
# ifndef __s390x__
|
||||
@ -158,6 +157,13 @@ typedef struct
|
||||
#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||
descr->member[idx] = (value)
|
||||
|
||||
/* Set the stack guard field in TCB head. */
|
||||
#define THREAD_SET_STACK_GUARD(value) \
|
||||
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||
#define THREAD_COPY_STACK_GUARD(descr) \
|
||||
((descr)->header.stack_guard \
|
||||
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* tls.h */
|
||||
|
@ -46,6 +46,8 @@ typedef struct
|
||||
dtv_t *dtv;
|
||||
void *self;
|
||||
int multiple_threads;
|
||||
uintptr_t sysinfo;
|
||||
uintptr_t stack_guard;
|
||||
} tcbhead_t;
|
||||
|
||||
#else /* __ASSEMBLER__ */
|
||||
@ -126,6 +128,13 @@ register struct pthread *__thread_self __asm__("%g7");
|
||||
#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||
descr->member[idx] = (value)
|
||||
|
||||
/* Set the stack guard field in TCB head. */
|
||||
#define THREAD_SET_STACK_GUARD(value) \
|
||||
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||
# define THREAD_COPY_STACK_GUARD(descr) \
|
||||
((descr)->header.stack_guard \
|
||||
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||
|
||||
#endif /* !ASSEMBLER */
|
||||
|
||||
#endif /* tls.h */
|
||||
|
@ -47,6 +47,8 @@ typedef struct
|
||||
dtv_t *dtv;
|
||||
void *self; /* Pointer to the thread descriptor. */
|
||||
int multiple_threads;
|
||||
uintptr_t sysinfo;
|
||||
uintptr_t stack_guard;
|
||||
} tcbhead_t;
|
||||
|
||||
#else /* __ASSEMBLER__ */
|
||||
@ -320,6 +322,13 @@ typedef struct
|
||||
__res; })
|
||||
|
||||
|
||||
/* Set the stack guard field in TCB head. */
|
||||
# define THREAD_SET_STACK_GUARD(value) \
|
||||
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||
# define THREAD_COPY_STACK_GUARD(descr) \
|
||||
((descr)->header.stack_guard \
|
||||
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* tls.h */
|
||||
|
1
nptl/tst-stackguard1-static.c
Normal file
1
nptl/tst-stackguard1-static.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-stackguard1.c"
|
226
nptl/tst-stackguard1.c
Normal file
226
nptl/tst-stackguard1.c
Normal file
@ -0,0 +1,226 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <elf/stackguard-macros.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char *command;
|
||||
static bool child;
|
||||
static uintptr_t stack_chk_guard_copy;
|
||||
static bool stack_chk_guard_copy_set;
|
||||
static int fds[2];
|
||||
|
||||
static void __attribute__ ((constructor))
|
||||
con (void)
|
||||
{
|
||||
stack_chk_guard_copy = STACK_CHK_GUARD;
|
||||
stack_chk_guard_copy_set = true;
|
||||
}
|
||||
|
||||
static int
|
||||
uintptr_t_cmp (const void *a, const void *b)
|
||||
{
|
||||
if (*(uintptr_t *) a < *(uintptr_t *) b)
|
||||
return 1;
|
||||
if (*(uintptr_t *) a > *(uintptr_t *) b)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||
{
|
||||
puts ("STACK_CHK_GUARD changed in thread");
|
||||
return (void *) 1L;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (!stack_chk_guard_copy_set)
|
||||
{
|
||||
puts ("constructor has not been run");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||
{
|
||||
puts ("STACK_CHK_GUARD changed between constructor and do_test");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (child)
|
||||
{
|
||||
int i;
|
||||
pthread_t th[4];
|
||||
void *ret;
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (pthread_create (&th[i], NULL, tf, NULL))
|
||||
{
|
||||
puts ("thread creation failed");
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (pthread_join (th[i], &ret))
|
||||
{
|
||||
puts ("thread join failed");
|
||||
return 1;
|
||||
}
|
||||
else if (ret != NULL)
|
||||
return 1;
|
||||
|
||||
write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (command == NULL)
|
||||
{
|
||||
puts ("missing --command or --child argument");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define N 16
|
||||
uintptr_t child_stack_chk_guards[N + 1];
|
||||
child_stack_chk_guards[N] = stack_chk_guard_copy;
|
||||
int i;
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
if (pipe (fds) < 0)
|
||||
{
|
||||
printf ("couldn't create pipe: %m\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t pid = fork ();
|
||||
if (pid < 0)
|
||||
{
|
||||
printf ("fork failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pid)
|
||||
{
|
||||
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||
{
|
||||
puts ("STACK_CHK_GUARD changed after fork");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fds[0]);
|
||||
close (2);
|
||||
dup2 (fds[1], 2);
|
||||
close (fds[1]);
|
||||
|
||||
system (command);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
close (fds[1]);
|
||||
|
||||
if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
|
||||
sizeof (uintptr_t))) != sizeof (uintptr_t))
|
||||
{
|
||||
puts ("could not read stack_chk_guard value from child");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close (fds[0]);
|
||||
|
||||
pid_t termpid;
|
||||
int status;
|
||||
termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
|
||||
if (termpid == -1)
|
||||
{
|
||||
printf ("waitpid failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
else if (termpid != pid)
|
||||
{
|
||||
printf ("waitpid returned %ld != %ld\n",
|
||||
(long int) termpid, (long int) pid);
|
||||
return 1;
|
||||
}
|
||||
else if (!WIFEXITED (status) || WEXITSTATUS (status))
|
||||
{
|
||||
puts ("child hasn't exited with exit status 0");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
|
||||
|
||||
uintptr_t default_guard = 0;
|
||||
unsigned char *p = (unsigned char *) &default_guard;
|
||||
p[sizeof (uintptr_t) - 1] = 255;
|
||||
p[sizeof (uintptr_t) - 2] = '\n';
|
||||
p[0] = 0;
|
||||
|
||||
/* Test if the stack guard canaries are either randomized,
|
||||
or equal to the default stack guard canary value.
|
||||
Even with randomized stack guards it might happen
|
||||
that the random number generator generates the same
|
||||
values, but if that happens in more than half from
|
||||
the 16 runs, something is very wrong. */
|
||||
int ndifferences = 0;
|
||||
int ndefaults = 0;
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
|
||||
ndifferences++;
|
||||
else if (child_stack_chk_guards[i] == default_guard)
|
||||
ndefaults++;
|
||||
}
|
||||
|
||||
printf ("differences %d defaults %d\n", ndifferences, ndefaults);
|
||||
|
||||
if (ndifferences < N / 2 && ndefaults < N / 2)
|
||||
{
|
||||
puts ("stack guard canaries are not randomized enough");
|
||||
puts ("nor equal to the default canary value");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OPT_COMMAND 10000
|
||||
#define OPT_CHILD 10001
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "command", required_argument, NULL, OPT_COMMAND }, \
|
||||
{ "child", no_argument, NULL, OPT_CHILD },
|
||||
#define CMDLINE_PROCESS \
|
||||
case OPT_COMMAND: \
|
||||
command = optarg; \
|
||||
break; \
|
||||
case OPT_CHILD: \
|
||||
child = true; \
|
||||
break;
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -1 +1,12 @@
|
||||
/* Nothing needed in general. */
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uintptr_t __attribute__ ((always_inline))
|
||||
_dl_setup_stack_chk_guard (void)
|
||||
{
|
||||
uintptr_t ret = 0;
|
||||
unsigned char *p = (unsigned char *) &ret;
|
||||
p[sizeof (ret) - 1] = 255;
|
||||
p[sizeof (ret) - 2] = '\n';
|
||||
p[0] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
@ -35,6 +35,11 @@ extern void __pthread_initialize_minimal (void)
|
||||
__attribute__ ((weak))
|
||||
# endif
|
||||
;
|
||||
# ifndef THREAD_SET_STACK_GUARD
|
||||
/* Only exported for architectures that don't store the stack guard canary
|
||||
in thread local area. */
|
||||
uintptr_t __stack_chk_guard attribute_relro;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTR_NTHREADS
|
||||
@ -152,6 +157,16 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||
__pthread_initialize_minimal ();
|
||||
#endif
|
||||
|
||||
# ifndef SHARED
|
||||
/* Set up the stack checker's canary. */
|
||||
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
|
||||
# ifdef THREAD_SET_STACK_GUARD
|
||||
THREAD_SET_STACK_GUARD (stack_chk_guard);
|
||||
# else
|
||||
__stack_chk_guard = stack_chk_guard;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Register the destructor of the dynamic linker if there is any. */
|
||||
if (__builtin_expect (rtld_fini != NULL, 1))
|
||||
__cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
|
||||
|
@ -133,17 +133,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef TLS_INIT_TP_EXPENSIVE
|
||||
if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE)
|
||||
{
|
||||
/* We do not need a TLS block and no thread descriptor. */
|
||||
# ifdef NONTLS_INIT_TP
|
||||
NONTLS_INIT_TP;
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We have to set up the TCB block which also (possibly) contains
|
||||
'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
|
||||
Instead we use 'sbrk' which would only uses 'errno' if it fails.
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <sys/utsname.h>
|
||||
#include "kernel-features.h"
|
||||
#include <dl-sysdep.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
@ -157,3 +158,24 @@ _dl_discover_osversion (void)
|
||||
else if (__LINUX_KERNEL_VERSION > 0) \
|
||||
FATAL ("FATAL: cannot determine kernel version\n"); \
|
||||
} while (0)
|
||||
|
||||
static inline uintptr_t __attribute__ ((always_inline))
|
||||
_dl_setup_stack_chk_guard (void)
|
||||
{
|
||||
uintptr_t ret;
|
||||
#ifdef ENABLE_STACKGUARD_RANDOMIZE
|
||||
int fd = __open ("/dev/urandom", O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
ssize_t reslen = __read (fd, &ret, sizeof (ret));
|
||||
__close (fd);
|
||||
if (reslen == (ssize_t) sizeof (ret))
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
ret = 0;
|
||||
unsigned char *p = (unsigned char *) &ret;
|
||||
p[sizeof (ret) - 1] = 255;
|
||||
p[sizeof (ret) - 2] = '\n';
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user