Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.88k stars 532 forks source link

AddressSanitizer: heap-use-after-free in Perl_pp_rv2sv #15893

Closed p5pRT closed 7 years ago

p5pRT commented 7 years ago

Migrated from rt.perl.org#130861 (status was 'resolved')

Searchable as RT130861$

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Configure options​:

“./Configure -des -Dusedevel -DDEBUGGING -Dcc=clang -Doptimize=-O2 -Accflags="-fsanitize=address -fsanitize-coverage=edge" -Aldflags="-fsanitize=address -fsanitize-coverage=edge" -Alddlflags=-shared"

Information about configuration​:

Distributor ID​: Ubuntu Description​: Ubuntu 16.10 Release​: 16.10 Codename​: yakkety Arch​: x86_64

Best Regards\, Marcin T.

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

perl-heap-use-after-free-684-546-f07

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

perl​: warning​: Setting locale failed. perl​: warning​: Please check that your locale settings​:   LANGUAGE = (unset)\,   LC_ALL = (unset)\,   LC_CTYPE = "UTF-8"\,   LANG = "en_US.UTF-8"   are supported and installed on your system. perl​: warning​: Falling back to a fallback locale ("en_US.UTF-8").

==708==ERROR​: AddressSanitizer​: heap-use-after-free on address 0x619000009a78 at pc 0x000000a7c685 bp 0x7fff554408f0 sp 0x7fff554408e8 WRITE of size 8 at 0x619000009a78 thread T0   #0 0xa7c684 in Perl_pp_rv2sv /home/mtowalski/Fuzzing/Programs/perl-git/pp.c​:406​:5   #1 0x85d546 in Perl_runops_debug /home/mtowalski/Fuzzing/Programs/perl-git/dump.c​:2450​:23   #2 0x5eaf07 in S_run_body /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2524​:2   #3 0x5eaf07 in perl_run /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2447   #4 0x503205 in main /home/mtowalski/Fuzzing/Programs/perl-git/perlmain.c​:123​:9   #5 0x7fef44a433f0 in __libc_start_main /build/glibc-jxM2Ev/glibc-2.24/csu/../csu/libc-start.c​:291   #6 0x433a89 in _start (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x433a89)

0x619000009a78 is located 1016 bytes inside of 1024-byte region [0x619000009680\,0x619000009a80) freed by thread T0 here​:   #0 0x4d2410 in realloc (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4d2410)   #1 0x863fe8 in Perl_safesysrealloc /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:274​:18

previously allocated by thread T0 here​:   #0 0x4d2038 in malloc (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4d2038)   #1 0x863661 in Perl_safesysmalloc /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:153​:21

SUMMARY​: AddressSanitizer​: heap-use-after-free /home/mtowalski/Fuzzing/Programs/perl-git/pp.c​:406​:5 in Perl_pp_rv2sv Shadow bytes around the buggy address​:   0x0c327fff92f0​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff9300​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff9310​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff9320​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff9330​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd =>0x0c327fff9340​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]   0x0c327fff9350​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c327fff9360​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c327fff9370​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff9380​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff9390​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 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   Array cookie​: ac   Intra object redzone​: bb   ASan internal​: fe   Left alloca redzone​: ca   Right alloca redzone​: cb ==708==ABORTING

p5pRT commented 7 years ago

From @arc

On 25 February 2017 at 23​:56\, via RT \perl5\-security\-report@​perl\.org wrote​:

I've attached the poc and the asan log.

That asan log is​:

==708==ERROR​: AddressSanitizer​: heap-use-after-free on address 0x619000009a78 at pc 0x000000a7c685 bp 0x7fff554408f0 sp 0x7fff554408e8 WRITE of size 8 at 0x619000009a78 thread T0   #0 0xa7c684 in Perl_pp_rv2sv /home/mtowalski/Fuzzing/Programs/perl-git/pp.c​:406​:5   #1 0x85d546 in Perl_runops_debug /home/mtowalski/Fuzzing/Programs/perl-git/dump.c​:2450​:23   #2 0x5eaf07 in S_run_body /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2524​:2   #3 0x5eaf07 in perl_run /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2447   #4 0x503205 in main /home/mtowalski/Fuzzing/Programs/perl-git/perlmain.c​:123​:9   #5 0x7fef44a433f0 in __libc_start_main /build/glibc-jxM2Ev/glibc-2.24/csu/../csu/libc-start.c​:291   #6 0x433a89 in _start (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x433a89)

0x619000009a78 is located 1016 bytes inside of 1024-byte region [0x619000009680\,0x619000009a80) freed by thread T0 here​:   #0 0x4d2410 in realloc (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4d2410)   #1 0x863fe8 in Perl_safesysrealloc /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:274​:18

previously allocated by thread T0 here​:   #0 0x4d2038 in malloc (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4d2038)   #1 0x863661 in Perl_safesysmalloc /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:153​:21

which isn't terribly helpful. However\, I get something much more detailed and interesting on Mac OS​:

==75998==ERROR​: AddressSanitizer​: heap-use-after-free on address 0x619000007c70 at pc 0x0001059f5ffa bp 0x7fff5a6bbe30 sp 0x7fff5a6bbe28 WRITE of size 8 at 0x619000007c70 thread T0   #0 0x1059f5ff9 in Perl_pp_rv2sv (perl+0x1004b2ff9)   #1 0x1058f5e02 in Perl_runops_standard (perl+0x1003b2e02)   #2 0x1056235e9 in perl_run (perl+0x1000e05e9)   #3 0x105543bcf in main (perl+0x100000bcf)   #4 0x7fff924075fc in start (libdyld.dylib+0x35fc)   #5 0x2 (\)

0x619000007c70 is located 1008 bytes inside of 1024-byte region [0x619000007880\,0x619000007c80) freed by thread T0 here​:   #0 0x105f18b07 in wrap_realloc (libclang_rt.asan_osx_dynamic.dylib+0x46b07)   #1 0x1058359db in Perl_safesysrealloc (perl+0x1002f29db)   #2 0x1058e60f7 in Perl_av_extend_guts (perl+0x1003a30f7)   #3 0x1058e5394 in Perl_av_extend (perl+0x1003a2394)   #4 0x105a75877 in Perl_stack_grow (perl+0x100532877)   #5 0x105625b98 in Perl_call_sv (perl+0x1000e2b98)   #6 0x105669c92 in S_require_tie_mod (perl+0x100126c92)   #7 0x10564bca0 in Perl_gv_fetchpvn_flags (perl+0x100108ca0)   #8 0x10564f252 in Perl_gv_fetchsv (perl+0x10010c252)   #9 0x1059f4ecb in Perl_softref2xv (perl+0x1004b1ecb)   #10 0x1059f5767 in Perl_pp_rv2sv (perl+0x1004b2767)   #11 0x1058f5e02 in Perl_runops_standard (perl+0x1003b2e02)   #12 0x1056235e9 in perl_run (perl+0x1000e05e9)   #13 0x105543bcf in main (perl+0x100000bcf)   #14 0x7fff924075fc in start (libdyld.dylib+0x35fc)   #15 0x2 (\)

previously allocated by thread T0 here​:   #0 0x105f18770 in wrap_malloc (libclang_rt.asan_osx_dynamic.dylib+0x46770)   #1 0x105835611 in Perl_safesysmalloc (perl+0x1002f2611)   #2 0x1058e59f9 in Perl_av_extend_guts (perl+0x1003a29f9)   #3 0x1058e5394 in Perl_av_extend (perl+0x1003a2394)   #4 0x105a759bf in Perl_new_stackinfo (perl+0x1005329bf)   #5 0x105608489 in perl_construct (perl+0x1000c5489)   #6 0x105543b1c in main (perl+0x100000b1c)   #7 0x7fff924075fc in start (libdyld.dylib+0x35fc)   #8 0x2 (\)

That is​: the freed memory was allocated by Perl_new_stackinfo\, and freed by Perl_stack_grow\, which suggests strongly to me that something has extended the stack\, and that pp_rv2sv is trying to write through the old stack pointer.

The attached patch fixes this for me\, and includes a slightly reduced version of the failing program as a test case\, but I'd like at least one more pair of eyes on it\, because I don't have a detailed analysis of what causes the crash. (That also means I don't have a sense for how easy it would be for an attacker to trigger this.)

Also\, if someone can find a better reduction\, that'd be great; I found that most of the changes I made to the large string literal in the failing program concealed the error. In particular\, the failing program ends up dereferencing the string "["\, which loads arybase\, which means that miniperl can't reproduce the error. Indeed\, the presence of S_require_tie_mod in asan's "freed by" suggests that it's perhaps loading arybase that triggers the stack reallocation.

-- Aaron Crane ** http​://aaroncrane.co.uk/

p5pRT commented 7 years ago

From @arc

0001-pp_rv2sv-SPAGAIN-after-doing-things-that-could-exten.patch ```diff From 3952d952ed32364a95c9bdd8fd28c2ecd986f999 Mon Sep 17 00:00:00 2001 From: Aaron Crane Date: Sun, 26 Feb 2017 11:36:17 +0000 Subject: [PATCH] pp_rv2sv: SPAGAIN after doing things that could extend the stack --- pp.c | 1 + t/op/ref.t | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pp.c b/pp.c index 62316fc8b4..833dabb70a 100644 --- a/pp.c +++ b/pp.c @@ -403,6 +403,7 @@ PP(pp_rv2sv) else if (PL_op->op_private & OPpDEREF) sv = vivify_ref(sv, PL_op->op_private & OPpDEREF); } + SPAGAIN; /* in case chasing soft refs reallocated the stack */ SETs(sv); RETURN; } diff --git a/t/op/ref.t b/t/op/ref.t index 65d50b67a2..0ab9883d3e 100644 --- a/t/op/ref.t +++ b/t/op/ref.t @@ -8,7 +8,7 @@ BEGIN { use strict qw(refs subs); -plan(236); +plan(237); # Test this first before we extend the stack with other operations. # This caused an asan failure due to a bad write past the end of the stack. @@ -820,6 +820,18 @@ for ("4eounthouonth") { '[perl #109746] referential identity of \literal under threads+mad' } +# RT#130861: heap-use-after-free in pp_rv2sv, from asan fuzzing +SKIP: { + skip_if_miniperl("no dynamic loading on miniperl, so can't load arybase", 1); + my $code = <<'EOF'; +@q = "-1ocT\xC2\xA8gZZZZZZZZZZZZZZZZZZZZZZZZZZZYT`gZYT`gZYT`gZYT`gZYT`gZYT`gZYT`gZY\xD4`cV\xC2\\m;(\\d+|.);g; +\xC2\xA8xcV\\\xC2\xA8`ge\$_[0.07\x9E\xF6\xD8\xFCF\xE6U\xFA\x16\xF9E}VVVVVVV"=~m;(\d+|.);g; +() = map $$$$$$_, @q; +EOF + fresh_perl_like($code, qr/^Not a SCALAR reference /, { stderr => 1 }, + 'rt#130861: heap uaf in pp_rv2sv'); +} + # Bit of a hack to make test.pl happy. There are 3 more tests after it leaves. $test = curr_test(); curr_test($test + 3); -- 2.11.0 ```
p5pRT commented 7 years ago

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

p5pRT commented 7 years ago

From @tonycoz

On Sun\, 26 Feb 2017 04​:13​:44 -0800\, arc wrote​:

On 25 February 2017 at 23​:56\, via RT \perl5\-security\-report@&#8203;perl\.org wrote​:

I've attached the poc and the asan log.

That asan log is​:

==708==ERROR​: AddressSanitizer​: heap-use-after-free on address 0x619000009a78 at pc 0x000000a7c685 bp 0x7fff554408f0 sp 0x7fff554408e8 WRITE of size 8 at 0x619000009a78 thread T0 #0 0xa7c684 in Perl_pp_rv2sv /home/mtowalski/Fuzzing/Programs/perl-git/pp.c​:406​:5 #1 0x85d546 in Perl_runops_debug /home/mtowalski/Fuzzing/Programs/perl-git/dump.c​:2450​:23 #2 0x5eaf07 in S_run_body /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2524​:2 #3 0x5eaf07 in perl_run /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2447 #4 0x503205 in main /home/mtowalski/Fuzzing/Programs/perl-git/perlmain.c​:123​:9 #5 0x7fef44a433f0 in __libc_start_main /build/glibc-jxM2Ev/glibc-2.24/csu/../csu/libc-start.c​:291 #6 0x433a89 in _start (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x433a89)

0x619000009a78 is located 1016 bytes inside of 1024-byte region [0x619000009680\,0x619000009a80) freed by thread T0 here​: #0 0x4d2410 in realloc (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4d2410) #1 0x863fe8 in Perl_safesysrealloc /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:274​:18

previously allocated by thread T0 here​: #0 0x4d2038 in malloc (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4d2038) #1 0x863661 in Perl_safesysmalloc /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:153​:21

which isn't terribly helpful. However\, I get something much more detailed and interesting on Mac OS​:

==75998==ERROR​: AddressSanitizer​: heap-use-after-free on address 0x619000007c70 at pc 0x0001059f5ffa bp 0x7fff5a6bbe30 sp 0x7fff5a6bbe28 WRITE of size 8 at 0x619000007c70 thread T0 #0 0x1059f5ff9 in Perl_pp_rv2sv (perl+0x1004b2ff9) #1 0x1058f5e02 in Perl_runops_standard (perl+0x1003b2e02) #2 0x1056235e9 in perl_run (perl+0x1000e05e9) #3 0x105543bcf in main (perl+0x100000bcf) #4 0x7fff924075fc in start (libdyld.dylib+0x35fc) #5 0x2 (\)

0x619000007c70 is located 1008 bytes inside of 1024-byte region [0x619000007880\,0x619000007c80) freed by thread T0 here​: #0 0x105f18b07 in wrap_realloc (libclang_rt.asan_osx_dynamic.dylib+0x46b07) #1 0x1058359db in Perl_safesysrealloc (perl+0x1002f29db) #2 0x1058e60f7 in Perl_av_extend_guts (perl+0x1003a30f7) #3 0x1058e5394 in Perl_av_extend (perl+0x1003a2394) #4 0x105a75877 in Perl_stack_grow (perl+0x100532877) #5 0x105625b98 in Perl_call_sv (perl+0x1000e2b98) #6 0x105669c92 in S_require_tie_mod (perl+0x100126c92) #7 0x10564bca0 in Perl_gv_fetchpvn_flags (perl+0x100108ca0) #8 0x10564f252 in Perl_gv_fetchsv (perl+0x10010c252) #9 0x1059f4ecb in Perl_softref2xv (perl+0x1004b1ecb) #10 0x1059f5767 in Perl_pp_rv2sv (perl+0x1004b2767) #11 0x1058f5e02 in Perl_runops_standard (perl+0x1003b2e02) #12 0x1056235e9 in perl_run (perl+0x1000e05e9) #13 0x105543bcf in main (perl+0x100000bcf) #14 0x7fff924075fc in start (libdyld.dylib+0x35fc) #15 0x2 (\)

previously allocated by thread T0 here​: #0 0x105f18770 in wrap_malloc (libclang_rt.asan_osx_dynamic.dylib+0x46770) #1 0x105835611 in Perl_safesysmalloc (perl+0x1002f2611) #2 0x1058e59f9 in Perl_av_extend_guts (perl+0x1003a29f9) #3 0x1058e5394 in Perl_av_extend (perl+0x1003a2394) #4 0x105a759bf in Perl_new_stackinfo (perl+0x1005329bf) #5 0x105608489 in perl_construct (perl+0x1000c5489) #6 0x105543b1c in main (perl+0x100000b1c) #7 0x7fff924075fc in start (libdyld.dylib+0x35fc) #8 0x2 (\)

That is​: the freed memory was allocated by Perl_new_stackinfo\, and freed by Perl_stack_grow\, which suggests strongly to me that something has extended the stack\, and that pp_rv2sv is trying to write through the old stack pointer.

The attached patch fixes this for me\, and includes a slightly reduced version of the failing program as a test case\, but I'd like at least one more pair of eyes on it\, because I don't have a detailed analysis of what causes the crash. (That also means I don't have a sense for how easy it would be for an attacker to trigger this.)

Also\, if someone can find a better reduction\, that'd be great; I found that most of the changes I made to the large string literal in the failing program concealed the error. In particular\, the failing program ends up dereferencing the string "["\, which loads arybase\, which means that miniperl can't reproduce the error. Indeed\, the presence of S_require_tie_mod in asan's "freed by" suggests that it's perhaps loading arybase that triggers the stack reallocation.

Here's a slightly different minification.

Changes to the literal that preserve the number of matches against the regexp were safe\, so compressing sequences of digits\, replacing non-ASCII characters and removing the new lines from the literal worked for me.

Changing the literal to a generated value ("1" . ("x" x 123)) didn't reproduce the issue.

WRT arybase\, perhaps require_tie_mod() needs to work with a new stack\, perhaps gv_fetchpvn_flags() reallocating the stack is a bug.

Tony

p5pRT commented 7 years ago

From @tonycoz

130861b.pl

p5pRT commented 7 years ago

From @iabyn

On Sun\, Feb 26\, 2017 at 08​:22​:01PM -0800\, Tony Cook via RT wrote​:

On Sun\, 26 Feb 2017 04​:13​:44 -0800\, arc wrote​:

On 25 February 2017 at 23​:56\, via RT \perl5\-security\-report@&#8203;perl\.org That is​: the freed memory was allocated by Perl_new_stackinfo\, and freed by Perl_stack_grow\, which suggests strongly to me that something has extended the stack\, and that pp_rv2sv is trying to write through the old stack pointer.

The attached patch fixes this for me\, and includes a slightly reduced version of the failing program as a test case\, but I'd like at least one more pair of eyes on it\, because I don't have a detailed analysis of what causes the crash. (That also means I don't have a sense for how easy it would be for an attacker to trigger this.)

Also\, if someone can find a better reduction\, that'd be great; I found that most of the changes I made to the large string literal in the failing program concealed the error. In particular\, the failing program ends up dereferencing the string "["\, which loads arybase\, which means that miniperl can't reproduce the error. Indeed\, the presence of S_require_tie_mod in asan's "freed by" suggests that it's perhaps loading arybase that triggers the stack reallocation.

Here's a slightly different minification.

Changes to the literal that preserve the number of matches against the regexp were safe\, so compressing sequences of digits\, replacing non-ASCII characters and removing the new lines from the literal worked for me.

Changing the literal to a generated value ("1" . ("x" x 123)) didn't reproduce the issue.

WRT arybase\, perhaps require_tie_mod() needs to work with a new stack\, perhaps gv_fetchpvn_flags() reallocating the stack is a bug.

I attach an alternative patch which I suggest should supersede Aaron's one. It has a much simplified test case\, and adds a SAVESTACKi() to S_require_tie_mod() in addition to the SPAGAIN in pp_rv2sv.

I don't think it really counts as a security issue​: it involves using one of - + ! [ as a run-time symbolic reference\, at a point where the stack is almost exactly full.

So I think this ticket should be moved to the public queue soonish\, then my patch should be applied to blead post-5.26 release.

-- Dave's first rule of Opera​: If something needs saying\, say it​: don't warble it.

p5pRT commented 7 years ago

From @iabyn

0001-S_require_tie_mod-use-a-new-stack.patch ```diff >From cd763c7f0f5abd08207c7852a2cba1c24d2904b8 Mon Sep 17 00:00:00 2001 From: David Mitchell Date: Tue, 14 Mar 2017 09:19:15 +0000 Subject: [PATCH] S_require_tie_mod(): use a new stack RT #130861 This function is used to load a module associated with various magic vars, like $[ and %+. Since it can be called 'unexpectedly', it should use a new stack. The issue in this ticket was equivalent to my $var = '['; $$var; where the symbolic dereference triggered a run-time load of arybase.pm, which grew the stack, invalidating the SP in pp_rv2sv. Note that most of the stuff which S_require_tie_mod() calls, such as load_module(), will do its own PUSHSTACK(); but S_require_tie_mod() also does a bit of stack manipulation itself. The test case includes a magic number, 125, which happens to be the exact size necessary to trigger a stack realloc in S_require_tie_mod(). In later perl versions this value may well change. But it seemed too expensive to call fresh_perl_is() 100's of times with different values of $n. This commit also adds a SPAGAIN to pp_rv2sv on the 'belt and braces' principle. This commit is based on an earlier effort by Aaron Crane. --- gv.c | 2 ++ pp.c | 1 + t/op/ref.t | 20 +++++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/gv.c b/gv.c index d32a9c5..581211f 100644 --- a/gv.c +++ b/gv.c @@ -1338,6 +1338,7 @@ S_require_tie_mod(pTHX_ GV *gv, const char varname, const char * name, GV **gvp; dSP; + PUSHSTACKi(PERLSI_MAGIC); ENTER; #define HV_FETCH_TIE_FUNC (GV **)hv_fetchs(stash, "_tie_it", 0) @@ -1367,6 +1368,7 @@ S_require_tie_mod(pTHX_ GV *gv, const char varname, const char * name, PUTBACK; call_sv((SV *)*gvp, G_VOID|G_DISCARD); LEAVE; + POPSTACK; } } diff --git a/pp.c b/pp.c index a640995..1275969 100644 --- a/pp.c +++ b/pp.c @@ -403,6 +403,7 @@ PP(pp_rv2sv) else if (PL_op->op_private & OPpDEREF) sv = vivify_ref(sv, PL_op->op_private & OPpDEREF); } + SPAGAIN; /* in case chasing soft refs reallocated the stack */ SETs(sv); RETURN; } diff --git a/t/op/ref.t b/t/op/ref.t index 65d50b6..44047ae 100644 --- a/t/op/ref.t +++ b/t/op/ref.t @@ -8,7 +8,7 @@ BEGIN { use strict qw(refs subs); -plan(236); +plan(237); # Test this first before we extend the stack with other operations. # This caused an asan failure due to a bad write past the end of the stack. @@ -820,6 +820,24 @@ for ("4eounthouonth") { '[perl #109746] referential identity of \literal under threads+mad' } +# RT#130861: heap-use-after-free in pp_rv2sv, from asan fuzzing +SKIP: { + skip_if_miniperl("no dynamic loading on miniperl, so can't load arybase", 1); + # this value is critical - its just enough so that the stack gets + # grown which loading/calling arybase + my $n = 125; + + my $code = <<'EOF'; +$ary = '['; +my @a = map $$ary, 1..NNN; +print "@a\n"; +EOF + $code =~ s/NNN/$n/g; + my @exp = ("0") x $n; + fresh_perl_is($code, "@exp", { stderr => 1 }, + 'rt#130861: heap uaf in pp_rv2sv'); +} + # Bit of a hack to make test.pl happy. There are 3 more tests after it leaves. $test = curr_test(); curr_test($test + 3); -- 2.4.11 ```
p5pRT commented 7 years ago

From @iabyn

On Tue\, Mar 14\, 2017 at 09​:40​:54AM +0000\, Dave Mitchell wrote​:

On Sun\, Feb 26\, 2017 at 08​:22​:01PM -0800\, Tony Cook via RT wrote​:

On Sun\, 26 Feb 2017 04​:13​:44 -0800\, arc wrote​:

On 25 February 2017 at 23​:56\, via RT \perl5\-security\-report@&#8203;perl\.org That is​: the freed memory was allocated by Perl_new_stackinfo\, and freed by Perl_stack_grow\, which suggests strongly to me that something has extended the stack\, and that pp_rv2sv is trying to write through the old stack pointer.

The attached patch fixes this for me\, and includes a slightly reduced version of the failing program as a test case\, but I'd like at least one more pair of eyes on it\, because I don't have a detailed analysis of what causes the crash. (That also means I don't have a sense for how easy it would be for an attacker to trigger this.)

Also\, if someone can find a better reduction\, that'd be great; I found that most of the changes I made to the large string literal in the failing program concealed the error. In particular\, the failing program ends up dereferencing the string "["\, which loads arybase\, which means that miniperl can't reproduce the error. Indeed\, the presence of S_require_tie_mod in asan's "freed by" suggests that it's perhaps loading arybase that triggers the stack reallocation.

Here's a slightly different minification.

Changes to the literal that preserve the number of matches against the regexp were safe\, so compressing sequences of digits\, replacing non-ASCII characters and removing the new lines from the literal worked for me.

Changing the literal to a generated value ("1" . ("x" x 123)) didn't reproduce the issue.

WRT arybase\, perhaps require_tie_mod() needs to work with a new stack\, perhaps gv_fetchpvn_flags() reallocating the stack is a bug.

I attach an alternative patch which I suggest should supersede Aaron's one. It has a much simplified test case\, and adds a SAVESTACKi() to S_require_tie_mod() in addition to the SPAGAIN in pp_rv2sv.

I don't think it really counts as a security issue​: it involves using one of - + ! [ as a run-time symbolic reference\, at a point where the stack is almost exactly full.

So I think this ticket should be moved to the public queue soonish\, then my patch should be applied to blead post-5.26 release.

Now pushed as v5.27.0-118-g655f5b2. I'll move this ticket to the public queue now.

-- Wesley Crusher gets beaten up by his classmates for being a smarmy git\, and consequently has a go at making some friends of his own age for a change.   -- Things That Never Happen in "Star Trek" #18

p5pRT commented 7 years ago

@iabyn - Status changed from 'open' to 'resolved'