add build options to disable the PERL_HASH* and PERL_PERTURB_KEYS env vars
authorTony Cook <tony@develop-help.com>
Thu, 8 Dec 2016 03:14:11 +0000 (14:14 +1100)
committerTony Cook <tony@develop-help.com>
Sun, 8 Jan 2017 23:12:24 +0000 (10:12 +1100)
These variables either control or reveal information used in perl's
hash implementation that a careful user may not want controlled or
exposed.

INSTALL
perl.c
t/run/runenv.t
util.c

diff --git a/INSTALL b/INSTALL
index ad6aea9..c668af0 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -423,6 +423,13 @@ See L<perlrun/PERL_HASH_SEED> and L<perlrun/PERL_PERTURB_KEYS> for
 details on the environment variables, and L<perlsec/Algorithmic
 Complexity Attacks> for further security details.
 
+The C<PERL_HASH_SEED> and PERL_PERTURB_KEYS> environment variables can
+be disabled by building configuring perl with
+C<-Accflags=-DNO_PERL_HASH_ENV>.
+
+The C<PERL_HASH_SEED_DEBUG> environment variable can be disabled by
+configuring perl with C<-Accflags=-DNO_PERL_HASH_SEED_DEBUG>.
+
 =head3 SOCKS
 
 Perl can be configured to be 'socksified', that is, to use the SOCKS
diff --git a/perl.c b/perl.c
index 37335a4..09eb2f4 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -1537,7 +1537,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
 #ifndef MULTIPLICITY
     PERL_UNUSED_ARG(my_perl);
 #endif
-#if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) || defined(USE_HASH_SEED_DEBUG)
+#if (defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) || defined(USE_HASH_SEED_DEBUG)) && !defined(NO_PERL_HASH_SEED_DEBUG)
     {
         const char * const s = PerlEnv_getenv("PERL_HASH_SEED_DEBUG");
 
@@ -1556,7 +1556,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
             PerlIO_printf(Perl_debug_log, "\n");
         }
     }
-#endif /* #if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) */
+#endif /* #if (defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) ... */
 
 #ifdef __amigaos4__
     {
index 6f235d2..611e012 100644 (file)
@@ -204,74 +204,87 @@ try({PERL5LIB => "foo",
     '',
     '');
 
-try({PERL_HASH_SEED_DEBUG => 1},
-    ['-e','1'],
-    '',
-    qr/HASH_FUNCTION =/);
-
-try({PERL_HASH_SEED_DEBUG => 1},
-    ['-e','1'],
-    '',
-    qr/HASH_SEED =/);
-
-# special case, seed "0" implies disabled hash key traversal randomization
-try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0"},
-    ['-e','1'],
-    '',
-    qr/PERTURB_KEYS = 0/);
-
-# check that setting it to a different value with the same logical value
-# triggers the normal "deterministic mode".
-try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0x0"},
-    ['-e','1'],
-    '',
-    qr/PERTURB_KEYS = 2/);
-
-try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "0"},
-    ['-e','1'],
-    '',
-    qr/PERTURB_KEYS = 0/);
-
-try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "1"},
-    ['-e','1'],
-    '',
-    qr/PERTURB_KEYS = 1/);
-
-try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "2"},
-    ['-e','1'],
-    '',
-    qr/PERTURB_KEYS = 2/);
-
-try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12345678"},
-    ['-e','1'],
-    '',
-    qr/HASH_SEED = 0x12345678/);
-
-try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12"},
-    ['-e','1'],
-    '',
-    qr/HASH_SEED = 0x12000000/);
+SKIP:
+{
+    skip "NO_PERL_HASH_SEED_DEBUG set", 4
+      if $Config{ccflags} =~ /-DNO_PERL_HASH_SEED_DEBUG\b/;
+
+    try({PERL_HASH_SEED_DEBUG => 1},
+        ['-e','1'],
+        '',
+        qr/HASH_FUNCTION =/);
+
+    try({PERL_HASH_SEED_DEBUG => 1},
+        ['-e','1'],
+        '',
+        qr/HASH_SEED =/);
+}
 
-try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "123456789"},
-    ['-e','1'],
-    '',
-    qr/HASH_SEED = 0x12345678/);
-
-# Test that PERL_PERTURB_KEYS works as expected.  We check that we get the same
-# results if we use PERL_PERTURB_KEYS = 0 or 2 and we reuse the seed from previous run.
-my @print_keys = ( '-e', '@_{"A".."Z"}=(); print keys %_');
-for my $mode ( 0,1, 2 ) { # disabled and deterministic respectively
-    my %base_opts = ( PERL_PERTURB_KEYS => $mode, PERL_HASH_SEED_DEBUG => 1 ),
-    my ($out, $err) = runperl_and_capture( { %base_opts }, [ @print_keys ]);
-    if ($err=~/HASH_SEED = (0x[a-f0-9]+)/) {
-        my $seed = $1;
-        my($out2, $err2) = runperl_and_capture( { %base_opts, PERL_HASH_SEED => $seed }, [ @print_keys ]);
-        if ( $mode == 1 ) {
-            isnt ($out,$out2,"PERL_PERTURB_KEYS = $mode results in different key order with the same key");
-        } else {
-            is ($out,$out2,"PERL_PERTURB_KEYS = $mode allows one to recreate a random hash");
+SKIP:
+{
+    skip "NO_PERL_HASH_ENV or NO_PERL_HASH_SEED_DEBUG set", 16
+      if $Config{ccflags} =~ /-DNO_PERL_HASH_ENV\b/ ||
+         $Config{ccflags} =~ /-DNO_PERL_HASH_SEED_DEBUG\b/;
+
+    # special case, seed "0" implies disabled hash key traversal randomization
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0"},
+        ['-e','1'],
+        '',
+        qr/PERTURB_KEYS = 0/);
+
+    # check that setting it to a different value with the same logical value
+    # triggers the normal "deterministic mode".
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0x0"},
+        ['-e','1'],
+        '',
+        qr/PERTURB_KEYS = 2/);
+
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "0"},
+        ['-e','1'],
+        '',
+        qr/PERTURB_KEYS = 0/);
+
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "1"},
+        ['-e','1'],
+        '',
+        qr/PERTURB_KEYS = 1/);
+
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "2"},
+        ['-e','1'],
+        '',
+        qr/PERTURB_KEYS = 2/);
+
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12345678"},
+        ['-e','1'],
+        '',
+        qr/HASH_SEED = 0x12345678/);
+
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12"},
+        ['-e','1'],
+        '',
+        qr/HASH_SEED = 0x12000000/);
+
+    try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "123456789"},
+        ['-e','1'],
+        '',
+        qr/HASH_SEED = 0x12345678/);
+
+    # Test that PERL_PERTURB_KEYS works as expected.  We check that we get the same
+    # results if we use PERL_PERTURB_KEYS = 0 or 2 and we reuse the seed from previous run.
+    my @print_keys = ( '-e', '@_{"A".."Z"}=(); print keys %_');
+    for my $mode ( 0,1, 2 ) { # disabled and deterministic respectively
+        my %base_opts = ( PERL_PERTURB_KEYS => $mode, PERL_HASH_SEED_DEBUG => 1 ),
+          my ($out, $err) = runperl_and_capture( { %base_opts }, [ @print_keys ]);
+        if ($err=~/HASH_SEED = (0x[a-f0-9]+)/) {
+            my $seed = $1;
+            my($out2, $err2) = runperl_and_capture( { %base_opts, PERL_HASH_SEED => $seed }, [ @print_keys ]);
+            if ( $mode == 1 ) {
+                isnt ($out,$out2,"PERL_PERTURB_KEYS = $mode results in different key order with the same key");
+            } else {
+                is ($out,$out2,"PERL_PERTURB_KEYS = $mode allows one to recreate a random hash");
+            }
+            is ($err,$err2,"Got the same debug output when we set PERL_HASH_SEED and PERL_PERTURB_KEYS");
         }
-        is ($err,$err2,"Got the same debug output when we set PERL_HASH_SEED and PERL_PERTURB_KEYS");
     }
 }
 
diff --git a/util.c b/util.c
index 02c84c8..a1306c6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -4712,20 +4712,23 @@ Perl_seed(pTHX)
 void
 Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
 {
+#ifndef NO_PERL_HASH_ENV
     const char *env_pv;
+#endif
     unsigned long i;
 
     PERL_ARGS_ASSERT_GET_HASH_SEED;
 
+#ifndef NO_PERL_HASH_ENV
     env_pv= PerlEnv_getenv("PERL_HASH_SEED");
 
     if ( env_pv )
-#ifndef USE_HASH_SEED_EXPLICIT
+#  ifndef USE_HASH_SEED_EXPLICIT
     {
         /* ignore leading spaces */
         while (isSPACE(*env_pv))
             env_pv++;
-#ifdef USE_PERL_PERTURB_KEYS
+#    ifdef USE_PERL_PERTURB_KEYS
         /* if they set it to "0" we disable key traversal randomization completely */
         if (strEQ(env_pv,"0")) {
             PL_hash_rand_bits_enabled= 0;
@@ -4733,7 +4736,7 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
             /* otherwise switch to deterministic mode */
             PL_hash_rand_bits_enabled= 2;
         }
-#endif
+#    endif
         /* ignore a leading 0x... if it is there */
         if (env_pv[0] == '0' && env_pv[1] == 'x')
             env_pv += 2;
@@ -4755,6 +4758,7 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
         /* should we warn about insufficient hex? */
     }
     else
+#  endif
 #endif
     {
         (void)seedDrand01((Rand_seed_t)seed());
@@ -4774,6 +4778,7 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
             PL_hash_rand_bits = ROTL_UV(PL_hash_rand_bits,8);
         }
     }
+#  ifndef NO_PERL_HASH_ENV
     env_pv= PerlEnv_getenv("PERL_PERTURB_KEYS");
     if (env_pv) {
         if (strEQ(env_pv,"0") || strEQ(env_pv,"NO")) {
@@ -4786,6 +4791,7 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
             Perl_warn(aTHX_ "perl: warning: strange setting in '$ENV{PERL_PERTURB_KEYS}': '%s'\n", env_pv);
         }
     }
+#  endif
 #endif
 }