Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

heap-buffer-overflow Perl_vivify_ref (pp_hot.c:4362) #15762

Open
p5pRT opened this issue Dec 11, 2016 · 6 comments
Open

heap-buffer-overflow Perl_vivify_ref (pp_hot.c:4362) #15762

p5pRT opened this issue Dec 11, 2016 · 6 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 11, 2016

Migrated from rt.perl.org#130321 (status was 'open')

Searchable as RT130321$

@p5pRT
Copy link
Author

p5pRT commented Dec 11, 2016

From @geeknik

Triggered with Perl v5.25.7-98-gdf13534 while fuzzing with AFL. However, it
doesn't always crash like this. Sometimes it is a simple null pointer deref
@​ Perl_vivify_ref /root/perl/pp_hot.c​:4362, sometimes it's an assertion
failure @​ Perl_sv_clear (sv.c​:6540), but running it multiple times in a row
can trigger the buffer overflow.

perl -e 'map$$_=0,%$T=%​::'

==14745==ERROR​: AddressSanitizer​: heap-buffer-overflow on address
0x6210000114f0 at pc 0x0000008ac879 bp 0x7ffc728d4e80 sp 0x7ffc728d4e78
READ of size 8 at 0x6210000114f0 thread T0
  #0 0x8ac878 in Perl_vivify_ref /root/perl/pp_hot.c​:4362​:2
  #1 0x9aeb55 in Perl_pp_rv2sv /root/perl/pp.c​:404​:11
  #2 0x7f81fb in Perl_runops_debug /root/perl/dump.c​:2260​:23
  #3 0x5a0ab3 in S_run_body /root/perl/perl.c​:2526​:2
  #4 0x5a0ab3 in perl_run /root/perl/perl.c​:2449
  #5 0x4de6dd in main /root/perl/perlmain.c​:123​:9
  #6 0x7fced94dbb44 in __libc_start_main
/build/glibc-daoqzt/glibc-2.19/csu/libc-start.c​:287
  #7 0x4de34c in _start (/root/perl/perl+0x4de34c)

0x6210000114f0 is located 0 bytes to the right of 4080-byte region
[0x621000010500,0x6210000114f0)
allocated by thread T0 here​:
  #0 0x4c0ccb in malloc (/root/perl/perl+0x4c0ccb)
  #1 0x7fc067 in Perl_safesysmalloc /root/perl/util.c​:153​:21

SUMMARY​: AddressSanitizer​: heap-buffer-overflow /root/perl/pp_hot.c​:4362
Perl_vivify_ref
Shadow bytes around the buggy address​:
  0x0c427fffa240​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffa250​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffa260​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffa270​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffa280​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c427fffa290​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa
  0x0c427fffa2a0​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffa2b0​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffa2c0​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffa2d0​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffa2e0​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes)​:
  Addressable​: 00
  Partially addressable​: 01 02 03 04 05 06 07
  Heap left redzone​: fa
  Heap right redzone​: fb
  Freed heap region​: fd
  Stack left redzone​: f1
  Stack mid redzone​: f2
  Stack right redzone​: f3
  Stack partial redzone​: f4
  Stack after return​: f5
  Stack use after scope​: f8
  Global redzone​: f9
  Global init order​: f6
  Poisoned by user​: f7
  Container overflow​: fc
  ASan internal​: fe
==14745==ABORTING

Perl 5.20.2 fails like so​:
==20640== Invalid read of size 1
==20640== at 0x4F0DA54​: ??? (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F0DBBD​: Perl_sv_unmagic (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F0C7DE​: Perl_sv_clear (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F0D289​: Perl_sv_free2 (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F3943C​: Perl_pp_mapwhile (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4EFB055​: Perl_runops_standard (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4E8B73D​: perl_run (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x400E18​: main (in /usr/bin/perl)
==20640== Address 0xff00000012 is not stack'd, malloc'd or (recently)
free'd
==20640==
==20640==
==20640== Process terminating with default action of signal 11 (SIGSEGV)
==20640== Access not within mapped region at address 0xFF00000012
==20640== at 0x4F0DA54​: ??? (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F0DBBD​: Perl_sv_unmagic (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F0C7DE​: Perl_sv_clear (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F0D289​: Perl_sv_free2 (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4F3943C​: Perl_pp_mapwhile (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4EFB055​: Perl_runops_standard (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x4E8B73D​: perl_run (in
/usr/lib/x86_64-linux-gnu/libperl.so.5.20.2)
==20640== by 0x400E18​: main (in /usr/bin/perl)
==20640== If you believe this happened as a result of a stack
==20640== overflow in your program's main thread (unlikely but
==20640== possible), you can try to increase the size of the
==20640== main thread stack using the --main-stacksize= flag.
==20640== The main thread stack size used in this run was 8388608.
Segmentation fault

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2016

From @tonycoz

On Sun, 11 Dec 2016 14​:18​:44 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-98-gdf13534 while fuzzing with AFL. However, it
doesn't always crash like this. Sometimes it is a simple null pointer deref
@​ Perl_vivify_ref /root/perl/pp_hot.c​:4362, sometimes it's an assertion
failure @​ Perl_sv_clear (sv.c​:6540), but running it multiple times in a row
can trigger the buffer overflow.

perl -e 'map$$_=0,%$T=%​::'

This looks like another stack-not-refcounted bug.

Tony

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2016

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 31, 2017

From @tonycoz

On Tue, 13 Dec 2016 21​:11​:01 -0800, tonyc wrote​:

On Sun, 11 Dec 2016 14​:18​:44 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-98-gdf13534 while fuzzing with AFL.
However, it
doesn't always crash like this. Sometimes it is a simple null pointer
deref
@​ Perl_vivify_ref /root/perl/pp_hot.c​:4362, sometimes it's an
assertion
failure @​ Perl_sv_clear (sv.c​:6540), but running it multiple times in
a row
can trigger the buffer overflow.

perl -e 'map$$_=0,%$T=%​::'

This looks like another stack-not-refcounted bug.

I can't reproduce the buffer overflow.

The random behaviour is caused by hash randomization, so if you can still reproduce it, can you provide the hash seed where it occurs? Like this​:

  PERL_HASH_SEED_DEBUG=1 ./perl -e 'map$$_=0,%$T=%​::'

You'll get something like​:

HASH_FUNCTION = HYBRID_OAATHU_SIPHASH_1_3 HASH_SEED = 0x9c21037e507a4e690fc406e7d29b44b960076c875b6852f8 PERTURB_KEYS = 1 (RANDOM)

which in my case produced​:

perl​: sv.c​:6547​: Perl_sv_clear​: Assertion `((svtype)((sv)->sv_flags & 0xff)) != (svtype)0xff' failed.
Aborted

Tony

@p5pRT
Copy link
Author

p5pRT commented Feb 20, 2017

From @iabyn

On Tue, Jan 31, 2017 at 03​:23​:20PM -0800, Tony Cook via RT wrote​:

On Tue, 13 Dec 2016 21​:11​:01 -0800, tonyc wrote​:

On Sun, 11 Dec 2016 14​:18​:44 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-98-gdf13534 while fuzzing with AFL.
However, it
doesn't always crash like this. Sometimes it is a simple null pointer
deref
@​ Perl_vivify_ref /root/perl/pp_hot.c​:4362, sometimes it's an
assertion
failure @​ Perl_sv_clear (sv.c​:6540), but running it multiple times in
a row
can trigger the buffer overflow.

perl -e 'map$$_=0,%$T=%​::'

This looks like another stack-not-refcounted bug.

I can't reproduce the buffer overflow.

The random behaviour is caused by hash randomization, so if you can still reproduce it, can you provide the hash seed where it occurs? Like this​:

PERL_HASH_SEED_DEBUG=1 ./perl -e 'map$$_=0,%$T=%​::'

You'll get something like​:

HASH_FUNCTION = HYBRID_OAATHU_SIPHASH_1_3 HASH_SEED = 0x9c21037e507a4e690fc406e7d29b44b960076c875b6852f8 PERTURB_KEYS = 1 (RANDOM)

which in my case produced​:

perl​: sv.c​:6547​: Perl_sv_clear​: Assertion `((svtype)((sv)->sv_flags & 0xff)) != (svtype)0xff' failed.
Aborted

I also cannot reproduce the buffer overflow​: with both valgrind and ASAN
I've run the code in a loop for a couple of hours and only ever got
the assertion failure or null ptr deref.

I agree its a stack refcount issue. The code can be reduced further as
follows​:

  map$$_=0,%$T=%​::
  =>
  map $$_=0, %$T = ('T', $​::{'T'});
  =>
  map $$_=0, %$T = ('T', *T);

The hash assign in list context leaves a fake glob on the stack which
had been stored as $T->{'T'}. The map then iterates over 'T' and the fake
glob. The first iteration does $$_=0, which is equivalent to ${'T'} = 0
which stops T b e i n g a r e f e r e n c e t o t h e h a s h , s o %T gets freed, so the
glob $T->{'T'} gets freed, so on the second iteration $_ gets aliased to a
freed or reallocated value.

Given that this requires code which already dangerously manipulates globs
and stashes, I can't see that it is a security issue.

I propose that the ticket be moved to the public queue, added to the
'stack not ref counted' meta ticket, then ignored until such time as we
fix that wider issue.

--
No matter how many dust sheets you use, you will get paint on the carpet.

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2017

From @iabyn

On Mon, Feb 20, 2017 at 11​:40​:55AM +0000, Dave Mitchell wrote​:

Given that this requires code which already dangerously manipulates globs
and stashes, I can't see that it is a security issue.

I propose that the ticket be moved to the public queue, added to the
'stack not ref counted' meta ticket, then ignored until such time as we
fix that wider issue.

which I am now doing.

--
"Foul and greedy Dwarf - you have eaten the last candle."
  -- "Hordes of the Things", BBC Radio.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant