Perl / perl5

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

heap-buffer-overflow in Perl_sv_backoff #17844

Closed lightsey closed 4 years ago

lightsey commented 4 years ago

Description

This bug was reported to the Perl security team in April of 2019 by @dur-randir. The original report was assigned rt.perl.org#134000, and after the migration to github the issue became Perl/perl5-security#111.

There isn't any clear way to reach this bug with normal use of Perl formats, so this doesn't need to be handled as a security issue.

The problem reported is a heap use-after-free bug that became visible after commit 9b4bdfd44e0e6d44a447f231c281f967c7ca35c9. The overflow is still reproducible with current 32bit blead builds instrumented with ASAN.

@tonycoz analyzed the original report, produced a patch for the issue, and noted in his analysis that "The cause of the problem is setting SvCUR() before we've resized the buffer."

I will create a pull request with Tony's patch.

Steps to Reproduce

jd@toucan:~/src/git/lab/perl5 (blead)$ ./perl -e 'formline "0^0",\\0^\\0 for 1..10;'
=================================================================
==9246==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf3c0506c at pc 0x08120ba4 bp 0xffc8c308 sp 0xffc8bee0
READ of size 16 at 0xf3c0506c thread T0
    #0 0x8120ba3 in __asan_memmove (/home/jd/src/git/lab/perl5/perl+0x8120ba3)
    #1 0x84855b8 in Perl_sv_backoff /home/jd/src/git/lab/perl5/sv.c:1535:5
    #2 0x84855b8 in Perl_sv_grow /home/jd/src/git/lab/perl5/sv.c:1569
    #3 0x85bb4dd in Perl_do_vop /home/jd/src/git/lab/perl5/doop.c:1098:11
    #4 0x84ee346 in Perl_pp_bit_or /home/jd/src/git/lab/perl5/pp.c:2403:2
    #5 0x8452874 in Perl_runops_standard /home/jd/src/git/lab/perl5/run.c:41:26
    #6 0x81e6386 in S_run_body /home/jd/src/git/lab/perl5/perl.c
    #7 0x81e5d5d in perl_run /home/jd/src/git/lab/perl5/perl.c:2684:2
    #8 0x8151d37 in main /home/jd/src/git/lab/perl5/perlmain.c:127:9
    #9 0xf7bc4b40 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x1ab40)
    #10 0x807dc91 in _start (/home/jd/src/git/lab/perl5/perl+0x807dc91)

0xf3c0506c is located 0 bytes to the right of 28-byte region [0xf3c05050,0xf3c0506c)
allocated by thread T0 here:
    #0 0x81218ba in realloc (/home/jd/src/git/lab/perl5/perl+0x81218ba)
    #1 0x83ea802 in Perl_safesysrealloc /home/jd/src/git/lab/perl5/util.c:279:18
    #2 0x84854a0 in Perl_sv_grow /home/jd/src/git/lab/perl5/sv.c:1613:17
    #3 0x85bb4dd in Perl_do_vop /home/jd/src/git/lab/perl5/doop.c:1098:11
    #4 0x84ee346 in Perl_pp_bit_or /home/jd/src/git/lab/perl5/pp.c:2403:2
    #5 0x8452874 in Perl_runops_standard /home/jd/src/git/lab/perl5/run.c:41:26
    #6 0x81e6386 in S_run_body /home/jd/src/git/lab/perl5/perl.c
    #7 0x81e5d5d in perl_run /home/jd/src/git/lab/perl5/perl.c:2684:2
    #8 0x8151d37 in main /home/jd/src/git/lab/perl5/perlmain.c:127:9
    #9 0xf7bc4b40 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x1ab40)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/jd/src/git/lab/perl5/perl+0x8120ba3) in __asan_memmove
Shadow bytes around the buggy address:
  0x3e7809b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3e7809c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3e7809d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3e7809e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3e7809f0: fa fa fa fa fa fa fa fa fd fd fd fd fa fa fd fd
=>0x3e780a00: fd fa fa fa 00 00 00 fa fa fa 00 00 00[04]fa fa
  0x3e780a10: 00 00 00 06 fa fa 00 00 00 00 fa fa 00 00 00 00
  0x3e780a20: fa fa 00 00 00 00 fa fa fd fd fd fa fa fa fa fa
  0x3e780a30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3e780a40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3e780a50: 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
  Shadow gap:              cc
==9246==ABORTING

Perl configuration

Summary of my perl5 (revision 5 version 32 subversion 0) configuration:
  Derived from: 41aa777b4de447bc68637ff0f3fe1575e1af76d4
  Platform:
    osname=linux
    osvers=4.19.0-9-amd64
    archname=x86_64-linux
    uname='linux toucan 4.19.0-9-amd64 #1 smp debian 4.19.118-2 (2020-04-29) x86_64 gnulinux '
    config_args='-des -Dusedevel -Dcc=clang -Accflags=-O3 -m32 -g -fsanitize=address -fno-omit-frame-pointer -Aldflags=-m32 -g -fsanitize=address -fno-omit-frame-pointer -Alddlflags=-shared -m32 -g -fsanitize=address  -fno-omit-frame-pointer'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=undef
    usemultiplicity=undef
    use64bitint=undef
    use64bitall=undef
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='clang'
    ccflags ='-O3 -m32 -g -fsanitize=address -fno-omit-frame-pointer -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
    optimize='-O2'
    cppflags='-O3 -m32 -g -fsanitize=address -fno-omit-frame-pointer -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='4.2.1 Compatible Clang 7.0.1 (tags/RELEASE_701/final)'
    gccosandvers=''
    intsize=4
    longsize=4
    ptrsize=4
    doublesize=8
    byteorder=1234
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=12
    longdblkind=3
    ivtype='long'
    ivsize=4
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=4
    prototype=define
  Linker and Libraries:
    ld='clang'
    ldflags =' -m32 -g -fsanitize=address -fno-omit-frame-pointer -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/llvm-7/lib/clang/7.0.1/lib /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
    libs=-lpthread -lnsl -lgdbm -ldl -lm -lcrypt -lutil -lc
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.28.so
    so=so
    useshrplib=false
    libperl=libperl.a
    gnulibc_version='2.28'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E'
    cccdlflags='-fPIC'
    lddlflags=' -shared -m32 -g -fsanitize=address -fno-omit-frame-pointer -L/usr/local/lib -fstack-protector-strong'

Characteristics of this binary (from libperl):
  Compile-time options:
    HAS_TIMES
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    PERL_USE_DEVEL
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
  Locally applied patches:
    uncommitted-changes
  Built under linux
  Compiled at Jun  7 2020 19:05:10
  %ENV:
    PERL5LIB="lib"
  @INC:
    lib
    /usr/local/lib/perl5/site_perl/5.32.0/x86_64-linux
    /usr/local/lib/perl5/site_perl/5.32.0
    /usr/local/lib/perl5/5.32.0/x86_64-linux
    /usr/local/lib/perl5/5.32.0
lightsey commented 4 years ago

Patch in: https://github.com/Perl/perl5/pull/17845

toddr commented 4 years ago

fixed with the merge of #17845