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_setsv_cow (sv.c:4872) #16860

Open
p5pRT opened this issue Mar 3, 2019 · 6 comments
Open

heap-use-after-free in Perl_sv_setsv_cow (sv.c:4872) #16860

p5pRT opened this issue Mar 3, 2019 · 6 comments
Labels

Comments

@p5pRT
Copy link

p5pRT commented Mar 3, 2019

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

Searchable as RT133878$

@p5pRT
Copy link
Author

p5pRT commented Mar 3, 2019

From @dur-randir

Created by @dur-randir

While fuzzing perl v5.29.8-21-gde59f38ed9 built with afl and run
under libdislocator, I found the following program (also attached to
this message)

00000000 73 2f 2f 30 2f 2c 40 2f 3d 30 2c 73 00 30 00 00 |s//0/,@​/=0,s.0..|
00000010 2d 73 70 6c 69 74 40 30 3d 76 61 6c 75 65 73 40 |-split@​0=values@​|
00000020 30 66 6f 72 2d 30 2c 40 2f 3d 40 30 3d 2f 2f |0for-0,@​/=@​0=//|

to perform an access outside of an allocated memory slot. ASAN diagnostics are​:

==29541==ERROR​: AddressSanitizer​: heap-use-after-free on address
0x60200000d6f9 at pc 0x000000a0367c bp 0x7ffc52a8a610 sp
0x7ffc52a8a608
WRITE of size 1 at 0x60200000d6f9 thread T0
  #0 0xa0367b in Perl_sv_setsv_cow /home/afl/afl-asan/sv.c​:4872​:18
  #1 0xca5a4b in S_reg_set_capture_string /home/afl/afl-asan/regexec.c​:3058​:36
  #2 0xc6d929 in Perl_regexec_flags /home/afl/afl-asan/regexec.c​:3834​:9
  #3 0x992658 in Perl_pp_subst /home/afl/afl-asan/pp_hot.c​:4231​:10
  #4 0x88f844 in Perl_runops_debug /home/afl/afl-asan/dump.c​:2537​:23
  #5 0x5f1015 in S_run_body /home/afl/afl-asan/perl.c​:2692​:2
  #6 0x5f1015 in perl_run /home/afl/afl-asan/perl.c​:2615
  #7 0x50b60a in main /home/afl/afl-asan/perlmain.c​:127​:9
  #8 0x7f58c9d2909a in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2409a)
  #9 0x43bdc9 in _start (/home/afl/afl-asan/perl+0x43bdc9)

0x60200000d6f9 is located 9 bytes inside of 10-byte region
[0x60200000d6f0,0x60200000d6fa)
freed by thread T0 here​:
  #0 0x4da200 in __interceptor_cfree.localalias.0
(/home/afl/afl-asan/perl+0x4da200)
  #1 0x89697a in Perl_safesysfree /home/afl/afl-asan/util.c​:385​:2
  #2 0xa02570 in Perl_sv_setsv_cow /home/afl/afl-asan/sv.c​:4846​:6
  #3 0xca5a4b in S_reg_set_capture_string /home/afl/afl-asan/regexec.c​:3058​:36
  #4 0xc6d929 in Perl_regexec_flags /home/afl/afl-asan/regexec.c​:3834​:9
  #5 0x992658 in Perl_pp_subst /home/afl/afl-asan/pp_hot.c​:4231​:10
  #6 0x88f844 in Perl_runops_debug /home/afl/afl-asan/dump.c​:2537​:23
  #7 0x5f1015 in S_run_body /home/afl/afl-asan/perl.c​:2692​:2
  #8 0x5f1015 in perl_run /home/afl/afl-asan/perl.c​:2615
  #9 0x50b60a in main /home/afl/afl-asan/perlmain.c​:127​:9
  #10 0x7f58c9d2909a in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2409a)

previously allocated by thread T0 here​:
  #0 0x4da398 in malloc (/home/afl/afl-asan/perl+0x4da398)
  #1 0x89580e in Perl_safesysmalloc /home/afl/afl-asan/util.c​:153​:21
  #2 0x9bb6e9 in Perl_sv_grow /home/afl/afl-asan/sv.c​:1599​:17
  #3 0x9d9559 in Perl_sv_setpvn /home/afl/afl-asan/sv.c​:4959​:12
  #4 0xa2d1b2 in Perl_newSVpvn_flags /home/afl/afl-asan/sv.c​:9301​:5
  #5 0x994943 in Perl_pp_subst /home/afl/afl-asan/pp_hot.c​:4391​:9
  #6 0x88f844 in Perl_runops_debug /home/afl/afl-asan/dump.c​:2537​:23
  #7 0x5f1015 in S_run_body /home/afl/afl-asan/perl.c​:2692​:2
  #8 0x5f1015 in perl_run /home/afl/afl-asan/perl.c​:2615
  #9 0x50b60a in main /home/afl/afl-asan/perlmain.c​:127​:9
  #10 0x7f58c9d2909a in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2409a)

This is a regression between 5.24 and 5.26, bisect points to

commit 8b0c337
Author​: David Mitchell <davem@​iabyn.com>
Date​: Wed Oct 5 10​:10​:56 2016 +0100

  Better optimise array and hash assignment

  [perl #127999] Slowdown in split + list assign

  Re-implement the code that handles e.g.

  (..., @​a) = (...);
  (..., %h) = (...);

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl 5.29.9:

Configured by dur-randir at Wed Feb 27 14:51:01 MSK 2019.

Summary of my perl5 (revision 5 version 29 subversion 9) configuration:
  Commit id: c1e47bad34ce1d9c84ed57c9b8978bcbd5a02e98
  Platform:
    osname=darwin
    osvers=13.4.0
    archname=darwin-thread-multi-2level
    uname='darwin isengard.local 13.4.0 darwin kernel version 13.4.0:
mon jan 11 18:17:34 pst 2016; root:xnu-2422.115.15~1release_x86_64
x86_64 '
    config_args='-de -Dusedevel -DDEBUGGING -Dusethreads'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.9
-DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include -DPERL_USE_SAFE_PUTENV'
    optimize='-O3 -g'
    cppflags='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.9
-DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include'
    ccversion=''
    gccversion='4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags =' -mmacosx-version-min=10.9 -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/lib
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib
/usr/lib
    libs=-lpthread -lgdbm -ldbm -ldl -lm -lutil -lc
    perllibs=-lpthread -ldl -lm -lutil -lc
    libc=
    so=dylib
    useshrplib=false
    libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=bundle
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags=' -mmacosx-version-min=10.9 -bundle -undefined
dynamic_lookup -L/usr/local/lib -fstack-protector'



@INC for perl 5.29.9:
    lib
    /usr/local/lib/perl5/site_perl/5.29.9/darwin-thread-multi-2level
    /usr/local/lib/perl5/site_perl/5.29.9
    /usr/local/lib/perl5/5.29.9/darwin-thread-multi-2level
    /usr/local/lib/perl5/5.29.9


Environment for perl 5.29.9:
    DYLD_LIBRARY_PATH (unset)
    HOME=/Users/dur-randir
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/Users/dur-randir/perlbrew/bin:/Users/dur-randir/perlbrew/perls/perl-5.22.1/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/texbin
    PERLBREW_HOME=/Users/dur-randir/.perlbrew
    PERLBREW_MANPATH=/Users/dur-randir/perlbrew/perls/perl-5.22.1/man
    PERLBREW_PATH=/Users/dur-randir/perlbrew/bin:/Users/dur-randir/perlbrew/perls/perl-5.22.1/bin
    PERLBREW_PERL=perl-5.22.1
    PERLBREW_ROOT=/Users/dur-randir/perlbrew
    PERLBREW_SHELLRC_VERSION=0.84
    PERLBREW_VERSION=0.84
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Mar 3, 2019

From @dur-randir

0070

@p5pRT
Copy link
Author

p5pRT commented Apr 17, 2019

From @tonycoz

On Sun, 03 Mar 2019 03​:36​:04 -0800, randir wrote​:

While fuzzing perl v5.29.8-21-gde59f38ed9 built with afl and run
under libdislocator, I found the following program (also attached to
this message)

00000000 73 2f 2f 30 2f 2c 40 2f 3d 30 2c 73 00 30 00 00
|s//0/,@​/=0,s.0..|
00000010 2d 73 70 6c 69 74 40 30 3d 76 61 6c 75 65 73 40 |-
split@​0=values@​|
00000020 30 66 6f 72 2d 30 2c 40 2f 3d 40 30 3d 2f 2f |0for-
0,@​/=@​0=//|

to perform an access outside of an allocated memory slot. ASAN
diagnostics are​:

==29541==ERROR​: AddressSanitizer​: heap-use-after-free on address
0x60200000d6f9 at pc 0x000000a0367c bp 0x7ffc52a8a610 sp
0x7ffc52a8a608
WRITE of size 1 at 0x60200000d6f9 thread T0
#0 0xa0367b in Perl_sv_setsv_cow /home/afl/afl-asan/sv.c​:4872​:18
#1 0xca5a4b in S_reg_set_capture_string /home/afl/afl-
asan/regexec.c​:3058​:36
#2 0xc6d929 in Perl_regexec_flags /home/afl/afl-
asan/regexec.c​:3834​:9
#3 0x992658 in Perl_pp_subst /home/afl/afl-asan/pp_hot.c​:4231​:10
#4 0x88f844 in Perl_runops_debug /home/afl/afl-asan/dump.c​:2537​:23
#5 0x5f1015 in S_run_body /home/afl/afl-asan/perl.c​:2692​:2
#6 0x5f1015 in perl_run /home/afl/afl-asan/perl.c​:2615
#7 0x50b60a in main /home/afl/afl-asan/perlmain.c​:127​:9
#8 0x7f58c9d2909a in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2409a)
#9 0x43bdc9 in _start (/home/afl/afl-asan/perl+0x43bdc9)

0x60200000d6f9 is located 9 bytes inside of 10-byte region
[0x60200000d6f0,0x60200000d6fa)
freed by thread T0 here​:
#0 0x4da200 in __interceptor_cfree.localalias.0
(/home/afl/afl-asan/perl+0x4da200)
#1 0x89697a in Perl_safesysfree /home/afl/afl-asan/util.c​:385​:2
#2 0xa02570 in Perl_sv_setsv_cow /home/afl/afl-asan/sv.c​:4846​:6
#3 0xca5a4b in S_reg_set_capture_string /home/afl/afl-
asan/regexec.c​:3058​:36
#4 0xc6d929 in Perl_regexec_flags /home/afl/afl-
asan/regexec.c​:3834​:9
#5 0x992658 in Perl_pp_subst /home/afl/afl-asan/pp_hot.c​:4231​:10
#6 0x88f844 in Perl_runops_debug /home/afl/afl-asan/dump.c​:2537​:23
#7 0x5f1015 in S_run_body /home/afl/afl-asan/perl.c​:2692​:2
#8 0x5f1015 in perl_run /home/afl/afl-asan/perl.c​:2615
#9 0x50b60a in main /home/afl/afl-asan/perlmain.c​:127​:9
#10 0x7f58c9d2909a in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2409a)

previously allocated by thread T0 here​:
#0 0x4da398 in malloc (/home/afl/afl-asan/perl+0x4da398)
#1 0x89580e in Perl_safesysmalloc /home/afl/afl-asan/util.c​:153​:21
#2 0x9bb6e9 in Perl_sv_grow /home/afl/afl-asan/sv.c​:1599​:17
#3 0x9d9559 in Perl_sv_setpvn /home/afl/afl-asan/sv.c​:4959​:12
#4 0xa2d1b2 in Perl_newSVpvn_flags /home/afl/afl-asan/sv.c​:9301​:5
#5 0x994943 in Perl_pp_subst /home/afl/afl-asan/pp_hot.c​:4391​:9
#6 0x88f844 in Perl_runops_debug /home/afl/afl-asan/dump.c​:2537​:23
#7 0x5f1015 in S_run_body /home/afl/afl-asan/perl.c​:2692​:2
#8 0x5f1015 in perl_run /home/afl/afl-asan/perl.c​:2615
#9 0x50b60a in main /home/afl/afl-asan/perlmain.c​:127​:9
#10 0x7f58c9d2909a in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2409a)

This is a regression between 5.24 and 5.26, bisect points to

commit 8b0c337
Author​: David Mitchell <davem@​iabyn.com>
Date​: Wed Oct 5 10​:10​:56 2016 +0100

Better optimise array and hash assignment

[perl #127999] Slowdown in split + list assign

Re-implement the code that handles e.g.

(..., @​a) = (...);
(..., %h) = (...);

I suspect this is a stack not refcounted issue.

The code is​:

s//0/,@​/=0,s.0..-split@​0=values@​0for-0,@​/=@​0=//

which groups like​:

(s//0/, (@​/ = 0), (s/0// - split((@​0 = values(@​0)), $_, 0))) foreach ((0, (@​/ = (@​0 = //))));

First the arguments to foreach are processed, setting @​/ and @​0 to copies of PL_sv_true, and the value 0 and the value of @​/ is pushed on the stack.

For each iteration $_ is aliased to those values.

On the first iteration both @​0 and @​/ are assigned to, so the values on the stack are released.

The next iteration then tries to process the now invalid value from @​/, and makes a copy of it in the saved_copy member of the regexp (this might not be quite correct, but the next bit is observed behaviour.)

Unfortunately this seems to have been allocated at the same location as the original SV from @​/, so the same sv is passed as both parameters to sv_setsv_cow(), which doesn't handle that case, releasing the PVX of the destination SV before trying to duplicate it from the source SV, which fails horribly because they're the same SV.

Tony

@p5pRT
Copy link
Author

p5pRT commented Apr 17, 2019

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

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2019

From @iabyn

On Tue, Apr 16, 2019 at 09​:58​:05PM -0700, Tony Cook via RT wrote​:

I suspect this is a stack not refcounted issue.

I propose we move this ticket to the public queue

--
Modern art​:
  "That's easy, I could have done that!"
  "Ah, but you didn't!"

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2019

From @tonycoz

On Wed, 07 Aug 2019 02​:41​:07 -0700, davem wrote​:

On Tue, Apr 16, 2019 at 09​:58​:05PM -0700, Tony Cook via RT wrote​:

I suspect this is a stack not refcounted issue.

I propose we move this ticket 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
Projects
None yet
Development

No branches or pull requests

2 participants