Skip Menu |
Report information
Id: 132602
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: sraums2498 [at] gmail.com
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: (no value)
Type: (no value)
Perl Version: (no value)
Fixed In: 5.27.9



Date: Mon, 18 Dec 2017 17:07:29 +0530
To: perl5-security-report [...] perl.org
From: SRAUMS JN <sraums2498 [...] gmail.com>
Subject: PERL-5.26.1 heap_use_after_free WRITE of size 8
Download (untitled) / with headers
text/plain 3.9k
=================================================================
==105657==ERROR: AddressSanitizer: heap-use-after-free on address 0x619000009a70 at pc 0x0000021ceb5c bp 0x7fff8d34c340 sp 0x7fff8d34c330
WRITE of size 8 at 0x619000009a70 thread T0
    #0 0x21ceb5b in Perl_pp_list /home/asan_perl/Documents/perl-5.26.1/pp.c:5193
    #1 0x1b1bc2e in Perl_runops_standard /home/asan_perl/Documents/perl-5.26.1/run.c:41
    #2 0x9218a5 in S_run_body /home/asan_perl/Documents/perl-5.26.1/perl.c:2519
    #3 0x9218a5 in perl_run /home/asan_perl/Documents/perl-5.26.1/perl.c:2447
    #4 0x46b6a7 in main /home/asan_perl/Documents/perl-5.26.1/perlmain.c:123
    #5 0x7f0cf33a282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #6 0x46c888 in _start (/home/asan_perl/Documents/perl-5.26.1/perl+0x46c888)

0x619000009a70 is located 1008 bytes inside of 1024-byte region [0x619000009680,0x619000009a80)
freed by thread T0 here:
    #0 0x7f0cf4146961 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98961)
    #1 0x1681118 in Perl_safesysrealloc /home/asan_perl/Documents/perl-5.26.1/util.c:274
    #2 0x1addeda in Perl_av_extend_guts /home/asan_perl/Documents/perl-5.26.1/av.c:163
    #3 0x22727fb in Perl_stack_grow /home/asan_perl/Documents/perl-5.26.1/scope.c:57
    #4 0x21ce97f in Perl_pp_list /home/asan_perl/Documents/perl-5.26.1/pp.c:5191
    #5 0x1b1bc2e in Perl_runops_standard /home/asan_perl/Documents/perl-5.26.1/run.c:41
    #6 0x9218a5 in S_run_body /home/asan_perl/Documents/perl-5.26.1/perl.c:2519
    #7 0x9218a5 in perl_run /home/asan_perl/Documents/perl-5.26.1/perl.c:2447
    #8 0x46b6a7 in main /home/asan_perl/Documents/perl-5.26.1/perlmain.c:123
    #9 0x7f0cf33a282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

previously allocated by thread T0 here:
    #0 0x7f0cf4146602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x167dd81 in Perl_safesysmalloc /home/asan_perl/Documents/perl-5.26.1/util.c:153
    #2 0x1adf2d0 in Perl_av_extend_guts /home/asan_perl/Documents/perl-5.26.1/av.c:186
    #3 0x2272eb6 in Perl_new_stackinfo /home/asan_perl/Documents/perl-5.26.1/scope.c:74
    #4 0x8ab011 in Perl_init_stacks /home/asan_perl/Documents/perl-5.26.1/perl.c:4137
    #5 0x8af2e0 in perl_construct /home/asan_perl/Documents/perl-5.26.1/perl.c:274
    #6 0x46b033 in main /home/asan_perl/Documents/perl-5.26.1/perlmain.c:117
    #7 0x7f0cf33a282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-use-after-free /home/asan_perl/Documents/perl-5.26.1/pp.c:5193 Perl_pp_list
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: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff9380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c327fff9390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==105657==ABORTING


--
Regards,
SRAUMS
Download 168
application/octet-stream 458b

Message body not shown because it is not plain text.

Subject: Re: [perl #132602] PERL-5.26.1 heap_use_after_free WRITE of size 8
From: Dave Mitchell <davem [...] iabyn.com>
To: perl5-security-report [...] perl.org
Date: Wed, 20 Dec 2017 14:46:21 +0000
Download (untitled) / with headers
text/plain 2.2k
On Mon, Dec 18, 2017 at 03:38:23AM -0800, SRAUMS JN wrote: Show quoted text
> WRITE of size 8 at 0x619000009a70 thread T0 > #0 0x21ceb5b in Perl_pp_list
This is a regression that was introduced into blead with v5.27.1-248-gb54564c and backported to 5.26.1 with v5.26.0-16-g6a20648, thus it only appears in a single production release. The fault is in pp_list using EXTEND() rather than MEXTEND(), so if the stack gets reallocated, mark still points to the old stack. I think it would be hard to find code in the wild which could exploit this: 1) pp_list() would have to be called in scalar context, which doesn't happen very often (I added an assert(0) in the scalar branch of pp_list, and 97% of the test suite files passed); 2) pp_list has to be called with the stack filled exactly to the brim, in order to trigger a stack grow. Once triggered, the effects are 1) pp_list will randomly return (...)[-1] or &PL_sv_undef - normally which of these is chosen depends on whether the list is empty; 2) On return, PL_stack_sp will point to the old freed stack, so any further stack activity will be writing SV addresses to, or beyond, the freed stack. I have a fix for this, and also a fix for a similar issue in pp_warn, found by looking for pp functions which contain both MARK and EXTEND (rather than MEXTEND). Here's a test I added which triggers the behaviour: fresh_perl_is(<<'EOF', "OK\n", {stderr => 1}, "RT #132602"); sub f { 3701, 15844 } my (@a, @b); for my $i (1..300) { push @a, $i; @b = (@a, scalar f()); die unless $b[-1] == 15844; } # mess with the stack some more for ASan's benefit for my $i (1..100) { push @a, $i; @b = @a; } print "OK\n"; EOF The OP_LIST is in the f sub, which doesn't know until runtime whether to return a list or the last element. Once the pp_list fix is pushed, it needs backporting to maint-5.26 too. My feeling is that since this is hard enough to exploit, and has been in only one production release, we should just treat it as a normal fix. -- A major Starfleet emergency breaks out near the Enterprise, but fortunately some other ships in the area are able to deal with it to everyone's satisfaction. -- Things That Never Happen in "Star Trek" #13
RT-Send-CC: perl5-security-report [...] perl.org
Download (untitled) / with headers
text/plain 3.1k
On Wed, 20 Dec 2017 06:46:41 -0800, davem wrote: Show quoted text
> On Mon, Dec 18, 2017 at 03:38:23AM -0800, SRAUMS JN wrote:
> > WRITE of size 8 at 0x619000009a70 thread T0 > > #0 0x21ceb5b in Perl_pp_list
> > This is a regression that was introduced into blead with > v5.27.1-248-gb54564c and backported to 5.26.1 with v5.26.0-16-g6a20648, > thus it only appears in a single production release. > > The fault is in pp_list using EXTEND() rather than MEXTEND(), so if the > stack gets reallocated, mark still points to the old stack. > > I think it would be hard to find code in the wild which could exploit > this: > > 1) pp_list() would have to be called in scalar context, which doesn't > happen very often (I added an assert(0) in the scalar branch of pp_list, > and 97% of the test suite files passed); > > 2) pp_list has to be called with the stack filled exactly to the brim, > in order to trigger a stack grow. > > Once triggered, the effects are > > 1) pp_list will randomly return (...)[-1] or &PL_sv_undef - normally > which of these is chosen depends on whether the list is empty; > > 2) On return, PL_stack_sp will point to the old freed stack, so any > further stack activity will be writing SV addresses to, or beyond, the > freed stack. > > I have a fix for this, and also a fix for a similar issue in pp_warn, > found by looking for pp functions which contain both MARK and EXTEND > (rather than MEXTEND). > > Here's a test I added which triggers the behaviour: > > fresh_perl_is(<<'EOF', "OK\n", {stderr => 1}, "RT #132602"); > sub f { 3701, 15844 } > my (@a, @b); > for my $i (1..300) { > push @a, $i; > @b = (@a, scalar f()); > die unless $b[-1] == 15844; > } > # mess with the stack some more for ASan's benefit > for my $i (1..100) { > push @a, $i; > @b = @a; > } > print "OK\n"; > EOF > > The OP_LIST is in the f sub, which doesn't know until runtime whether to > return a list or the last element. > > Once the pp_list fix is pushed, it needs backporting to maint-5.26 too. > > My feeling is that since this is hard enough to exploit, and has been in > only one production release, we should just treat it as a normal fix.
It's potentially a denial of service in that a write to the freed block might crash perl (the memory may no longer be mapped), or corrupt the arena, leading to a crash later on. But as you say, it's unlikely for pp_list to be used in scalar context, and it's very unlikely the stack will be filled to the brim, so I agree this isn't a useful denial of service, and the lack of control over the value written (it's a pointer) means I don't think this can be used for any sort of code execution attack. If the new block allocated when the stack was reallocated contained SV pointers (such as the AvARRAY() from an AV) it may be possible to use this for some sort of information disclosure, since the next SV popped from he stack will be the previous SV pointer[1], but with the unlikelyhood of the pre-conditions I don't think this is realistically exploitable. So I agree this isn't a security issue. Tony [1] AvREAL() arrays have the new entries cleared, but the stack isn't
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 124b
On Tue, 30 Jan 2018 16:53:24 -0800, tonyc wrote: Show quoted text
> So I agree this isn't a security issue.
Moved to the public queue. Tony
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 333b
On Wed, 20 Dec 2017 06:46:41 -0800, davem wrote: Show quoted text
> I have a fix for this, and also a fix for a similar issue in pp_warn, > found by looking for pp functions which contain both MARK and EXTEND > (rather than MEXTEND).
I think the original issue here was fixed in 57bd660029d (perl #131954), but not the pp_warn issue you found. Tony
Date: Wed, 31 Jan 2018 21:19:11 +0000
Subject: Re: [perl #132602] PERL-5.26.1 heap_use_after_free WRITE of size 8
To: Tony Cook via RT <perlbug-followup [...] perl.org>
CC: perl5-porters [...] perl.org
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 579b
On Tue, Jan 30, 2018 at 04:59:24PM -0800, Tony Cook via RT wrote: Show quoted text
> On Wed, 20 Dec 2017 06:46:41 -0800, davem wrote:
> > I have a fix for this, and also a fix for a similar issue in pp_warn, > > found by looking for pp functions which contain both MARK and EXTEND > > (rather than MEXTEND).
> > I think the original issue here was fixed in 57bd660029d (perl #131954), but > not the pp_warn issue you found.
Ah yes, I forgot to push it. Pushed now as v5.27.8-140-g8d629a7. -- A walk of a thousand miles begins with a single step... then continues for another 1,999,999 or so.


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org