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-use-after-free in Perl_sv_setpv_bufsize (perl/sv.c:4918:17) #17084

Open
p5pRT opened this issue Jul 6, 2019 · 7 comments
Open

heap-use-after-free in Perl_sv_setpv_bufsize (perl/sv.c:4918:17) #17084

p5pRT opened this issue Jul 6, 2019 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Jul 6, 2019

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

Searchable as RT134269$

@p5pRT
Copy link
Author

p5pRT commented Jul 6, 2019

From imdb95@gmail.com

Hello,
I found this bug when fuzzing perl5.

**********Compilation and environment**********
root@​instance-2​:~/fuzz_perl# ./perl/perl -v

This is perl 5, version 31, subversion 2 (v5.31.2 (v5.31.1-6-g9649a81))
built for x86_64-linux

Copyright 1987-2019, Larry Wall

Perl may be copied only under the terms of either the Artistic License or
the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.


root@​instance-2​:~/fuzz_perl# uname -a
Linux instance-2 4.15.0-1036-gcp #38~16.04.1-Ubuntu SMP Tue Jun 25 15​:30​:46
UTC 2019 x86_64 x86_64 x86_64 GNU/Linux


root@​instance-2​:~/fuzz_perl# lsb_release -r
Release​: 16.04


Compilation​:
AFL_USE_ASAN=1 ./Configure -des -Dusedevel -DDEBUGGING -Dcc=afl-clang-fast
-Doptimize=-g && AFL_USE_ASAN=1 make


The bug also occurs in default perl version for Ubuntu 16.04.

**********Reproduce-1**********
root@​instance-2​:~/fuzz_perl# ./perl/perl -e '"" =~ /$a{$| = 1} $b{$| .= *
|= 2}/'

==3038==ERROR​: AddressSanitizer​: heap-use-after-free on address
0x602000001090 at pc 0x0000009eaf79 bp 0x7ffcbd35b1d0 sp 0x7ffcbd35b1c8
WRITE of size 1 at 0x602000001090 thread T0
  #0 0x9eaf78 in Perl_sv_setpv_bufsize /root/fuzz_perl/perl/sv.c​:4918​:17
  #1 0x944236 in S_do_concat /root/fuzz_perl/perl/pp_hot.c​:298​:13
  #2 0x9434e9 in Perl_pp_concat /root/fuzz_perl/perl/pp_hot.c​:332​:5
  #3 0x88087c in Perl_runops_debug /root/fuzz_perl/perl/dump.c​:2537​:23
  #4 0x5e95f2 in S_run_body /root/fuzz_perl/perl/perl.c
  #5 0x5e95f2 in perl_run /root/fuzz_perl/perl/perl.c​:2639
  #6 0x50a398 in main /root/fuzz_perl/perl/perlmain.c​:127​:9
  #7 0x7ffb3e9fc82f in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
  #8 0x4368c8 in _start (/root/fuzz_perl/perl/perl+0x4368c8)

0x602000001090 is located 0 bytes inside of 10-byte region
[0x602000001090,0x60200000109a)
freed by thread T0 here​:
  #0 0x4dd27b in __interceptor_free
/scratch/llvm/clang-4/xenial/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc​:47​:3
  #1 0x887577 in Perl_safesysfree /root/fuzz_perl/perl/util.c​:399​:2
  #2 0xa0c16e in Perl_sv_free2 /root/fuzz_perl/perl/sv.c​:7093​:9

previously allocated by thread T0 here​:
  #0 0x4dd5cc in malloc
/scratch/llvm/clang-4/xenial/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc​:66​:3
  #1 0x88660e in Perl_safesysmalloc /root/fuzz_perl/perl/util.c​:155​:21

SUMMARY​: AddressSanitizer​: heap-use-after-free
/root/fuzz_perl/perl/sv.c​:4918​:17 in Perl_sv_setpv_bufsize
Shadow bytes around the buggy address​:
  0x0c047fff81c0​: fa fa 00 02 fa fa 00 01 fa fa 00 02 fa fa 00 05
  0x0c047fff81d0​: fa fa 02 fa fa fa 07 fa fa fa fd fd fa fa fd fd
  0x0c047fff81e0​: fa fa 00 02 fa fa fd fa fa fa 00 02 fa fa fd fd
  0x0c047fff81f0​: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fa
  0x0c047fff8200​: fa fa 02 fa fa fa fd fd fa fa fd fd fa fa fd fd
=>0x0c047fff8210​: fa fa[fd]fd fa fa 00 02 fa fa fa fa fa fa fa fa
  0x0c047fff8220​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8230​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8240​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8250​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8260​: 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
  Freed heap region​: fd
  Stack left redzone​: f1
  Stack mid redzone​: f2
  Stack right redzone​: f3
  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
==3038==ABORTING

**********Reproduce-2**********
root@​instance-2​:~/fuzz_perl# ./perl/perl -e '$| .= *|= 1'
ASAN​:DEADLYSIGNAL

==10503==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000000
(pc 0x0000009eab4c bp 0xfffffffffffffffc sp 0x7ffdf94f3780 T0)
==10503==The signal is caused by a WRITE memory access.
==10503==Hint​: address points to the zero page.
  #0 0x9eab4b in Perl_sv_setpv_bufsize /root/fuzz_perl/perl/sv.c​:4918​:17
  #1 0x944236 in S_do_concat /root/fuzz_perl/perl/pp_hot.c​:298​:13
  #2 0x9434e9 in Perl_pp_concat /root/fuzz_perl/perl/pp_hot.c​:332​:5
  #3 0x88087c in Perl_runops_debug /root/fuzz_perl/perl/dump.c​:2537​:23
  #4 0x5e95f2 in S_run_body /root/fuzz_perl/perl/perl.c
  #5 0x5e95f2 in perl_run /root/fuzz_perl/perl/perl.c​:2639
  #6 0x50a398 in main /root/fuzz_perl/perl/perlmain.c​:127​:9
  #7 0x7f5eaedf982f in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
  #8 0x4368c8 in _start (/root/fuzz_perl/perl/perl+0x4368c8)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV /root/fuzz_perl/perl/sv.c​:4918​:17 in
Perl_sv_setpv_bufsize
==10503==ABORTING

**********Reproduce-3**********
root@​instance-2​:~/fuzz_perl# perl -v

This is perl 5, version 22, subversion 1 (v5.22.1) built for
x86_64-linux-gnu-thread-multi
(with 73 registered patches, see perl -V for more detail)

Copyright 1987-2015, Larry Wall

Perl may be copied only under the terms of either the Artistic License or
the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.


root@​instance-2​:~/fuzz_perl# perl -e '"" =~ /$a{$| = 1} $b{$| .= * |= 2}/'
*** Error in `perl'​: malloc()​: memory corruption (fast)​: 0x0000000001e6a410
***
======= Backtrace​: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fbad0b957e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x82651)[0x7fbad0ba0651]
/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7fbad0ba2184]
perl(Perl_safesysmalloc+0x12)[0x498422]
perl(Perl_sv_grow+0xf8)[0x4cb848]
perl(Perl_sv_setpvn+0x63)[0x4d2363]
perl(Perl_newSVpvn+0x4d)[0x4d2bad]
perl[0x4730c9]
perl(Perl_re_op_compile+0x1a2)[0x48dba2]
perl(Perl_pp_regcomp+0xe1)[0x4f6671]
perl(Perl_runops_standard+0x16)[0x4b64a6]
perl(perl_run+0x2f9)[0x443bc9]
perl(main+0x12b)[0x41cb2b]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fbad0b3e830]
perl(_start+0x29)[0x41cb69]
======= Memory map​: ========
00400000-005cf000 r-xp 00000000 08​:01 24164
/usr/bin/perl
007cf000-007d0000 r--p 001cf000 08​:01 24164
/usr/bin/perl
007d0000-007d3000 rw-p 001d0000 08​:01 24164
/usr/bin/perl
01e44000-01e86000 rw-p 00000000 00​:00 0
[heap]
7fbacc000000-7fbacc021000 rw-p 00000000 00​:00 0
7fbacc021000-7fbad0000000 ---p 00000000 00​:00 0
7fbad06d0000-7fbad06e6000 r-xp 00000000 08​:01 1995
/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbad06e6000-7fbad08e5000 ---p 00016000 08​:01 1995
/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbad08e5000-7fbad08e6000 rw-p 00015000 08​:01 1995
/lib/x86_64-linux-gnu/libgcc_s.so.1
7fbad08e6000-7fbad08ef000 r-xp 00000000 08​:01 2029
/lib/x86_64-linux-gnu/libcrypt-2.23.so
7fbad08ef000-7fbad0aee000 ---p 00009000 08​:01 2029
/lib/x86_64-linux-gnu/libcrypt-2.23.so
7fbad0aee000-7fbad0aef000 r--p 00008000 08​:01 2029
/lib/x86_64-linux-gnu/libcrypt-2.23.so
7fbad0aef000-7fbad0af0000 rw-p 00009000 08​:01 2029
/lib/x86_64-linux-gnu/libcrypt-2.23.so
7fbad0af0000-7fbad0b1e000 rw-p 00000000 00​:00 0
7fbad0b1e000-7fbad0cde000 r-xp 00000000 08​:01 2082
/lib/x86_64-linux-gnu/libc-2.23.so
7fbad0cde000-7fbad0ede000 ---p 001c0000 08​:01 2082
/lib/x86_64-linux-gnu/libc-2.23.so
7fbad0ede000-7fbad0ee2000 r--p 001c0000 08​:01 2082
/lib/x86_64-linux-gnu/libc-2.23.so
7fbad0ee2000-7fbad0ee4000 rw-p 001c4000 08​:01 2082
/lib/x86_64-linux-gnu/libc-2.23.so
7fbad0ee4000-7fbad0ee8000 rw-p 00000000 00​:00 0
7fbad0ee8000-7fbad0f00000 r-xp 00000000 08​:01 2018
/lib/x86_64-linux-gnu/libpthread-2.23.so
7fbad0f00000-7fbad10ff000 ---p 00018000 08​:01 2018
/lib/x86_64-linux-gnu/libpthread-2.23.so
7fbad10ff000-7fbad1100000 r--p 00017000 08​:01 2018
/lib/x86_64-linux-gnu/libpthread-2.23.so
7fbad1100000-7fbad1101000 rw-p 00018000 08​:01 2018
/lib/x86_64-linux-gnu/libpthread-2.23.so
7fbad1101000-7fbad1105000 rw-p 00000000 00​:00 0
7fbad1105000-7fbad120d000 r-xp 00000000 08​:01 2087
/lib/x86_64-linux-gnu/libm-2.23.so
7fbad120d000-7fbad140c000 ---p 00108000 08​:01 2087
/lib/x86_64-linux-gnu/libm-2.23.so
7fbad140c000-7fbad140d000 r--p 00107000 08​:01 2087
/lib/x86_64-linux-gnu/libm-2.23.so
7fbad140d000-7fbad140e000 rw-p 00108000 08​:01 2087
/lib/x86_64-linux-gnu/libm-2.23.so
7fbad140e000-7fbad1411000 r-xp 00000000 08​:01 2014
/lib/x86_64-linux-gnu/libdl-2.23.so
7fbad1411000-7fbad1610000 ---p 00003000 08​:01 2014
/lib/x86_64-linux-gnu/libdl-2.23.so
7fbad1610000-7fbad1611000 r--p 00002000 08​:01 2014
/lib/x86_64-linux-gnu/libdl-2.23.so
7fbad1611000-7fbad1612000 rw-p 00003000 08​:01 2014
/lib/x86_64-linux-gnu/libdl-2.23.so
7fbad1612000-7fbad1638000 r-xp 00000000 08​:01 2015
/lib/x86_64-linux-gnu/ld-2.23.so
7fbad1693000-7fbad182b000 r--p 00000000 08​:01 29183
/usr/lib/locale/locale-archive
7fbad182b000-7fbad1830000 rw-p 00000000 00​:00 0
7fbad1836000-7fbad1837000 rw-p 00000000 00​:00 0
7fbad1837000-7fbad1838000 r--p 00025000 08​:01 2015
/lib/x86_64-linux-gnu/ld-2.23.so
7fbad1838000-7fbad1839000 rw-p 00026000 08​:01 2015
/lib/x86_64-linux-gnu/ld-2.23.so
7fbad1839000-7fbad183a000 rw-p 00000000 00​:00 0
7ffd276ae000-7ffd276cf000 rw-p 00000000 00​:00 0
[stack]
7ffd2772a000-7ffd2772d000 r--p 00000000 00​:00 0
[vvar]
7ffd2772d000-7ffd2772f000 r-xp 00000000 00​:00 0
[vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00​:00 0
[vsyscall]
Aborted

**********More-info**********
root@​instance-2​:~/fuzz_perl# perl -e '* |= 2; $| .= *|=1;'
Modification of a read-only value attempted at -e line 1.

Please confirm the bug. And by the way, could you explain what the
following snippet do​:
* |= 2;

Thanks,
Manh Nguyen

@p5pRT
Copy link
Author

p5pRT commented Jul 8, 2019

From @iabyn

On Sat, Jul 06, 2019 at 12​:34​:46PM -0700, Nguyen Duc Manh wrote​:

**********Reproduce-1**********
root@​instance-2​:~/fuzz_perl# ./perl/perl -e '"" =~ /$a{$| = 1} $b{$| .= *
|= 2}/'
**********Reproduce-2**********
root@​instance-2​:~/fuzz_perl# ./perl/perl -e '$| .= *|= 1'
ASAN​:DEADLYSIGNAL
**********Reproduce-3**********
root@​instance-2​:~/fuzz_perl# perl -e '"" =~ /$a{$| = 1} $b{$| .= * |= 2}/'
**********More-info**********
root@​instance-2​:~/fuzz_perl# perl -e '* |= 2; $| .= *|=1;'
Modification of a read-only value attempted at -e line 1.

These all look like stack-not-refcounted bugs, and I don't think they're
security issues.

Please confirm the bug. And by the way, could you explain what the
following snippet do​:
* |= 2;

It aliases the '|' typeglob (i.e. $| etc) to the typeglob '2' (i.e. $2
etc).

So its the same as

  *| = *2

--
Justice is when you get what you deserve.
Law is when you get what you pay for.e

@p5pRT
Copy link
Author

p5pRT commented Jul 8, 2019

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

@p5pRT
Copy link
Author

p5pRT commented Jul 8, 2019

From imdb95@gmail.com

On Mon, Jul 8, 2019 at 4​:18 PM Dave Mitchell via RT <
perl5-security-report-followup@​perl.org> wrote​:

These all look like stack-not-refcounted bugs, and I don't think
they're security issues.

Can you explain why it is not a security issue when heap-use-after-free
(WRITE of size 1) happens?

Thanks,
Manh Nguyen

@p5pRT
Copy link
Author

p5pRT commented Aug 6, 2019

From @tonycoz

On Mon, 08 Jul 2019 03​:34​:38 -0700, imdb95@​gmail.com wrote​:

On Mon, Jul 8, 2019 at 4​:18 PM Dave Mitchell via RT <
perl5-security-report-followup@​perl.org> wrote​:

These all look like stack-not-refcounted bugs, and I don't think
they're security issues.

Can you explain why it is not a security issue when heap-use-after-free
(WRITE of size 1) happens?

We've had some debate on whether to treat such issues as security issues.

The base cause of this and similar bugs is that the perl parameter/return stack isn't reference counted, and when normal variables are pushed onto the stack they don't get a reference count increment with delayed decrement like typical return values do.

So in your code the value of $| is pushed onto the stack, the next assignment assigns to *|, decrementing the referenced count of $| and freeing it, leading to the error you reported.

But such problems are implicit in the structure of the code rather than due to any data that the code might read.

For example in your case doing​:

  *| = 2;
  $| = *|;

prevents the problem;

It may be that the code in some other case might only see this type of problem with a limited set of inputs (eg. a function that's included in a list might only clear an array also included in that list in a limited set of circumstances), but the problem is still implicit in the structure of the code.

My example[1]​:

  sub foo {
  @​x = () if $_[0];
  1;
  }

  # dangerous​:
  @​y = ( @​x, foo($x) );
  # safe
  @​y = @​x;
  push @​y, foo($x);

While we don't treat this issue as a security issue, we do still consider it a bug, but a very complex to fix bug, especially if we want to a) retain compatibility with existing XS code on CPAN and b) still allow that code adapt to use a refcounted stack but retain compatibility with older versions of perl.

Tony

[1] this code is bad due to the action at a distance anyway

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2019

From @iabyn

On Mon, Aug 05, 2019 at 06​:29​:21PM -0700, Tony Cook via RT wrote​:

On Mon, 08 Jul 2019 03​:34​:38 -0700, imdb95@​gmail.com wrote​:

On Mon, Jul 8, 2019 at 4​:18 PM Dave Mitchell via RT <
perl5-security-report-followup@​perl.org> wrote​:

These all look like stack-not-refcounted bugs, and I don't think
they're security issues.

Can you explain why it is not a security issue when heap-use-after-free
(WRITE of size 1) happens?

We've had some debate on whether to treat such issues as security issues.

The base cause of this and similar bugs is that the perl parameter/return stack isn't reference counted, and when normal variables are pushed onto the stack they don't get a reference count increment with delayed decrement like typical return values do.

I propose that this ticket gets moved to the public queue.

--
O Unicef Clearasil!
Gibberish and Drivel!
  -- "Bored of the Rings"

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2019

From @tonycoz

On Wed, 07 Aug 2019 01​:58​:17 -0700, davem wrote​:

On Mon, Aug 05, 2019 at 06​:29​:21PM -0700, Tony Cook via RT wrote​:

On Mon, 08 Jul 2019 03​:34​:38 -0700, imdb95@​gmail.com wrote​:

On Mon, Jul 8, 2019 at 4​:18 PM Dave Mitchell via RT <
perl5-security-report-followup@​perl.org> wrote​:

These all look like stack-not-refcounted bugs, and I don't think
they're security issues.

Can you explain why it is not a security issue when heap-use-after-
free
(WRITE of size 1) happens?

We've had some debate on whether to treat such issues as security
issues.

The base cause of this and similar bugs is that the perl
parameter/return stack isn't reference counted, and when normal
variables are pushed onto the stack they don't get a reference count
increment with delayed decrement like typical return values do.

I propose that this ticket gets moved to the public queue.

Now public.

Tony

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