Submitted By: Robert Connolly (ashes) Date: 2007-04-25 Initial Package Version: 2.5 Upstream Status: Rejected http://sources.redhat.com/bugzilla/show_bug.cgi?id=4417 Origin: OpenBSD src/lib/libc/crypt/arc4random.c v1.16, and Alt/Owl Linux glibc-2.5-owl-alt-res_randomid.patch. Description: This patch adds arc4random(3) to the Glibc library, to tempname.c for mktemp and friends, to res_init.c and res_mkquery.c to improve the resolver, and to bindrsvprt.c to randomize the port numbers. This patch also adds the --with-prng-device configure option to let you specify /dev/urandom, /dev/erandom, or whatever. This device does not need to exist at build time. This patch also uses ./configure to check for RANDOM_ERANDOM in , and will use it with arc4random() if it is found. /dev/?random will be used otherwise, and none need to exist in the host kernel at build time. Note: It looks like the Linux kernel will eventually stop supplying the __sysctl syscall, so this option may be removed one day. After 'make install' you will probably want to install the manual/arc4random.3 manual page. diff -Naur glibc-2.5.orig/config.h.in glibc-2.5/config.h.in --- glibc-2.5.orig/config.h.in 2006-03-02 15:54:43.000000000 +0000 +++ glibc-2.5/config.h.in 2007-04-24 21:30:07.000000000 +0000 @@ -206,6 +206,12 @@ /* Define if __stack_chk_guard canary should be randomized at program startup. */ #undef ENABLE_STACKGUARD_RANDOMIZE +/* Define this to the system's pseudo-random device (/dev/urandom). */ +#undef PRNG_DEV + +/* Define if your has RANDOM_ERANDOM. */ +#undef HAVE_RANDOM_ERANDOM + /* */ diff -Naur glibc-2.5.orig/configure glibc-2.5/configure --- glibc-2.5.orig/configure 2006-09-29 20:18:33.000000000 +0000 +++ glibc-2.5/configure 2007-04-24 21:30:07.000000000 +0000 @@ -313,7 +313,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons add_on_subdirs base_machine submachine sysnames sysdeps_add_ons INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES CXX_SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_asm_protected_directive libc_cv_cc_with_libunwind libc_cv_z_nodelete libc_cv_z_nodlopen libc_cv_z_initfirst libc_cv_z_relro libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie libc_cv_hashstyle fno_unit_at_a_time libc_cv_ssp libc_cv_have_initfini no_whole_archive exceptions LIBGD have_libaudit have_libcap have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script elf xcoff static shared pic_default profile omitfp bounded static_nss nopic_initfini DEFINES mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS with_fp with_cvs enable_check_abi oldest_abi bindnow force_install all_warnings build build_cpu build_vendor build_os host host_cpu host_vendor host_os subdirs add_ons add_on_subdirs base_machine submachine sysnames sysdeps_add_ons INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT BUILD_CC cross_compiling CPP CXX CXXFLAGS ac_ct_CXX AR OBJDUMP RANLIB ac_ct_RANLIB MIG AS LD PWD_P MAKE MSGFMT MAKEINFO SED AUTOCONF SYSINCLUDES CXX_SYSINCLUDES libc_cv_gcc_static_libgcc BASH libc_cv_have_bash2 KSH libc_cv_have_ksh AWK PERL INSTALL_INFO BISON VERSIONING libc_cv_asm_protected_directive libc_cv_cc_with_libunwind libc_cv_z_nodelete libc_cv_z_nodlopen libc_cv_z_initfirst libc_cv_z_relro libc_cv_Bgroup libc_cv_libgcc_s_suffix libc_cv_as_needed ASFLAGS_config libc_cv_z_combreloc libc_cv_z_execstack libc_cv_fpie libc_cv_hashstyle fno_unit_at_a_time libc_cv_ssp libc_cv_have_initfini no_whole_archive exceptions LIBGD have_libaudit have_libcap have_selinux EGREP sizeof_long_double libc_cv_gcc_unwind_find_fde uname_sysname uname_release uname_version old_glibc_headers libc_cv_slibdir libc_cv_localedir libc_cv_sysconfdir libc_cv_rootsbindir libc_cv_forced_unwind use_ldconfig ldd_rewrite_script elf xcoff static shared pic_default have_random_erandom profile omitfp bounded static_nss nopic_initfini DEFINES mach_interface_list VERSION RELEASE LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -903,6 +903,9 @@ --with-headers=PATH location of system headers to use (for example /usr/src/linux/include) [default=compiler default] + --with-prng-device=/path/to/prng + specify the path to the system's pseudo-random + device. [default=/dev/urandom] --with-tls enable support for TLS --without-__thread do not use TLS features even when supporting them --with-cpu=CPU select code for CPU variant @@ -1513,6 +1516,19 @@ sysheaders='' fi; + +# Check whether --with-prng-device or --without-prng-device was given. +if test "${with_prng_device+set}" = set; then + withval="$with_prng_device" + prng_device=$withval +else + prng_device=/dev/urandom +fi; +cat >>confdefs.h <<_ACEOF +#define PRNG_DEV "$prng_device" +_ACEOF + + # Check whether --enable-sanity-checks or --disable-sanity-checks was given. if test "${enable_sanity_checks+set}" = set; then enableval="$enable_sanity_checks" @@ -7797,6 +7813,31 @@ echo "${ECHO_T}$pic_default" >&6 +echo "$as_me:$LINENO: checking whether you have sysctl RANDOM_ERANDOM" >&5 +echo $ECHO_N "checking whether you have sysctl RANDOM_ERANDOM... $ECHO_C" >&6 +if test "${have_random_erandom+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + have_random_erandom=no +cat > conftest.c < +int main(void) { return RANDOM_ERANDOM; } +EOF +if eval "${CC-cc} -S conftest.c 2>&5 1>&5"; then + have_random_erandom=yes +fi +rm -f conftest.* +fi +echo "$as_me:$LINENO: result: $have_random_erandom" >&5 +echo "${ECHO_T}$have_random_erandom" >&6 + +if test $have_random_erandom = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_RANDOM_ERANDOM 1 +_ACEOF + +fi + @@ -8552,6 +8593,7 @@ s,@static@,$static,;t t s,@shared@,$shared,;t t s,@pic_default@,$pic_default,;t t +s,@have_random_erandom@,$have_random_erandom,;t t s,@profile@,$profile,;t t s,@omitfp@,$omitfp,;t t s,@bounded@,$bounded,;t t diff -Naur glibc-2.5.orig/configure.in glibc-2.5/configure.in --- glibc-2.5.orig/configure.in 2006-07-10 21:45:29.000000000 +0000 +++ glibc-2.5/configure.in 2007-04-24 21:30:07.000000000 +0000 @@ -100,6 +100,15 @@ [sysheaders=$withval], [sysheaders='']) +AC_ARG_WITH([prng-device], + AC_HELP_STRING([--with-prng-device=/path/to/prng], + [specify the path to the system's + pseudo-random device. + @<:@default=/dev/urandom@:>@]), + [prng_device=$withval], + [prng_device=/dev/urandom]) +AC_DEFINE_UNQUOTED(PRNG_DEV, "$prng_device") + AC_ARG_ENABLE([sanity-checks], AC_HELP_STRING([--disable-sanity-checks], [really do not use threads (should not be used except in special situations) @<:@default=yes@:>@]), @@ -2165,6 +2174,21 @@ rm -f conftest.*]) AC_SUBST(pic_default) +AC_CACHE_CHECK([whether you have sysctl RANDOM_ERANDOM], have_random_erandom, +[have_random_erandom=no +cat > conftest.c < +int main(void) { return RANDOM_ERANDOM; } +EOF +if eval "${CC-cc} -S conftest.c 2>&AS_MESSAGE_LOG_FD 1>&AS_MESSAGE_LOG_FD"; then + have_random_erandom=yes +fi +rm -f conftest.*]) +AC_SUBST(have_random_erandom) +if test $have_random_erandom = yes; then + AC_DEFINE(HAVE_RANDOM_ERANDOM) +fi + AC_SUBST(profile) AC_SUBST(omitfp) AC_SUBST(bounded) diff -Naur glibc-2.5.orig/manual/arc4random.3 glibc-2.5/manual/arc4random.3 --- glibc-2.5.orig/manual/arc4random.3 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.5/manual/arc4random.3 2007-04-24 21:28:35.000000000 +0000 @@ -0,0 +1,110 @@ +.\" $OpenBSD: arc4random.3,v 1.19 2005/07/17 08:50:55 jaredy Exp $ +.\" +.\" Copyright 1997 Niels Provos +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Niels Provos. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" Manual page, using -mandoc macros +.\" +.Dd April 15, 1997 +.Dt ARC4RANDOM 3 +.Os +.Sh NAME +.Nm arc4random , +.Nm arc4random_stir , +.Nm arc4random_addrandom +.Nd arc4 random number generator +.Sh SYNOPSIS +.Fd #include +.Ft u_int32_t +.Fn arc4random "void" +.Ft void +.Fn arc4random_stir "void" +.Ft void +.Fn arc4random_addrandom "u_char *dat" "int datlen" +.Sh DESCRIPTION +The +.Fn arc4random +function provides a high quality 32-bit pseudo-random +number very quickly. +.Fn arc4random +seeds itself on a regular basis from the kernel strong random number +subsystem described in +.Xr random 4 . +On each call, an ARC4 generator is used to generate a new result. +The +.Fn arc4random +function uses the ARC4 cipher key stream generator, +which uses 8*8 8-bit S-Boxes. +The S-Boxes can be in about (2**1700) states. +.Pp +.Fn arc4random +fits into a middle ground not covered by other subsystems such as +the strong, slow, and resource expensive random +devices described in +.Xr random 4 +versus the fast but poor quality interfaces described in +.Xr rand 3 , +.Xr random 3 , +and +.Xr drand48 3 . +.Pp +The +.Fn arc4random_stir +function reads data from a pseudo-random device, usually +.Pa /dev/urandom, +and uses it to permute the S-Boxes via +.Fn arc4random_addrandom . +.Pp +There is no need to call +.Fn arc4random_stir +before using +.Fn arc4random , +since +.Fn arc4random +automatically initializes itself. +.Sh SEE ALSO +.Xr rand 3 , +.Xr rand48 3 , +.Xr random 3 +.Sh HISTORY +An algorithm called +.Pa RC4 +was designed by RSA Data Security, Inc. +It was considered a trade secret. +Because it was a trade secret, it obviously could not be patented. +A clone of this was posted anonymously to USENET and confirmed to +be equivalent by several sources who had access to the original cipher. +Because of the trade secret situation, RSA Data Security, Inc. can do +nothing about the release of the ARC4 algorithm. +Since +.Pa RC4 +used to be a trade secret, the cipher is now referred to as +.Pa ARC4 . +.Pp +These functions first appeared in +.Ox 2.1 . diff -Naur glibc-2.5.orig/resolv/res_init.c glibc-2.5/resolv/res_init.c --- glibc-2.5.orig/resolv/res_init.c 2006-09-04 17:59:54.000000000 +0000 +++ glibc-2.5/resolv/res_init.c 2007-04-24 21:38:06.000000000 +0000 @@ -537,7 +537,7 @@ u_int res_randomid(void) { - return 0xffff & __getpid(); + return arc4random() & 0xffff; } #ifdef _LIBC libc_hidden_def (__res_randomid) diff -Naur glibc-2.5.orig/resolv/res_mkquery.c glibc-2.5/resolv/res_mkquery.c --- glibc-2.5.orig/resolv/res_mkquery.c 2006-09-04 17:57:02.000000000 +0000 +++ glibc-2.5/resolv/res_mkquery.c 2007-04-25 00:31:25.000000000 +0000 @@ -120,23 +120,7 @@ return (-1); memset(buf, 0, HFIXEDSZ); hp = (HEADER *) buf; - /* We randomize the IDs every time. The old code just - incremented by one after the initial randomization which - still predictable if the application does multiple - requests. */ - int randombits; - do - { -#ifdef RANDOM_BITS - RANDOM_BITS (randombits); -#else - struct timeval tv; - __gettimeofday (&tv, NULL); - randombits = (tv.tv_sec << 8) ^ tv.tv_usec; -#endif - } - while ((randombits & 0xffff) == 0); - statp->id = (statp->id + randombits) & 0xffff; + statp->id = arc4random() & 0xffff; hp->id = statp->id; hp->opcode = op; hp->rd = (statp->options & RES_RECURSE) != 0; diff -Naur glibc-2.5.orig/scripts/data/localplt-i386-linux-gnu.data glibc-2.5/scripts/data/localplt-i386-linux-gnu.data --- glibc-2.5.orig/scripts/data/localplt-i386-linux-gnu.data 2006-01-11 21:06:19.000000000 +0000 +++ glibc-2.5/scripts/data/localplt-i386-linux-gnu.data 2007-04-25 02:25:02.000000000 +0000 @@ -1,4 +1,6 @@ libc.so: _Unwind_Find_FDE +libc.so: arc4random +libc.so: arc4random_stir libc.so: calloc libc.so: free libc.so: malloc diff -Naur glibc-2.5.orig/stdlib/Makefile glibc-2.5/stdlib/Makefile --- glibc-2.5.orig/stdlib/Makefile 2006-08-21 21:02:11.000000000 +0000 +++ glibc-2.5/stdlib/Makefile 2007-04-24 21:28:35.000000000 +0000 @@ -30,7 +30,7 @@ routines := \ atof atoi atol atoll \ - abort \ + abort arc4random \ bsearch qsort msort \ getenv putenv setenv secure-getenv \ exit on_exit atexit cxa_atexit cxa_finalize old_atexit \ diff -Naur glibc-2.5.orig/stdlib/Versions glibc-2.5/stdlib/Versions --- glibc-2.5.orig/stdlib/Versions 2004-05-03 21:25:53.000000000 +0000 +++ glibc-2.5/stdlib/Versions 2007-04-24 21:28:35.000000000 +0000 @@ -11,6 +11,7 @@ # a* a64l; abort; abs; atexit; atof; atoi; atol; atoll; + arc4random_stir; arc4random_addrandom; arc4random; # b* bsearch; diff -Naur glibc-2.5.orig/stdlib/arc4random.c glibc-2.5/stdlib/arc4random.c --- glibc-2.5.orig/stdlib/arc4random.c 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.5/stdlib/arc4random.c 2007-04-25 01:28:02.000000000 +0000 @@ -0,0 +1,258 @@ +/* + * Copyright (c) 1996, David Mazieres + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Arc4 random number generator for OpenBSD. + * + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * Here the stream cipher has been modified always to include entropy + * when initializing the state. That makes it impossible to + * regenerate the same random sequence twice, so this can't be used + * for encryption, but will generate good random numbers. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +/* Modified by Robert Connolly for Glibc. April 23, 2007 */ + +#include +#include +#include +#include +#include + +#if defined(HAVE_RANDOM_ERANDOM) +#include +#endif + +#ifdef __GNUC__ +#define inline __inline +#else +#define inline +#endif + +struct arc4_stream { + u_int8_t i; + u_int8_t j; + u_int8_t s[256]; +}; + +static int rs_initialized; +static struct arc4_stream rs; +static pid_t arc4_stir_pid; +static int arc4_count; + +static inline u_int8_t arc4_getbyte(struct arc4_stream *); + +#if defined(TEST) +u_int32_t arc4random(void); +void arc4random_stir(void); +void arc4random_addrandom(unsigned char *, int); +#endif + +#if !defined(_LIBC) +#define __getpid getpid +#define __gettimeofday gettimeofday +#define __open open +#define __read read +#define __close close +#endif + +static inline void +arc4_init(struct arc4_stream *as) +{ + int n; + + for (n = 0; n < 256; n++) + as->s[n] = n; + as->i = 0; + as->j = 0; +} + +static inline void +arc4_addrandom(struct arc4_stream *as, u_char *dat, int datlen) +{ + int n; + u_int8_t si; + + as->i--; + for (n = 0; n < 256; n++) { + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si + dat[n % datlen]); + as->s[as->i] = as->s[as->j]; + as->s[as->j] = si; + } + as->j = as->i; +} + +static void +arc4_stir(struct arc4_stream *as) +{ + int n, fd; + u_char rnd[128]; + struct timeval tv; + +#if defined(HAVE_RANDOM_ERANDOM) + /* This is the most efficient method (1 syscall). */ + int mib[3]; + size_t len; + + mib[0] = CTL_KERN; + mib[1] = KERN_RANDOM; + mib[2] = RANDOM_ERANDOM; + + len = sizeof(rnd); + if (__sysctl(mib, 3, rnd, &len, NULL, 0) == -1) + /* Sysctl failed? Try /dev/urandom (3 syscalls). */ +#endif + fd = __open(PRNG_DEV, O_RDONLY, 0); + if (fd != -1) { + __read(fd, rnd, sizeof(rnd)); + __close(fd); + } + /* Did the pseudo-random device fail? Use gettimeofday(). */ + else if (__gettimeofday(&tv, NULL) != (-1)) { + + /* Initialize the first element so it's hopefully not '0', + * to help out the next loop. Tossing in some prime numbers + * probably can't hurt. */ + rnd[0] = (tv.tv_sec % 10000) * 3 + tv.tv_usec * 7 + \ + (__getpid() % 1000) * 13; + + for (n = 1; n < 127 ; n++) { + + /* Take advantage of the stack space. Only initialize + * elements equal to '0'. This will make the rnd[] + * array much less vulnerable to timing attacks. Here + * we'll stir getpid() into the value of the previous + * elememnt. Approximately 1 in 128 elements will still + * become '0', so it will be a nightmare to try to + * predict this array. */ + + if (rnd[n] == 0) { + rnd[n] = ((rnd[n - 1] + n) ^ \ + ((__getpid() % 1000) * 17)); + } + } + } + else { + /* gettimeofday() failed? Do the same thing as above, but only + * with getpid(). This is very bad, but arc4random() should never + * fail, so never give up. */ + + rnd[0] = (__getpid() % 1000) * 19; + for (n = 1; n < 127 ; n++) { + if (rnd[n] == 0) { + rnd[n] = ((rnd[n - 1] + n) ^ \ + ((__getpid() % 1000) * 23)); + } + } + } + /* else??? Print warning here. */ + + arc4_stir_pid = __getpid(); + arc4_addrandom(as, rnd, sizeof(rnd)); + + /* + * Discard early keystream, as per recommendations in: + * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps + */ + for (n = 0; n < 256; n++) + (void)arc4_getbyte(as); + arc4_count = 1600000; +} + +static inline u_int8_t +arc4_getbyte(struct arc4_stream *as) +{ + u_int8_t si, sj; + + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si); + sj = as->s[as->j]; + as->s[as->i] = sj; + as->s[as->j] = si; + return (as->s[(si + sj) & 0xff]); +} + +/* + * __arc4_getbyte() is a libc private function intended for use + * with malloc(3) without calling getpid(2). It's good for + * fetching a specific amount of bytes. + */ +u_int8_t +__arc4_getbyte(void) +{ + if (--arc4_count == 0 || !rs_initialized) + arc4random_stir(); + return arc4_getbyte(&rs); +} + +static inline u_int32_t +arc4_getword(struct arc4_stream *as) +{ + u_int32_t val; + val = arc4_getbyte(as) << 24; + val |= arc4_getbyte(as) << 16; + val |= arc4_getbyte(as) << 8; + val |= arc4_getbyte(as); + return val; +} + +void +arc4random_stir(void) +{ + if (!rs_initialized) { + arc4_init(&rs); + rs_initialized = 1; + } + arc4_stir(&rs); +} + +void +arc4random_addrandom(u_char *dat, int datlen) +{ + if (!rs_initialized) + arc4random_stir(); + arc4_addrandom(&rs, dat, datlen); +} + +u_int32_t +arc4random(void) +{ + arc4_count -= 4; + if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != __getpid()) + arc4random_stir(); + return arc4_getword(&rs); +} + +#if defined(TEST) +#include +int main(void) +{ + int random_number; + random_number = arc4random() % 65536; + printf("%d\n", random_number); + return 0; +} +#endif diff -Naur glibc-2.5.orig/stdlib/stdlib.h glibc-2.5/stdlib/stdlib.h --- glibc-2.5.orig/stdlib/stdlib.h 2006-01-14 12:08:29.000000000 +0000 +++ glibc-2.5/stdlib/stdlib.h 2007-04-24 21:28:35.000000000 +0000 @@ -577,6 +577,12 @@ extern int lcong48_r (unsigned short int __param[7], struct drand48_data *__buffer) __THROW __nonnull ((1, 2)); + +/* Arcfour random number generator. */ +extern u_int32_t arc4random(void); +extern void arc4random_stir(void); +extern void arc4random_addrandom(unsigned char *, int); + # endif /* Use misc. */ #endif /* Use SVID or X/Open. */ diff -Naur glibc-2.5.orig/sunrpc/bindrsvprt.c glibc-2.5/sunrpc/bindrsvprt.c --- glibc-2.5.orig/sunrpc/bindrsvprt.c 2005-11-22 04:39:05.000000000 +0000 +++ glibc-2.5/sunrpc/bindrsvprt.c 2007-04-25 02:48:13.000000000 +0000 @@ -67,7 +67,7 @@ if (port == 0) { - port = (__getpid () % NPORTS) + STARTPORT; + port = (arc4random() % NPORTS) + STARTPORT; } /* Initialize to make gcc happy. */ diff -Naur glibc-2.5.orig/sysdeps/posix/tempname.c glibc-2.5/sysdeps/posix/tempname.c --- glibc-2.5.orig/sysdeps/posix/tempname.c 2006-04-07 19:29:07.000000000 +0000 +++ glibc-2.5/sysdeps/posix/tempname.c 2007-04-24 21:28:40.000000000 +0000 @@ -52,10 +52,6 @@ # include #endif -#if HAVE_SYS_TIME_H || _LIBC -# include -#endif - #if HAVE_STDINT_H || _LIBC # include #endif @@ -94,8 +90,6 @@ # define struct_stat64 struct stat64 #else # define struct_stat64 struct stat -# define __getpid getpid -# define __gettimeofday gettimeofday # define __mkdir mkdir # define __open open # define __open64 open @@ -107,25 +101,6 @@ # define __secure_getenv getenv #endif -#ifdef _LIBC -# include -# if HP_TIMING_AVAIL -# define RANDOM_BITS(Var) \ - if (__builtin_expect (value == UINT64_C (0), 0)) \ - { \ - /* If this is the first time this function is used initialize \ - the variable we accumulate the value in to some somewhat \ - random value. If we'd not do this programs at startup time \ - might have a reduced set of possible names, at least on slow \ - machines. */ \ - struct timeval tv; \ - __gettimeofday (&tv, NULL); \ - value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ - } \ - HP_TIMING_NOW (Var) -# endif -#endif - /* Use the widest available unsigned type if uint64_t is not available. The algorithm below extracts a number less than 62**6 (approximately 2**35.725) from uint64_t, so ancient hosts where @@ -229,10 +204,8 @@ { int len; char *XXXXXX; - static uint64_t value; - uint64_t random_time_bits; - unsigned int count; int fd = -1; + unsigned int i; int save_errno = errno; struct_stat64 st; @@ -262,39 +235,13 @@ /* This is where the Xs start. */ XXXXXX = &tmpl[len - 6]; - /* Get some more or less random data. */ -#ifdef RANDOM_BITS - RANDOM_BITS (random_time_bits); -#else -# if HAVE_GETTIMEOFDAY || _LIBC - { - struct timeval tv; - __gettimeofday (&tv, NULL); - random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; - } -# else - random_time_bits = time (NULL); -# endif -#endif - value += random_time_bits ^ __getpid (); - - for (count = 0; count < attempts; value += 7777, ++count) + for (i = 0; i < 6 ; ++i) { - uint64_t v = value; - - /* Fill in the random bits. */ - XXXXXX[0] = letters[v % 62]; - v /= 62; - XXXXXX[1] = letters[v % 62]; - v /= 62; - XXXXXX[2] = letters[v % 62]; - v /= 62; - XXXXXX[3] = letters[v % 62]; - v /= 62; - XXXXXX[4] = letters[v % 62]; - v /= 62; - XXXXXX[5] = letters[v % 62]; + XXXXXX[i] = letters[(arc4random() % 62)]; + } + for (i = 0; i < attempts; ++i) + { switch (kind) { case __GT_FILE: