diff -Naur glibc-2.8-20080607.orig/config.h.in glibc-2.8-20080607/config.h.in --- glibc-2.8-20080607.orig/config.h.in 2007-03-26 20:40:08.000000000 +0000 +++ glibc-2.8-20080607/config.h.in 2008-06-10 01:54:11.000000000 +0000 @@ -189,6 +189,9 @@ /* 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 + /* */ diff -Naur glibc-2.8-20080607.orig/configure glibc-2.8-20080607/configure --- glibc-2.8-20080607.orig/configure 2008-04-11 17:53:20.000000000 +0000 +++ glibc-2.8-20080607/configure 2008-06-10 01:56:17.000000000 +0000 @@ -1393,6 +1393,9 @@ --without-cvs if CVS should not be used --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 @@ -1992,6 +1995,19 @@ 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 +fi; +if test "$prng_device" != "/dev/urandom"; then + cat >>confdefs.h <<_ACEOF +#define PRNG_DEV "$prng_device" +_ACEOF + +fi + + # Check whether --enable-sanity-checks was given. if test "${enable_sanity_checks+set}" = set; then enableval=$enable_sanity_checks; enable_sanity=$enableval diff -Naur glibc-2.8-20080607.orig/configure.in glibc-2.8-20080607/configure.in --- glibc-2.8-20080607.orig/configure.in 2008-04-11 17:52:55.000000000 +0000 +++ glibc-2.8-20080607/configure.in 2008-06-10 01:54:11.000000000 +0000 @@ -100,6 +100,16 @@ [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]) +if test "$prng_device" != "/dev/urandom"; then + AC_DEFINE_UNQUOTED(PRNG_DEV, "$prng_device") +fi + 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@:>@]), diff -Naur glibc-2.8-20080607.orig/manual/arc4random.3 glibc-2.8-20080607/manual/arc4random.3 --- glibc-2.8-20080607.orig/manual/arc4random.3 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.8-20080607/manual/arc4random.3 2008-06-10 01:54:11.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.8-20080607.orig/manual/mkstemps.3 glibc-2.8-20080607/manual/mkstemps.3 --- glibc-2.8-20080607.orig/manual/mkstemps.3 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.8-20080607/manual/mkstemps.3 2008-06-10 01:54:11.000000000 +0000 @@ -0,0 +1,86 @@ +.\" $OpenBSD: mktemp.3,v 1.40 2007/05/10 22:46:36 espie Exp $ +.\" +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. +.\" +.Dd June 4, 1993 +.Dt MKTEMP 3 +.Os +.Sh NAME +.Nm mkstemps +.Nd make temporary file name (unique) +.Sh SYNOPSIS +.Fd #include +.Ft int +.Fn mkstemps "char *template" "int suffixlen" +.Sh DESCRIPTION +.Pp +The +.Fn mkstemps +function acts the same as +.Fn mkstemp , +except it permits a suffix to exist in the template. +The template should be of the form +.Pa /tmp/tmpXXXXXXXXXXsuffix . +.Fn mkstemps +is told the length of the suffix string, i.e., +.Li strlen("suffix") . +.Pp +The +.Fn mkstemps +function return \-1 if no suitable file could be created. +If any call fails, an error code is placed in the global variable +.Va errno . +The +.Fn mkstemps +function may also set +.Va errno +to any value specified by the +.Xr open 2 +function or, +.Bl -tag -width Er +.It Bq Er EINVAL +The suffix length is longer than the template length. +.El +.Sh SEE ALSO +.Xr chmod 2 , +.Xr getpid 2 , +.Xr mkdir 2 , +.Xr open 2 , +.Xr stat 2 , +.Xr tempnam 3 , +.Xr tmpfile 3 , +.Xr tmpnam 3 +.Sh HISTORY +The +.Fn mkstemps +function appeared in +.Ox 2.3 . +.Sh BUGS +The +.Fn mkstemps +function are non-standard and should not be used if portability is required. diff -Naur glibc-2.8-20080607.orig/misc/Makefile glibc-2.8-20080607/misc/Makefile --- glibc-2.8-20080607.orig/misc/Makefile 2007-10-12 21:18:18.000000000 +0000 +++ glibc-2.8-20080607/misc/Makefile 2008-06-10 01:56:51.000000000 +0000 @@ -44,7 +44,7 @@ acct chroot fsync sync fdatasync reboot \ gethostid sethostid \ revoke vhangup \ - swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \ + swapon swapoff mktemp mkstemp mkstemps mkstemp64 mkdtemp \ mkostemp mkostemp64 \ ualarm usleep \ gtty stty \ diff -Naur glibc-2.8-20080607.orig/misc/Versions glibc-2.8-20080607/misc/Versions --- glibc-2.8-20080607.orig/misc/Versions 2007-08-11 02:46:23.000000000 +0000 +++ glibc-2.8-20080607/misc/Versions 2008-06-10 01:54:11.000000000 +0000 @@ -54,7 +54,7 @@ # m* madvise; mkstemp; mktemp; mlock; mlockall; mmap; mount; mprotect; msync; - munlock; munlockall; munmap; + munlock; munlockall; munmap; mkstemps; # o* openlog; diff -Naur glibc-2.8-20080607.orig/misc/mkstemps.c glibc-2.8-20080607/misc/mkstemps.c --- glibc-2.8-20080607.orig/misc/mkstemps.c 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.8-20080607/misc/mkstemps.c 2008-06-10 01:54:11.000000000 +0000 @@ -0,0 +1,116 @@ +/* Copyright (C) 1991, 1992, 1996, 1998, 2004 Free Software Foundation, Inc. + This file is derived from mkstemp.c from 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* From gcc-4.1.2 libiberty. This version uses arc4random(). - ashes */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* We need to provide a type for gcc_uint64_t. */ +#ifdef __GNUC__ +__extension__ typedef unsigned long long gcc_uint64_t; +#else +typedef unsigned long gcc_uint64_t; +#endif + +#ifndef TMP_MAX +#define TMP_MAX 16384 +#endif + +/* + +@deftypefn Replacement int mkstemps (char *@var{pattern}, int @var{suffix_len}) + +Generate a unique temporary file name from @var{pattern}. +@var{pattern} has the form: + +@example + @var{path}/ccXXXXXX@var{suffix} +@end example + +@var{suffix_len} tells us how long @var{suffix} is (it can be zero +length). The last six characters of @var{pattern} before @var{suffix} +must be @samp{XXXXXX}; they are replaced with a string that makes the +filename unique. Returns a file descriptor open on the file for +reading and writing. + +@end deftypefn + +*/ + +int +mkstemps (char *pattern, int suffix_len) +{ + static const char letters[] + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + static gcc_uint64_t value; + char *XXXXXX; + size_t len; + int count; + + len = strlen (pattern); + + if ((int) len < 6 + suffix_len + || strncmp (&pattern[len - 6 - suffix_len], "XXXXXX", 6)) + { + return -1; + } + + XXXXXX = &pattern[len - 6 - suffix_len]; + + value = arc4random(); + + for (count = 0; count < TMP_MAX; ++count) + { + gcc_uint64_t v = value; + int fd; + + /* 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]; + + fd = open (pattern, O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd >= 0) + /* The file does not exist. */ + return fd; + + /* This is a random value. It is only necessary that the next + TMP_MAX values generated by adding 7777 to VALUE are different + with (module 2^32). */ + value += 7777; + } + + /* We return the null string if we can't find a unique file name. */ + pattern[0] = '\0'; + return -1; +} diff -Naur glibc-2.8-20080607.orig/resolv/res_init.c glibc-2.8-20080607/resolv/res_init.c --- glibc-2.8-20080607.orig/resolv/res_init.c 2008-04-07 17:20:25.000000000 +0000 +++ glibc-2.8-20080607/resolv/res_init.c 2008-06-10 01:54:11.000000000 +0000 @@ -568,7 +568,7 @@ u_int res_randomid(void) { - return 0xffff & __getpid(); + return arc4random() & 0xffff; } #ifdef _LIBC libc_hidden_def (__res_randomid) diff -Naur glibc-2.8-20080607.orig/resolv/res_mkquery.c glibc-2.8-20080607/resolv/res_mkquery.c --- glibc-2.8-20080607.orig/resolv/res_mkquery.c 2007-02-09 23:42:17.000000000 +0000 +++ glibc-2.8-20080607/resolv/res_mkquery.c 2008-06-10 01:54:11.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.8-20080607.orig/scripts/data/localplt-i386-linux-gnu.data glibc-2.8-20080607/scripts/data/localplt-i386-linux-gnu.data --- glibc-2.8-20080607.orig/scripts/data/localplt-i386-linux-gnu.data 2006-01-11 21:06:19.000000000 +0000 +++ glibc-2.8-20080607/scripts/data/localplt-i386-linux-gnu.data 2008-06-10 01:54:11.000000000 +0000 @@ -1,7 +1,11 @@ libc.so: _Unwind_Find_FDE +libc.so: arc4random +libc.so: arc4random_stir libc.so: calloc libc.so: free libc.so: malloc libc.so: memalign +libc.so: open +libc.so: puts libc.so: realloc libm.so: matherr diff -Naur glibc-2.8-20080607.orig/stdlib/Makefile glibc-2.8-20080607/stdlib/Makefile --- glibc-2.8-20080607.orig/stdlib/Makefile 2008-03-08 21:31:19.000000000 +0000 +++ glibc-2.8-20080607/stdlib/Makefile 2008-06-10 01:54:11.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.8-20080607.orig/stdlib/Versions glibc-2.8-20080607/stdlib/Versions --- glibc-2.8-20080607.orig/stdlib/Versions 2007-11-13 17:20:49.000000000 +0000 +++ glibc-2.8-20080607/stdlib/Versions 2008-06-10 01:54:11.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.8-20080607.orig/stdlib/arc4random.c glibc-2.8-20080607/stdlib/arc4random.c --- glibc-2.8-20080607.orig/stdlib/arc4random.c 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.8-20080607/stdlib/arc4random.c 2008-06-10 01:54:11.000000000 +0000 @@ -0,0 +1,248 @@ +/* + * 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. November 23, 2007 */ + +#include +#include +#include +#include +#include + +#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; + + /* Start with gettimeofday(). */ + 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) * 23 + 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'. + */ + if (rnd[n] == 0) { + rnd[n] = ((rnd[n - 1] + n) ^ \ + ((__getpid() % 1000) * 7)); + } + } + } else { /* gettimeofday=-1? This should never happen! */ + puts ("gettimeofday() failed. Exiting from arc4random()."); + exit (1); + } + + /* Now try to get some real entropy. */ +#ifdef PRNG_DEV + fd = __open(PRNG_DEV, O_RDONLY, 0); + if (fd != -1) { + /* + * This sizeof(rnd) is divided by two so we only fill half of + * the rnd[] array. This is done in case PRNG_DEV=/dev/zero, or + * the PRNG_DEV device is seriously messed up, so half of the + * array always uses the previous routine. + */ + __read(fd, rnd, sizeof(rnd)/2); + __close(fd); + } else { /* fd=-1? Try again. */ +#endif + fd = __open("/dev/urandom", O_RDONLY, 0); + if (fd != -1) { + __read(fd, rnd, sizeof(rnd)/2); + __close(fd); + } +#ifdef PRNG_DEV + } +#endif + + 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.8-20080607.orig/stdlib/stdlib.h glibc-2.8-20080607/stdlib/stdlib.h --- glibc-2.8-20080607.orig/stdlib/stdlib.h 2007-11-13 17:21:29.000000000 +0000 +++ glibc-2.8-20080607/stdlib/stdlib.h 2008-06-10 01:54:11.000000000 +0000 @@ -459,6 +459,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. */ @@ -612,6 +618,7 @@ Returns TEMPLATE, or a null pointer if it cannot get a unique name. The directory is created mode 700. */ extern char *mkdtemp (char *__template) __THROW __nonnull ((1)) __wur; +extern int mkstemps(char *, int) __THROW __wur; #endif #ifdef __USE_GNU diff -Naur glibc-2.8-20080607.orig/string/strfry.c glibc-2.8-20080607/string/strfry.c --- glibc-2.8-20080607.orig/string/strfry.c 2008-03-31 18:30:11.000000000 +0000 +++ glibc-2.8-20080607/string/strfry.c 2008-06-10 01:54:11.000000000 +0000 @@ -31,7 +31,7 @@ { static char state[32]; rdata.state = NULL; - __initstate_r (time ((time_t *) NULL) ^ getpid (), + __initstate_r (arc4random(), state, sizeof (state), &rdata); init = 1; } diff -Naur glibc-2.8-20080607.orig/sunrpc/bindrsvprt.c glibc-2.8-20080607/sunrpc/bindrsvprt.c --- glibc-2.8-20080607.orig/sunrpc/bindrsvprt.c 2008-01-21 01:35:17.000000000 +0000 +++ glibc-2.8-20080607/sunrpc/bindrsvprt.c 2008-06-10 01:54:11.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.8-20080607.orig/sysdeps/posix/tempname.c glibc-2.8-20080607/sysdeps/posix/tempname.c --- glibc-2.8-20080607.orig/sysdeps/posix/tempname.c 2008-03-30 03:30:25.000000000 +0000 +++ glibc-2.8-20080607/sysdeps/posix/tempname.c 2008-06-10 01:54:11.000000000 +0000 @@ -51,10 +51,6 @@ # include #endif -#if HAVE_SYS_TIME_H || _LIBC -# include -#endif - #if HAVE_STDINT_H || _LIBC # include #endif @@ -93,8 +89,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 @@ -106,25 +100,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 @@ -227,10 +202,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; @@ -260,39 +233,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: diff -Naur glibc-2.8-20080607.orig/sysdeps/unix/sysv/linux/dl-osinfo.h glibc-2.8-20080607/sysdeps/unix/sysv/linux/dl-osinfo.h --- glibc-2.8-20080607.orig/sysdeps/unix/sysv/linux/dl-osinfo.h 2008-04-17 08:32:24.000000000 +0000 +++ glibc-2.8-20080607/sysdeps/unix/sysv/linux/dl-osinfo.h 2008-06-10 01:54:11.000000000 +0000 @@ -64,14 +64,27 @@ { uintptr_t ret; #ifdef ENABLE_STACKGUARD_RANDOMIZE - int fd = __open ("/dev/urandom", O_RDONLY); +# ifdef PRNG_DEV + int fd = __open (PRNG_DEV, O_RDONLY); if (fd >= 0) { ssize_t reslen = __read (fd, &ret, sizeof (ret)); __close (fd); if (reslen == (ssize_t) sizeof (ret)) return ret; + } else { /* fd=-1? Try again. */ +# endif + fd = __open("/dev/urandom", O_RDONLY, 0); + if (fd != -1) + { + ssize_t reslen = __read (fd, &ret, sizeof (ret)); + __close (fd); + if (reslen == (ssize_t) sizeof (ret)) + return ret; + } +# ifdef PRNG_DEV } +# endif #endif ret = 0; unsigned char *p = (unsigned char *) &ret;