ash,hush: fix $RANDOM in children being repeated
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 12 Oct 2009 13:25:01 +0000 (15:25 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 12 Oct 2009 13:25:01 +0000 (15:25 +0200)
function                                             old     new   delta
next_random                                           46      68     +22
forkshell                                            248     263     +15
expand_vars_to_list                                 2118    2131     +13
run_pipe                                            1775    1782      +7
popstring                                            134     140      +6
builtin_umask                                        123     121      -2
ash_main                                            1356    1336     -20
get_local_var_value                                  125     104     -21
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/3 up/down: 63/-43)             Total: 20 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c
shell/hush.c
shell/math.c
shell/random.c
shell/random.h

index cc2677126ece2d9fe5748810a5439f9b9dfae961..d81dbd3f5c1985de192cd48c69721a80d01e353e 100644 (file)
@@ -4725,10 +4725,12 @@ forkshell(struct job *jp, union node *n, int mode)
                        freejob(jp);
                ash_msg_and_raise_error("can't fork");
        }
-       if (pid == 0)
+       if (pid == 0) {
+               CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
                forkchild(jp, n, mode);
-       else
+       } else {
                forkparent(jp, n, mode, pid);
+       }
        return pid;
 }
 
@@ -10079,12 +10081,6 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 static void FAST_FUNC
 change_random(const char *value)
 {
-       /* Galois LFSR parameter */
-       /* Taps at 32 31 29 1: */
-       enum { MASK = 0x8000000b };
-       /* Another example - taps at 32 31 30 10: */
-       /* MASK = 0x00400007 */
-
        uint32_t t;
 
        if (value == NULL) {
@@ -13268,11 +13264,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
 #endif
        rootpid = getpid();
 
-#if ENABLE_ASH_RANDOM_SUPPORT
-       /* Can use monotonic_ns() for better randomness but for now it is
-        * not used anywhere else in busybox... so avoid bloat */
-       INIT_RANDOM_T(&random_gen, rootpid, monotonic_us());
-#endif
        init();
        setstackmark(&smark);
        procargs(argv);
index d105029ffb15295b1482447fc212f3a9be137ecf..21f3edcaca35feed079c49c9ab2542e96509ab74 100644 (file)
@@ -88,6 +88,8 @@
 #include "match.h"
 #if ENABLE_HUSH_RANDOM_SUPPORT
 # include "random.h"
+#else
+# define CLEAR_RANDOM_T(rnd) ((void)0)
 #endif
 #ifndef PIPE_BUF
 # define PIPE_BUF 4096  /* amount of buffering in a pipe */
@@ -1319,8 +1321,6 @@ static const char *get_local_var_value(const char *name)
        // bash compat: UID? EUID?
 #if ENABLE_HUSH_RANDOM_SUPPORT
        if (strcmp(name, "RANDOM") == 0) {
-               if (G.random_gen.galois_LFSR == 0)
-                       INIT_RANDOM_T(&G.random_gen, G.root_pid, monotonic_us());
                return utoa(next_random(&G.random_gen));
        }
 #endif
@@ -4000,6 +4000,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
                if (!command->pid) { /* child */
 #if ENABLE_HUSH_JOB
                        disable_restore_tty_pgrp_on_exit();
+                       CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
 
                        /* Every child adds itself to new process group
                         * with pgid == pid_of_first_child_in_pipe */
@@ -5207,6 +5208,7 @@ static FILE *generate_stream_from_string(const char *s)
                        + (1 << SIGTTIN)
                        + (1 << SIGTTOU)
                        , SIG_IGN);
+               CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
                close(channel[0]); /* NB: close _first_, then move fd! */
                xmove_fd(channel[1], 1);
                /* Prevent it from trying to handle ctrl-z etc */
index 3791b84bcd68cf68114ff081bf7bd4727bd746c7..fc20def628da43deebd1d1f62b3645daeba89d1b 100644 (file)
@@ -258,7 +258,7 @@ static int
 arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks)
 {
        if (t->var) {
-               const char * p = lookupvar(t->var);
+               const char *p = lookupvar(t->var);
 
                if (p) {
                        int errcode;
index cca9d120dfcaee290a97a95c319d68d2da6785f4..7f5821cbcca21f672134fc3fc0ef6b585164f83a 100644 (file)
@@ -20,6 +20,13 @@ next_random(random_t *rnd)
 
        uint32_t t;
 
+       if (UNINITED_RANDOM_T(rnd)) {
+               /* Can use monotonic_ns() for better randomness but for now
+                * it is not used anywhere else in busybox... so avoid bloat
+                */
+               INIT_RANDOM_T(rnd, getpid(), monotonic_us());
+       }
+
        /* LCG has period of 2^32 and alternating lowest bit */
        rnd->LCG = 1664525 * rnd->LCG + 1013904223;
        /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
index 8667e1c99b884368b906aad18cf4bc8e6cb6e549..e22a2e88b53ffca49984c924d6d83772d9c7a8d1 100644 (file)
@@ -13,7 +13,13 @@ typedef struct random_t {
        uint32_t LCG;        /* LCG (fast but weak) */
 } random_t;
 
+#define UNINITED_RANDOM_T(rnd) \
+       ((rnd)->galois_LFSR == 0)
+
 #define INIT_RANDOM_T(rnd, nonzero, v) \
        ((rnd)->galois_LFSR = (nonzero), (rnd)->LCG = (v))
 
+#define CLEAR_RANDOM_T(rnd) \
+       ((rnd)->galois_LFSR = 0)
+
 uint32_t next_random(random_t *rnd) FAST_FUNC;