http://cvs.fedoraproject.org/viewvc/devel/bash/bash-3.2-rng.patch?view=co https://bugzilla.redhat.com/show_bug.cgi?id=234906 http://cvs.fedoraproject.org/viewvc/devel/bash/bash-3.2-344411.patch?view=co https://bugzilla.redhat.com/show_bug.cgi?id=344411 Use /dev/urandom for $RANDOM. This patch does not break the Korn shell behaviour, where we can initialize $RANDOM ourselves and get the same results each time. /dev/urandom is only opened when $RANDOM is called. Set something else with --with-randomdev=/dev/whatever_random. diff -Naur bash-3.2.orig/config.h.in bash-3.2/config.h.in --- bash-3.2.orig/config.h.in 2006-09-12 20:00:54.000000000 +0000 +++ bash-3.2/config.h.in 2008-10-14 20:44:20.000000000 +0000 @@ -203,6 +203,8 @@ #define DEFAULT_MAIL_DIRECTORY "/usr/spool/mail" +#undef PATH_RANDOMDEV + /* Characteristics of the system's header files and libraries that affect the compilation environment. */ @@ -812,6 +814,10 @@ /* Define if you have the wcwidth function. */ #undef HAVE_WCWIDTH +#undef HAVE_RANDOM + +#undef HAVE_SRANDOM + /* Presence of certain system include files. */ /* Define if you have the header file. */ diff -Naur bash-3.2.orig/configure bash-3.2/configure --- bash-3.2.orig/configure 2006-09-26 15:06:01.000000000 +0000 +++ bash-3.2/configure 2008-10-14 20:44:20.000000000 +0000 @@ -922,6 +922,7 @@ already installed --with-purecov configure to postprocess with pure coverage --with-purify configure to postprocess with purify + --with-randomdev=path use specified random device instead of /dev/urandom --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir @@ -1647,6 +1648,12 @@ opt_purify=$withval fi; +# Check whether --with-random or --without-random was given. +if test "${with_random+set}" = set; then + withval="$with_random" + opt_randomdev=$withval +fi; + if test "$opt_bash_malloc" = yes; then MALLOC_TARGET=malloc MALLOC_SRC=malloc.c @@ -1696,6 +1703,19 @@ DEBUGGER_START_FILE=${ac_default_prefix}/share/bashdb/bashdb-main.inc fi +if test "$opt_randomdev" = yes -o -z "$opt_randomdev"; then + opt_randomdev="/dev/urandom" +elif test "$opt_randomdev" = no; then + opt_randomdev= +fi +if test -n "$opt_randomdev"; then + +cat >>confdefs.h <<_ACEOF +#define PATH_RANDOMDEV "$opt_randomdev" +_ACEOF + +fi + opt_minimal_config=no opt_job_control=yes @@ -12490,6 +12510,110 @@ +for ac_func in random srandom +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + for ac_func in vsnprintf snprintf vasprintf asprintf diff -Naur bash-3.2.orig/configure.in bash-3.2/configure.in --- bash-3.2.orig/configure.in 2006-09-26 15:05:45.000000000 +0000 +++ bash-3.2/configure.in 2008-10-14 20:44:20.000000000 +0000 @@ -111,6 +111,7 @@ AC_ARG_WITH(installed-readline, AC_HELP_STRING([--with-installed-readline], [use a version of the readline library that is already installed]), opt_with_installed_readline=$withval) AC_ARG_WITH(purecov, AC_HELP_STRING([--with-purecov], [configure to postprocess with pure coverage]), opt_purecov=$withval) AC_ARG_WITH(purify, AC_HELP_STRING([--with-purify], [configure to postprocess with purify]), opt_purify=$withval) +AC_ARG_WITH(random, AC_HELP_STRING([--with-randomdev=path], [use specified random device instead of /dev/urandom]), opt_randomdev=$withval) if test "$opt_bash_malloc" = yes; then MALLOC_TARGET=malloc @@ -152,6 +153,15 @@ DEBUGGER_START_FILE=${ac_default_prefix}/share/bashdb/bashdb-main.inc fi +if test "$opt_randomdev" = yes -o -z "$opt_randomdev"; then + opt_randomdev="/dev/urandom" +elif test "$opt_randomdev" = no; then + opt_randomdev= +fi +if test -n "$opt_randomdev"; then + AC_DEFINE_UNQUOTED(PATH_RANDOMDEV, "$opt_randomdev", [Random device path.]) +fi + dnl optional shell features in config.h.in opt_minimal_config=no @@ -708,6 +718,8 @@ setenv setlinebuf setlocale setvbuf siginterrupt strchr \ sysconf tcgetattr times ttyname tzset unsetenv) +AC_CHECK_FUNCS(random srandom) + AC_CHECK_FUNCS(vsnprintf snprintf vasprintf asprintf) AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit) AC_CHECK_FUNCS(getpwent getpwnam getpwuid) diff -Naur bash-3.2.orig/variables.c bash-3.2/variables.c --- bash-3.2.orig/variables.c 2006-09-08 17:33:32.000000000 +0000 +++ bash-3.2/variables.c 2008-10-14 20:44:28.000000000 +0000 @@ -42,6 +42,11 @@ #include "bashansi.h" #include "bashintl.h" +#if defined (PATH_RANDOMDEV) +# include +# include "filecntl.h" +#endif + #include "shell.h" #include "flags.h" #include "execute_cmd.h" @@ -182,7 +187,8 @@ static SHELL_VAR *init_seconds_var __P((void)); static int brand __P((void)); -static void sbrand __P((unsigned long)); /* set bash random number generator. */ +static void sbrand __P((unsigned int)); /* set bash random number generator. */ +static void seed_random __P((void)); /* seed the generator randomly */ static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t)); static SHELL_VAR *get_random __P((SHELL_VAR *)); @@ -494,9 +500,6 @@ } #endif /* HISTORY */ - /* Seed the random number generator. */ - sbrand (dollar_dollar_pid + shell_start_time); - /* Handle some "special" variables that we may have inherited from a parent shell. */ if (interactive_shell) @@ -1143,9 +1146,11 @@ } /* The random number seed. You can change this by setting RANDOM. */ +#if !defined (HAVE_RANDOM) static unsigned long rseed = 1; +#endif static int last_random_value; -static int seeded_subshell = 0; +static int seeded_subshell = -1; /* A linear congruential random number generator based on the example one in the ANSI C standard. This one isn't very good, but a more @@ -1155,28 +1160,58 @@ static int brand () { +#if defined (HAVE_RANDOM) + unsigned int rseed; + rseed = random(); +#else rseed = rseed * 1103515245 + 12345; +#endif return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */ } /* Set the random number generator seed to SEED. */ static void sbrand (seed) - unsigned long seed; + unsigned int seed; { +#if defined (HAVE_RANDOM) + srandom((unsigned int)seed); +#else rseed = seed; +#endif last_random_value = 0; } +static void +seed_random () +{ + unsigned int seed; +#if defined (PATH_RANDOMDEV) + int fd; + int rv; + if ((rv = fd = open (PATH_RANDOMDEV, O_RDONLY)) != -1) { + while ((rv = read(fd, &seed, sizeof(seed))) != sizeof(seed) && errno == EINTR); + close (fd); + } + if (rv != sizeof(seed)) { +#endif + struct timeval tv; + gettimeofday(&tv, NULL); + seed = (unsigned int)tv.tv_sec + (unsigned int)tv.tv_usec + getpid(); +#if defined (PATH_RANDOMDEV) + } +#endif + sbrand (seed); +} + static SHELL_VAR * assign_random (self, value, unused) SHELL_VAR *self; char *value; arrayind_t unused; { - sbrand (strtoul (value, (char **)NULL, 10)); - if (subshell_environment) - seeded_subshell = 1; + sbrand ((unsigned int)strtoul (value, (char **)NULL, 10)); + seeded_subshell = getpid(); return (self); } @@ -1186,10 +1221,10 @@ int rv; /* Reset for command and process substitution. */ - if (subshell_environment && seeded_subshell == 0) + if (seeded_subshell != getpid()) { - sbrand (rseed + getpid() + NOW); - seeded_subshell = 1; + seed_random (); + seeded_subshell = getpid(); } do