Skip to content

Commit 95309d6

Browse files
committed
add build options to disable the PERL_HASH* and PERL_PERTURB_KEYS env vars
These variables either control or reveal information used in perl's hash implementation that a careful user may not want controlled or exposed.
1 parent 33874d2 commit 95309d6

File tree

4 files changed

+97
-71
lines changed

4 files changed

+97
-71
lines changed

INSTALL

+7
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,13 @@ See L<perlrun/PERL_HASH_SEED> and L<perlrun/PERL_PERTURB_KEYS> for
423423
details on the environment variables, and L<perlsec/Algorithmic
424424
Complexity Attacks> for further security details.
425425

426+
The C<PERL_HASH_SEED> and PERL_PERTURB_KEYS> environment variables can
427+
be disabled by building configuring perl with
428+
C<-Accflags=-DNO_PERL_HASH_ENV>.
429+
430+
The C<PERL_HASH_SEED_DEBUG> environment variable can be disabled by
431+
configuring perl with C<-Accflags=-DNO_PERL_HASH_SEED_DEBUG>.
432+
426433
=head3 SOCKS
427434

428435
Perl can be configured to be 'socksified', that is, to use the SOCKS

perl.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
15371537
#ifndef MULTIPLICITY
15381538
PERL_UNUSED_ARG(my_perl);
15391539
#endif
1540-
#if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) || defined(USE_HASH_SEED_DEBUG)
1540+
#if (defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) || defined(USE_HASH_SEED_DEBUG)) && !defined(NO_PERL_HASH_SEED_DEBUG)
15411541
{
15421542
const char * const s = PerlEnv_getenv("PERL_HASH_SEED_DEBUG");
15431543

@@ -1556,7 +1556,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
15561556
PerlIO_printf(Perl_debug_log, "\n");
15571557
}
15581558
}
1559-
#endif /* #if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) */
1559+
#endif /* #if (defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) ... */
15601560

15611561
#ifdef __amigaos4__
15621562
{

t/run/runenv.t

+79-66
Original file line numberDiff line numberDiff line change
@@ -204,74 +204,87 @@ try({PERL5LIB => "foo",
204204
'',
205205
'');
206206

207-
try({PERL_HASH_SEED_DEBUG => 1},
208-
['-e','1'],
209-
'',
210-
qr/HASH_FUNCTION =/);
211-
212-
try({PERL_HASH_SEED_DEBUG => 1},
213-
['-e','1'],
214-
'',
215-
qr/HASH_SEED =/);
216-
217-
# special case, seed "0" implies disabled hash key traversal randomization
218-
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0"},
219-
['-e','1'],
220-
'',
221-
qr/PERTURB_KEYS = 0/);
222-
223-
# check that setting it to a different value with the same logical value
224-
# triggers the normal "deterministic mode".
225-
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0x0"},
226-
['-e','1'],
227-
'',
228-
qr/PERTURB_KEYS = 2/);
229-
230-
try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "0"},
231-
['-e','1'],
232-
'',
233-
qr/PERTURB_KEYS = 0/);
234-
235-
try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "1"},
236-
['-e','1'],
237-
'',
238-
qr/PERTURB_KEYS = 1/);
239-
240-
try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "2"},
241-
['-e','1'],
242-
'',
243-
qr/PERTURB_KEYS = 2/);
244-
245-
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12345678"},
246-
['-e','1'],
247-
'',
248-
qr/HASH_SEED = 0x12345678/);
249-
250-
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12"},
251-
['-e','1'],
252-
'',
253-
qr/HASH_SEED = 0x12000000/);
207+
SKIP:
208+
{
209+
skip "NO_PERL_HASH_SEED_DEBUG set", 4
210+
if $Config{ccflags} =~ /-DNO_PERL_HASH_SEED_DEBUG\b/;
211+
212+
try({PERL_HASH_SEED_DEBUG => 1},
213+
['-e','1'],
214+
'',
215+
qr/HASH_FUNCTION =/);
216+
217+
try({PERL_HASH_SEED_DEBUG => 1},
218+
['-e','1'],
219+
'',
220+
qr/HASH_SEED =/);
221+
}
254222

255-
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "123456789"},
256-
['-e','1'],
257-
'',
258-
qr/HASH_SEED = 0x12345678/);
259-
260-
# Test that PERL_PERTURB_KEYS works as expected. We check that we get the same
261-
# results if we use PERL_PERTURB_KEYS = 0 or 2 and we reuse the seed from previous run.
262-
my @print_keys = ( '-e', '@_{"A".."Z"}=(); print keys %_');
263-
for my $mode ( 0,1, 2 ) { # disabled and deterministic respectively
264-
my %base_opts = ( PERL_PERTURB_KEYS => $mode, PERL_HASH_SEED_DEBUG => 1 ),
265-
my ($out, $err) = runperl_and_capture( { %base_opts }, [ @print_keys ]);
266-
if ($err=~/HASH_SEED = (0x[a-f0-9]+)/) {
267-
my $seed = $1;
268-
my($out2, $err2) = runperl_and_capture( { %base_opts, PERL_HASH_SEED => $seed }, [ @print_keys ]);
269-
if ( $mode == 1 ) {
270-
isnt ($out,$out2,"PERL_PERTURB_KEYS = $mode results in different key order with the same key");
271-
} else {
272-
is ($out,$out2,"PERL_PERTURB_KEYS = $mode allows one to recreate a random hash");
223+
SKIP:
224+
{
225+
skip "NO_PERL_HASH_ENV or NO_PERL_HASH_SEED_DEBUG set", 16
226+
if $Config{ccflags} =~ /-DNO_PERL_HASH_ENV\b/ ||
227+
$Config{ccflags} =~ /-DNO_PERL_HASH_SEED_DEBUG\b/;
228+
229+
# special case, seed "0" implies disabled hash key traversal randomization
230+
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0"},
231+
['-e','1'],
232+
'',
233+
qr/PERTURB_KEYS = 0/);
234+
235+
# check that setting it to a different value with the same logical value
236+
# triggers the normal "deterministic mode".
237+
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "0x0"},
238+
['-e','1'],
239+
'',
240+
qr/PERTURB_KEYS = 2/);
241+
242+
try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "0"},
243+
['-e','1'],
244+
'',
245+
qr/PERTURB_KEYS = 0/);
246+
247+
try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "1"},
248+
['-e','1'],
249+
'',
250+
qr/PERTURB_KEYS = 1/);
251+
252+
try({PERL_HASH_SEED_DEBUG => 1, PERL_PERTURB_KEYS => "2"},
253+
['-e','1'],
254+
'',
255+
qr/PERTURB_KEYS = 2/);
256+
257+
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12345678"},
258+
['-e','1'],
259+
'',
260+
qr/HASH_SEED = 0x12345678/);
261+
262+
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "12"},
263+
['-e','1'],
264+
'',
265+
qr/HASH_SEED = 0x12000000/);
266+
267+
try({PERL_HASH_SEED_DEBUG => 1, PERL_HASH_SEED => "123456789"},
268+
['-e','1'],
269+
'',
270+
qr/HASH_SEED = 0x12345678/);
271+
272+
# Test that PERL_PERTURB_KEYS works as expected. We check that we get the same
273+
# results if we use PERL_PERTURB_KEYS = 0 or 2 and we reuse the seed from previous run.
274+
my @print_keys = ( '-e', '@_{"A".."Z"}=(); print keys %_');
275+
for my $mode ( 0,1, 2 ) { # disabled and deterministic respectively
276+
my %base_opts = ( PERL_PERTURB_KEYS => $mode, PERL_HASH_SEED_DEBUG => 1 ),
277+
my ($out, $err) = runperl_and_capture( { %base_opts }, [ @print_keys ]);
278+
if ($err=~/HASH_SEED = (0x[a-f0-9]+)/) {
279+
my $seed = $1;
280+
my($out2, $err2) = runperl_and_capture( { %base_opts, PERL_HASH_SEED => $seed }, [ @print_keys ]);
281+
if ( $mode == 1 ) {
282+
isnt ($out,$out2,"PERL_PERTURB_KEYS = $mode results in different key order with the same key");
283+
} else {
284+
is ($out,$out2,"PERL_PERTURB_KEYS = $mode allows one to recreate a random hash");
285+
}
286+
is ($err,$err2,"Got the same debug output when we set PERL_HASH_SEED and PERL_PERTURB_KEYS");
273287
}
274-
is ($err,$err2,"Got the same debug output when we set PERL_HASH_SEED and PERL_PERTURB_KEYS");
275288
}
276289
}
277290

util.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -4712,28 +4712,31 @@ Perl_seed(pTHX)
47124712
void
47134713
Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
47144714
{
4715+
#ifndef NO_PERL_HASH_ENV
47154716
const char *env_pv;
4717+
#endif
47164718
unsigned long i;
47174719

47184720
PERL_ARGS_ASSERT_GET_HASH_SEED;
47194721

4722+
#ifndef NO_PERL_HASH_ENV
47204723
env_pv= PerlEnv_getenv("PERL_HASH_SEED");
47214724

47224725
if ( env_pv )
4723-
#ifndef USE_HASH_SEED_EXPLICIT
4726+
# ifndef USE_HASH_SEED_EXPLICIT
47244727
{
47254728
/* ignore leading spaces */
47264729
while (isSPACE(*env_pv))
47274730
env_pv++;
4728-
#ifdef USE_PERL_PERTURB_KEYS
4731+
# ifdef USE_PERL_PERTURB_KEYS
47294732
/* if they set it to "0" we disable key traversal randomization completely */
47304733
if (strEQ(env_pv,"0")) {
47314734
PL_hash_rand_bits_enabled= 0;
47324735
} else {
47334736
/* otherwise switch to deterministic mode */
47344737
PL_hash_rand_bits_enabled= 2;
47354738
}
4736-
#endif
4739+
# endif
47374740
/* ignore a leading 0x... if it is there */
47384741
if (env_pv[0] == '0' && env_pv[1] == 'x')
47394742
env_pv += 2;
@@ -4755,6 +4758,7 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
47554758
/* should we warn about insufficient hex? */
47564759
}
47574760
else
4761+
# endif
47584762
#endif
47594763
{
47604764
(void)seedDrand01((Rand_seed_t)seed());
@@ -4774,6 +4778,7 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
47744778
PL_hash_rand_bits = ROTL_UV(PL_hash_rand_bits,8);
47754779
}
47764780
}
4781+
# ifndef NO_PERL_HASH_ENV
47774782
env_pv= PerlEnv_getenv("PERL_PERTURB_KEYS");
47784783
if (env_pv) {
47794784
if (strEQ(env_pv,"0") || strEQ(env_pv,"NO")) {
@@ -4786,6 +4791,7 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
47864791
Perl_warn(aTHX_ "perl: warning: strange setting in '$ENV{PERL_PERTURB_KEYS}': '%s'\n", env_pv);
47874792
}
47884793
}
4794+
# endif
47894795
#endif
47904796
}
47914797

0 commit comments

Comments
 (0)