Navigation Menu

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 Perl_sv_setpv_bufsize (sv.c:4956) #15747

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

heap-use-after-free Perl_sv_setpv_bufsize (sv.c:4956) #15747

p5pRT opened this issue Dec 4, 2016 · 11 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 4, 2016

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

Searchable as RT130256$

@p5pRT
Copy link
Author

p5pRT commented Dec 4, 2016

From @geeknik

Triggered with Perl v5.25.7-26-g7332835.

./perl -e '@​0=$0|=*0=H or()'

==17224==ERROR​: AddressSanitizer​: heap-use-after-free on address
0x60200000e630 at pc 0x0000009399d4 bp 0x7ffc6e92ce70 sp 0x7ffc6e92ce68
WRITE of size 1 at 0x60200000e630 thread T0
  #0 0x9399d3 in Perl_sv_setpv_bufsize /root/perl/sv.c​:4956​:5
  #1 0xb1b832 in Perl_do_vop /root/perl/doop.c​:1011​:9
  #2 0x9d13ef in Perl_pp_bit_or /root/perl/pp.c​:2471​:2
  #3 0x7f63bb in Perl_runops_debug /root/perl/dump.c​:2260​:23
  #4 0x5a06c3 in S_run_body /root/perl/perl.c​:2526​:2
  #5 0x5a06c3 in perl_run /root/perl/perl.c​:2449
  #6 0x4de6cd in main /root/perl/perlmain.c​:123​:9
  #7 0x7f62d5d19b44 in __libc_start_main
/build/glibc-daoqzt/glibc-2.19/csu/libc-start.c​:287
  #8 0x4de33c in _start (/root/perl/perl+0x4de33c)

0x60200000e630 is located 0 bytes inside of 10-byte region
[0x60200000e630,0x60200000e63a)
freed by thread T0 here​:
  #0 0x4c0a3b in __interceptor_free (/root/perl/perl+0x4c0a3b)
  #1 0x7fb019 in Perl_safesysfree /root/perl/util.c​:388​:2
  #2 0x955f30 in Perl_sv_free2 /root/perl/sv.c​:7056​:9

previously allocated by thread T0 here​:
  #0 0x4c0cbb in malloc (/root/perl/perl+0x4c0cbb)
  #1 0x7fa227 in Perl_safesysmalloc /root/perl/util.c​:153​:21

SUMMARY​: AddressSanitizer​: heap-use-after-free /root/perl/sv.c​:4956
Perl_sv_setpv_bufsize
Shadow bytes around the buggy address​:
  0x0c047fff9c70​: fa fa 05 fa fa fa 00 05 fa fa 04 fa fa fa 05 fa
  0x0c047fff9c80​: fa fa 05 fa fa fa 00 00 fa fa 00 02 fa fa 05 fa
  0x0c047fff9c90​: fa fa 00 02 fa fa 00 fa fa fa 00 04 fa fa 07 fa
  0x0c047fff9ca0​: fa fa 00 02 fa fa 00 03 fa fa 06 fa fa fa 00 03
  0x0c047fff9cb0​: fa fa 05 fa fa fa 00 02 fa fa 00 05 fa fa 00 06
=>0x0c047fff9cc0​: fa fa 00 04 fa fa[fd]fd fa fa fd fa fa fa 00 02
  0x0c047fff9cd0​: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 06
  0x0c047fff9ce0​: fa fa 00 04 fa fa 00 02 fa fa 00 02 fa fa 00 00
  0x0c047fff9cf0​: fa fa fd fa fa fa 00 02 fa fa fd fa fa fa 00 02
  0x0c047fff9d00​: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff9d10​: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
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
==17224==ABORTING

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2016

From @tonycoz

On Sun, 04 Dec 2016 01​:53​:36 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-26-g7332835.

./perl -e '@​0=$0|=*0=H or()'

Stack traces from valgrind​:

==19883== Invalid write of size 1
==19883== at 0x5E3822​: Perl_sv_setpv_bufsize (sv.c​:4956)
==19883== by 0x6AB21D​: Perl_do_vop (doop.c​:1011)
==19883== by 0x62A6CB​: Perl_pp_bit_or (pp.c​:2471)
==19883== by 0x556D8A​: Perl_runops_debug (dump.c​:2260)
==19883== by 0x460EB1​: S_run_body (perl.c​:2526)
==19883== by 0x460494​: perl_run (perl.c​:2449)
==19883== by 0x41EFDD​: main (perlmain.c​:123)
==19883== Address 0x5f793b0 is 0 bytes inside a block of size 10 free'd
==19883== at 0x4C29E90​: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19883== by 0x558891​: Perl_safesysfree (util.c​:388)
==19883== by 0x5F1B8E​: Perl_sv_clear (sv.c​:6754)
==19883== by 0x5F37A1​: Perl_sv_free2 (sv.c​:7056)
==19883== by 0x46CF09​: S_SvREFCNT_dec (inline.h​:189)
==19883== by 0x480C7A​: Perl_gp_free (gv.c​:2598)
==19883== by 0x5DF75B​: Perl_sv_setsv_flags (sv.c​:4569)
==19883== by 0x5A0C78​: Perl_pp_sassign (pp_hot.c​:226)
==19883== by 0x556D8A​: Perl_runops_debug (dump.c​:2260)
==19883== by 0x460EB1​: S_run_body (perl.c​:2526)
==19883== by 0x460494​: perl_run (perl.c​:2449)
==19883== by 0x41EFDD​: main (perlmain.c​:123)

This looks like another stack-not-refcounted issue.

Tony

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Jan 31, 2017

From @tonycoz

On Sun, 04 Dec 2016 16​:20​:22 -0800, tonyc wrote​:

On Sun, 04 Dec 2016 01​:53​:36 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-26-g7332835.

./perl -e '@​0=$0|=*0=H or()'

Simplifies to​:

./perl -e '$0|=*0="H"'

This looks like another stack-not-refcounted issue.

And so it is, now public.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 31, 2017

From @demerphq

On 31 Jan 2017 1​:04 p.m., "Tony Cook via RT" <perlbug-followup@​perl.org>
wrote​:

On Sun, 04 Dec 2016 16​:20​:22 -0800, tonyc wrote​:

On Sun, 04 Dec 2016 01​:53​:36 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-26-g7332835.

./perl -e '@​0=$0|=*0=H or()'

Simplifies to​:

./perl -e '$0|=*0="H"'

This looks like another stack-not-refcounted issue.

And so it is, now public

Is it *just* a stack not refcounted bug or is it more. What is supposed to
happen when you assign a string to a glob? I know what is supposed to
happen when it's a ref or another glob, but a string?

Yves

@p5pRT
Copy link
Author

p5pRT commented Jan 31, 2017

From @tonycoz

On Tue, Jan 31, 2017 at 07​:30​:56AM +0100, demerphq wrote​:

On 31 Jan 2017 1​:04 p.m., "Tony Cook via RT" <perlbug-followup@​perl.org>
wrote​:

On Sun, 04 Dec 2016 16​:20​:22 -0800, tonyc wrote​:

On Sun, 04 Dec 2016 01​:53​:36 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-26-g7332835.

./perl -e '@​0=$0|=*0=H or()'

Simplifies to​:

./perl -e '$0|=*0="H"'

This looks like another stack-not-refcounted issue.

And so it is, now public

Is it *just* a stack not refcounted bug or is it more. What is supposed to
happen when you assign a string to a glob? I know what is supposed to
happen when it's a ref or another glob, but a string?

It looks like the same as​:

  $0|=*0=*H

Tony

@p5pRT
Copy link
Author

p5pRT commented Feb 1, 2017

From @iabyn

On Tue, Jan 31, 2017 at 07​:30​:56AM +0100, demerphq wrote​:

Is it *just* a stack not refcounted bug or is it more. What is supposed to
happen when you assign a string to a glob? I know what is supposed to
happen when it's a ref or another glob, but a string?

It uses the string as the name of a typeglob. Sp

  *foo = "bar";

is equivalent to

  *foo = *bar;

And both make the GP of *foo point to the GP of *bar, freeing the old GP
and any of its contents.

--
Overhead, without any fuss, the stars were going out.
  -- Arthur C Clarke

@p5pRT
Copy link
Author

p5pRT commented Feb 1, 2017

From @demerphq

On 1 Feb 2017 22​:29, "Dave Mitchell" <davem@​iabyn.com> wrote​:

On Tue, Jan 31, 2017 at 07​:30​:56AM +0100, demerphq wrote​:

Is it *just* a stack not refcounted bug or is it more. What is supposed
to
happen when you assign a string to a glob? I know what is supposed to
happen when it's a ref or another glob, but a string?

It uses the string as the name of a typeglob. Sp

  *foo = "bar";

is equivalent to

  *foo = *bar;

And both make the GP of *foo point to the GP of *bar, freeing the old GP
and any of its contents

Wow. Not what I expected. Do you happen to know where that is documented?
Is it intentional or coincidental that it works like that?

Yves

@p5pRT
Copy link
Author

p5pRT commented Feb 1, 2017

From @iabyn

On Wed, Feb 01, 2017 at 05​:21​:47PM +0100, demerphq wrote​:

On 1 Feb 2017 22​:29, "Dave Mitchell" <davem@​iabyn.com> wrote​:

It uses the string as the name of a typeglob. Sp

\*foo = "bar";

is equivalent to

\*foo = \*bar;

And both make the GP of *foo point to the GP of *bar, freeing the old GP
and any of its contents

Wow. Not what I expected. Do you happen to know where that is documented?

No idea - I just looked at what it actually does.

Is it intentional or coincidental that it works like that?

No idea (I seem to keep saying that). There does seem to be a lot of
'if you're expecting a typeglob and you get a string, treat it as the name
of the typeglob' behaviour in perl though, c.f.

  readline 'FH'

behaving like

  readline *FH

I hate typeglobs.

--
This email is confidential, and now that you have read it you are legally
obliged to shoot yourself. Or shoot a lawyer, if you prefer. If you have
received this email in error, place it in its original wrapping and return
for a full refund. By opening this email, you accept that Elvis lives.

@p5pRT
Copy link
Author

p5pRT commented Oct 2, 2017

From @geeknik

Just triggered this bug in v5.27.4-29-gdc41635.

./perl -e '$$.=*$=*$$'

=================================================================
==30274==ERROR​: AddressSanitizer​: heap-use-after-free on address
0x60200000e1f0 at pc 0xbcce5c bp 0x7fff60a28b20 sp 0x7fff60a28b18
WRITE of size 1 at 0x60200000e1f0 thread T0
  #0 0xbcce5b in Perl_sv_setpv_bufsize /root/perl/sv.c​:4958
  #1 0xaa2e02 in Perl_pp_concat /root/perl/pp_hot.c​:292
  #2 0x92ee8e in Perl_runops_debug /root/perl/dump.c​:2486
  #3 0x5a9bed in S_run_body /root/perl/perl.c​:2592
  #4 0x5a9bed in perl_run /root/perl/perl.c​:2520
  #5 0x4362e9 in main /root/perl/perlmain.c​:123
  #6 0x7f6fce22cb44 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
  #7 0x4372fa (/root/perl/perl+0x4372fa)

0x60200000e1f0 is located 0 bytes inside of 10-byte region
[0x60200000e1f0,0x60200000e1fa)
freed by thread T0 here​:
  #0 0x7f6fcf37e527 in __interceptor_free
(/usr/lib/x86_64-linux-gnu/libasan.so.1+0x54527)
  #1 0xb254d0 in Perl_sv_clear /root/perl/sv.c​:6825
  #2 0xb28547 in Perl_sv_free2 /root/perl/sv.c​:7127
  #3 0x5b91cb in S_SvREFCNT_dec /root/perl/inline.h​:191
  #4 0x5b91cb in Perl_gp_free /root/perl/gv.c​:2638
  #5 0xbc0d7e in S_glob_assign_glob /root/perl/sv.c​:3950
  #6 0xb75020 in Perl_sv_setsv_flags /root/perl/sv.c​:4461
  #7 0xa9c427 in Perl_pp_sassign /root/perl/pp_hot.c​:226
  #8 0x92ee8e in Perl_runops_debug /root/perl/dump.c​:2486
  #9 0x5a9bed in S_run_body /root/perl/perl.c​:2592
  #10 0x5a9bed in perl_run /root/perl/perl.c​:2520
  #11 0x4362e9 in main /root/perl/perlmain.c​:123
  #12 0x7f6fce22cb44 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21b44)

previously allocated by thread T0 here​:
  #0 0x7f6fcf37e73f in malloc
(/usr/lib/x86_64-linux-gnu/libasan.so.1+0x5473f)
  #1 0x96d04d in Perl_safesysmalloc /root/perl/util.c​:153
  #2 0xb888b7 in Perl_sv_grow /root/perl/sv.c​:1603
  #3 0xb8e1cc in Perl_sv_2pv_flags /root/perl/sv.c​:3090
  #4 0x613b62 in Perl_gv_fetchsv /root/perl/gv.c​:1569
  #5 0xc7c54d in S_rv2gv /root/perl/pp.c​:191
  #6 0xc7c54d in Perl_pp_rv2gv /root/perl/pp.c​:210
  #7 0x92ee8e in Perl_runops_debug /root/perl/dump.c​:2486
  #8 0x5a9bed in S_run_body /root/perl/perl.c​:2592
  #9 0x5a9bed in perl_run /root/perl/perl.c​:2520
  #10 0x4362e9 in main /root/perl/perlmain.c​:123
  #11 0x7f6fce22cb44 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21b44)

SUMMARY​: AddressSanitizer​: heap-use-after-free /root/perl/sv.c​:4958
Perl_sv_setpv_bufsize

And if I change it ever so slightly, we get a null pointer dereference
instead​:

./perl -e '$$.=*$=0'

ASAN​:SIGSEGV

==21206==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000000
(pc 0x000000bcc503 sp 0x7ffd0cde5380 bp 0x7ffd0cde53b0 T0)
  #0 0xbcc502 in Perl_sv_setpv_bufsize /root/perl/sv.c​:4959
  #1 0xaa2e02 in Perl_pp_concat /root/perl/pp_hot.c​:292
  #2 0x92ee8e in Perl_runops_debug /root/perl/dump.c​:2486
  #3 0x5a9bed in S_run_body /root/perl/perl.c​:2592
  #4 0x5a9bed in perl_run /root/perl/perl.c​:2520
  #5 0x4362e9 in main /root/perl/perlmain.c​:123
  #6 0x7fe49ff72b44 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
  #7 0x4372fa (/root/perl/perl+0x4372fa)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV /root/perl/sv.c​:4959 Perl_sv_setpv_bufsize
==21206==ABORTING

@lightsey
Copy link
Contributor

lightsey commented Jun 1, 2020

This example of the same problem was submitted by Dominik Chylinski to the Perl security team:

jd@toucan:~/src/git/lab/perl5 (blead)$ ./perl -e '$0.=do{*0={}.$0[0]^p}if%0=0'
=================================================================
==6532==ERROR: AddressSanitizer: heap-use-after-free on address 0xf5b00910 at pc 0x088381f1 bp 0xffc126a8 sp 0xffc126a0
WRITE of size 1 at 0xf5b00910 thread T0
    #0 0x88381f0 in Perl_sv_setpv_bufsize /home/jd/src/git/lab/perl5/sv.c:4948:17
    #1 0x879c791 in S_do_concat /home/jd/src/git/lab/perl5/pp_hot.c:299:13
    #2 0x879b7e8 in Perl_pp_concat /home/jd/src/git/lab/perl5/pp_hot.c:333:5
    #3 0x87961ff in Perl_runops_standard /home/jd/src/git/lab/perl5/run.c:41:26
    #4 0x825063d in S_run_body /home/jd/src/git/lab/perl5/perl.c:2759:2
    #5 0x824e256 in perl_run /home/jd/src/git/lab/perl5/perl.c:2682:2
    #6 0x8154029 in main /home/jd/src/git/lab/perl5/perlmain.c:127:9
    #7 0xf7bfab40 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x1ab40)
    #8 0x807fd11 in _start (/home/jd/src/git/lab/perl5/perl+0x807fd11)

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

2 participants