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_do_print (doio.c:1400) #15531

Closed
p5pRT opened this issue Aug 19, 2016 · 14 comments
Closed

heap-use-after-free Perl_do_print (doio.c:1400) #15531

p5pRT opened this issue Aug 19, 2016 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 19, 2016

Migrated from rt.perl.org#128997 (status was 'resolved')

Searchable as RT128997$

@p5pRT
Copy link
Author

p5pRT commented Aug 19, 2016

From @geeknik

The attached test case named orig55 triggers a heap-use-after-free
in Perl_do_print (doio.c​:1400). This was found with AFL, ASAN and
libdislocator.so affects v5.25.4 (v5.25.3-305-g8c6b0c7).

==1757==ERROR​: AddressSanitizer​: heap-use-after-free on address
0x61d00001d3a8 at pc 0x000000b23e59 bp 0x7ffc4fec9650 sp 0x7ffc4fec9648
READ of size 2 at 0x61d00001d3a8 thread T0
  #0 0xb23e58 in Perl_do_print /root/perl/doio.c​:1400​:3
  #1 0x7ff698 in Perl_write_to_stderr /root/perl/util.c​:1580​:2
  #2 0x801d0f in Perl_vwarn /root/perl/util.c​:1937​:2
  #3 0x802668 in Perl_vwarner /root/perl/util.c​:2050​:2
  #4 0x80218e in Perl_ck_warner_d /root/perl/util.c​:2002​:2
  #5 0x6a36df in Perl_yyerror_pvn /root/perl/toke.c​:11093​:2
  #6 0x691e87 in Perl_yyerror_pv /root/perl/toke.c​:10999​:12
  #7 0x691e87 in S_yywarn /root/perl/toke.c​:10984
  #8 0x691e87 in S_no_op /root/perl/toke.c​:520
  #9 0x62040a in Perl_yylex /root/perl/toke.c​:6614​:3
  #10 0x6ac9d5 in Perl_yyparse /root/perl/perly.c​:334​:19
  #11 0x59c4a1 in S_parse_body /root/perl/perl.c​:2372​:9
  #12 0x59283c in perl_parse /root/perl/perl.c​:1688​:2
  #13 0x4de835 in main /root/perl/perlmain.c​:121​:18
  #14 0x7f2c60cf8b44 in __libc_start_main
/build/glibc-uPj9cH/glibc-2.19/csu/libc-start.c​:287
  #15 0x4de4cc in _start (/root/perl/perl+0x4de4cc)

0x61d00001d3a8 is located 1832 bytes inside of 2048-byte region
[0x61d00001cc80,0x61d00001d480)
freed by thread T0 here​:
  #0 0x4c0bcb in __interceptor_free (/root/perl/perl+0x4c0bcb)
  #1 0x4e0d8d in Perl_opslab_free /root/perl/op.c​:480​:2

previously allocated by thread T0 here​:
  #0 0x4c0fa0 in calloc (/root/perl/perl+0x4c0fa0)
  #1 0x4dfa34 in S_new_slab /root/perl/op.c​:243​:30
  #2 0x4dfa34 in Perl_Slab_Alloc /root/perl/op.c​:343

SUMMARY​: AddressSanitizer​: heap-use-after-free /root/perl/doio.c​:1400
Perl_do_print
Shadow bytes around the buggy address​:
  0x0c3a7fffba20​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fffba30​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fffba40​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fffba50​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fffba60​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c3a7fffba70​: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fffba80​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fffba90​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fffbaa0​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fffbab0​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fffbac0​: 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
  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
==1757==ABORTING

When you minimize the orig55 testcase with afl-tmin, you get test55, which
triggers a heap-buffer-overflow in Perl_sv_setpvn (sv.c​:4899).

==10948==ERROR​: AddressSanitizer​: heap-buffer-overflow on address
0x60400000a4f8 at pc 0x0000004a9ff2 bp 0x7ffc3e2ad430 sp 0x7ffc3e2acbf0
READ of size 13 at 0x60400000a4f8 thread T0
  #0 0x4a9ff1 in __asan_memmove (/root/perl/perl+0x4a9ff1)
  #1 0x909695 in Perl_sv_setpvn /root/perl/sv.c​:4899​:5
  #2 0x951c07 in Perl_newSVpvn_flags /root/perl/sv.c​:9154​:5
  #3 0x66407b in Perl_yylex /root/perl/toke.c​:4899​:31
  #4 0x6ac9d5 in Perl_yyparse /root/perl/perly.c​:334​:19
  #5 0x59c4a1 in S_parse_body /root/perl/perl.c​:2372​:9
  #6 0x59283c in perl_parse /root/perl/perl.c​:1688​:2
  #7 0x4de835 in main /root/perl/perlmain.c​:121​:18
  #8 0x7f4f249eeb44 in __libc_start_main
/build/glibc-uPj9cH/glibc-2.19/csu/libc-start.c​:287
  #9 0x4de4cc in _start (/root/perl/perl+0x4de4cc)

0x60400000a4f8 is located 0 bytes to the right of 40-byte region
[0x60400000a4d0,0x60400000a4f8)
allocated by thread T0 here​:
  #0 0x4c113e in realloc (/root/perl/perl+0x4c113e)
  #1 0x7f62c6 in Perl_safesysrealloc /root/perl/util.c​:274​:18

SUMMARY​: AddressSanitizer​: heap-buffer-overflow ??​:0 __asan_memmove
Shadow bytes around the buggy address​:
  0x0c087fff9440​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9450​: fa fa fa fa fa fa fa fa fa fa fd fd fd fd fd fd
  0x0c087fff9460​: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fa
  0x0c087fff9470​: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 00
  0x0c087fff9480​: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 07 fa
=>0x0c087fff9490​: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00[fa]
  0x0c087fff94a0​: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 00
  0x0c087fff94b0​: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x0c087fff94c0​: fa fa 00 00 00 00 07 fa fa fa 00 00 00 00 00 01
  0x0c087fff94d0​: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 06 fa
  0x0c087fff94e0​: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 07 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
  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
==10948==ABORTING

In both cases, Perl 5.20.2 returns errors, does not crash.

@p5pRT
Copy link
Author

p5pRT commented Aug 19, 2016

From @geeknik

test55.gz

@p5pRT
Copy link
Author

p5pRT commented Aug 19, 2016

From @geeknik

orig55.gz

@p5pRT
Copy link
Author

p5pRT commented Aug 22, 2016

From @tonycoz

On Fri Aug 19 12​:21​:50 2016, brian.carpenter@​gmail.com wrote​:

The attached test case named orig55 triggers a heap-use-after-free
in Perl_do_print (doio.c​:1400). This was found with AFL, ASAN and
libdislocator.so affects v5.25.4 (v5.25.3-305-g8c6b0c7).

I don't think this is a security issue (but it's still a bug.)

Attached a simplified version of orig55.

I sort of suspect a relationship to #128996, since I don't expect
opslab_free() to be releasing the memory that S_no_op() is referencing
here.

tony@​mars​:.../perl/git$ hd -c 128997ab.pl
00000000 42 45 47 49 4e 20 7b 20 24 5e 48 20 3d 2d 68 65 |BEGIN { $^H =-he|
0000000 B E G I N { $ ^ H = - h e
00000010 78 20 22 32 31 31 30 74 22 7d 3b 0a 24 5e 48 20 |x "2110t"};.$^H |
0000010 x " 2 1 1 0 t " } ; \n $ ^ H
00000020 3d 2d 68 65 78 20 6a 6f 69 6e 20 22 30 22 5e 30 |=-hex join "0"^0|
0000020 = - h e x j o i n " 0 " ^ 0
00000030 24 5f 24 43 61 6d 65 6c 0a 20 20 22 78 22 25 62 |$_$Camel. "x"%b|
0000030 $ _ $ C a m e l \n " x " % b
00000040 22 ff 22 0a |".".|
0000040 " � " \n
0000044

Tony

@p5pRT
Copy link
Author

p5pRT commented Aug 22, 2016

From @tonycoz

128997ab.pl.gz

@p5pRT
Copy link
Author

p5pRT commented Aug 22, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Aug 22, 2016

From @tonycoz

On Fri Aug 19 12​:21​:50 2016, brian.carpenter@​gmail.com wrote​:

When you minimize the orig55 testcase with afl-tmin, you get test55, which
triggers a heap-buffer-overflow in Perl_sv_setpvn (sv.c​:4899).

I simplified this a little​:

tony@​mars​:.../perl/git$ hd -c 128997bb.pl
00000000 42 45 47 49 4e 7b 24 30 3d 22 22 3b 24 5e 48 3d |BEGIN{$0="";$^H=|
0000000 B E G I N { $ 0 = " " ; $ ^ H =
00000010 2d 68 65 78 22 31 22 7d 22 22 ff 0a |-hex"1"}""..|
0000010 - h e x " 1 " } " " � \n
000001c

And a little more​:

tony@​mars​:.../perl/git$ hd -c 128997bb.pl
00000000 42 45 47 49 4e 7b 24 30 3d 22 22 3b 24 5e 48 3d |BEGIN{$0="";$^H=|
0000000 B E G I N { $ 0 = " " ; $ ^ H =
00000010 2d 20 20 20 20 31 20 7d 22 22 ff 0a |- 1 }""..|
0000010 - 1 } " " � \n
000001c

Eliminating the whitespace​:

00000000 42 45 47 49 4e 7b 24 30 3d 22 22 3b 24 5e 48 3d |BEGIN{$0="";$^H=|
0000000 B E G I N { $ 0 = " " ; $ ^ H =
00000010 2d 31 7d 22 22 ff 0a |-1}""..|
0000010 - 1 } " " � \n
0000017

Changes the reported error to "unknown-crash"​:

==29597==ERROR​: AddressSanitizer​: unknown-crash on address 0x60300000e605 at pc 0x89c88d bp 0x7ffe88fa4dd0 sp 0x7ffe88fa4dc8
READ of size 13 at 0x60300000e605 thread T0
  #0 0x89c88c in Perl_sv_setpvn /home/tony/dev/perl/git/perl/sv.c​:4899
  #1 0x8e06ec in Perl_newSVpvn_flags /home/tony/dev/perl/git/perl/sv.c​:9154
  #2 0x56f9b6 in Perl_yylex /home/tony/dev/perl/git/perl/toke.c​:4899
  #3 0x5f3781 in Perl_yyparse /home/tony/dev/perl/git/perl/perly.c​:334
  #4 0x4be59a in S_parse_body /home/tony/dev/perl/git/perl/perl.c​:2373
  #5 0x4ba38d in perl_parse /home/tony/dev/perl/git/perl/perl.c​:1689
  #6 0x41fa33 in main /home/tony/dev/perl/git/perl/perlmain.c​:121
  #7 0x7fd0929b0b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
  #8 0x41f7c8 (/home/tony/dev/perl/git/perl/perl+0x41f7c8)

Tony

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2016

From @tonycoz

On Fri Aug 19 12​:21​:50 2016, brian.carpenter@​gmail.com wrote​:

The attached test case named orig55 triggers a heap-use-after-free
in Perl_do_print (doio.c​:1400). This was found with AFL, ASAN and
libdislocator.so affects v5.25.4 (v5.25.3-305-g8c6b0c7).

==1757==ERROR​: AddressSanitizer​: heap-use-after-free on address
0x61d00001d3a8 at pc 0x000000b23e59 bp 0x7ffc4fec9650 sp 0x7ffc4fec9648
READ of size 2 at 0x61d00001d3a8 thread T0
#0 0xb23e58 in Perl_do_print /root/perl/doio.c​:1400​:3
#1 0x7ff698 in Perl_write_to_stderr /root/perl/util.c​:1580​:2

This appears to be fixed by 4eadd82.

When you minimize the orig55 testcase with afl-tmin, you get test55, which
triggers a heap-buffer-overflow in Perl_sv_setpvn (sv.c​:4899).

==10948==ERROR​: AddressSanitizer​: heap-buffer-overflow on address
0x60400000a4f8 at pc 0x0000004a9ff2 bp 0x7ffc3e2ad430 sp 0x7ffc3e2acbf0
READ of size 13 at 0x60400000a4f8 thread T0
#0 0x4a9ff1 in __asan_memmove (/root/perl/perl+0x4a9ff1)
#1 0x909695 in Perl_sv_setpvn /root/perl/sv.c​:4899​:5
#2 0x951c07 in Perl_newSVpvn_flags /root/perl/sv.c​:9154​:5
#3 0x66407b in Perl_yylex /root/perl/toke.c​:4899​:31
#4 0x6ac9d5 in Perl_yyparse /root/perl/perly.c​:334​:19
#5 0x59c4a1 in S_parse_body /root/perl/perl.c​:2372​:9
#6 0x59283c in perl_parse /root/perl/perl.c​:1688​:2
#7 0x4de835 in main /root/perl/perlmain.c​:121​:18
#8 0x7f4f249eeb44 in __libc_start_main

But not this.

Since this isn't a security issue I've moved it to the public queue.

Tony

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2016

From @tonycoz

On Mon Oct 17 17​:04​:40 2016, tonyc wrote​:

When you minimize the orig55 testcase with afl-tmin, you get test55, which
triggers a heap-buffer-overflow in Perl_sv_setpvn (sv.c​:4899).

==10948==ERROR​: AddressSanitizer​: heap-buffer-overflow on address
0x60400000a4f8 at pc 0x0000004a9ff2 bp 0x7ffc3e2ad430 sp 0x7ffc3e2acbf0
READ of size 13 at 0x60400000a4f8 thread T0
#0 0x4a9ff1 in __asan_memmove (/root/perl/perl+0x4a9ff1)
#1 0x909695 in Perl_sv_setpvn /root/perl/sv.c​:4899​:5
#2 0x951c07 in Perl_newSVpvn_flags /root/perl/sv.c​:9154​:5
#3 0x66407b in Perl_yylex /root/perl/toke.c​:4899​:31
#4 0x6ac9d5 in Perl_yyparse /root/perl/perly.c​:334​:19
#5 0x59c4a1 in S_parse_body /root/perl/perl.c​:2372​:9
#6 0x59283c in perl_parse /root/perl/perl.c​:1688​:2
#7 0x4de835 in main /root/perl/perlmain.c​:121​:18
#8 0x7f4f249eeb44 in __libc_start_main

But not this.

Should be fixed by the attached.

Tony

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2016

From @tonycoz

0001-perl-128997-avoid-reading-beyond-the-end-of-the-line.patch
From dbabdaa2a253dd057e8df334c336b9dc18bd0d28 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 18 Oct 2016 15:46:48 +1100
Subject: (perl #128997) avoid reading beyond the end of the line buffer

when there's a short UTF-8 character at the end.
---
 t/op/lex.t |  8 +++++++-
 toke.c     | 17 ++++++++++++-----
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/t/op/lex.t b/t/op/lex.t
index db0cf3a..f3cb510 100644
--- a/t/op/lex.t
+++ b/t/op/lex.t
@@ -7,7 +7,7 @@ use warnings;
 
 BEGIN { chdir 't' if -d 't'; require './test.pl'; }
 
-plan(tests => 32);
+plan(tests => 33);
 
 {
     no warnings 'deprecated';
@@ -255,3 +255,9 @@ fresh_perl_is(
     {},
     '[perl #128996] - use of PL_op after op is freed'
 );
+fresh_perl_like(
+    qq(BEGIN{\$0="";\$^H=-hex join""=>1}""\xFF),
+    qr/Malformed UTF-8 character: \\xff \(too short; got 1 byte, need 13\) at - line 1\./,
+    {},
+    '[perl #128997] - buffer read overflow'
+);
diff --git a/toke.c b/toke.c
index d44d36a..041996f 100644
--- a/toke.c
+++ b/toke.c
@@ -4896,11 +4896,18 @@ Perl_yylex(pTHX)
 	}
     {
         SV *dsv = newSVpvs_flags("", SVs_TEMP);
-        const char *c = UTF ? sv_uni_display(dsv, newSVpvn_flags(s,
-                                                    UTF8SKIP(s),
-                                                    SVs_TEMP | SVf_UTF8),
-                                            10, UNI_DISPLAY_ISPRINT)
-                            : Perl_form(aTHX_ "\\x%02X", (unsigned char)*s);
+        const char *c;
+        if (UTF) {
+            STRLEN skiplen = UTF8SKIP(s);
+            STRLEN stravail = PL_bufend - s;
+            c = sv_uni_display(dsv, newSVpvn_flags(s,
+                                                   skiplen > stravail ? stravail : skiplen,
+                                                   SVs_TEMP | SVf_UTF8),
+                               10, UNI_DISPLAY_ISPRINT);
+        }
+        else {
+            c = Perl_form(aTHX_ "\\x%02X", (unsigned char)*s);
+        }
         len = UTF ? Perl_utf8_length(aTHX_ (U8 *) PL_linestart, (U8 *) s) : (STRLEN) (s - PL_linestart);
         if (len > UNRECOGNIZED_PRECEDE_COUNT) {
             d = UTF ? (char *) utf8_hop((U8 *) s, -UNRECOGNIZED_PRECEDE_COUNT) : s - UNRECOGNIZED_PRECEDE_COUNT;
-- 
2.1.4

@p5pRT
Copy link
Author

p5pRT commented Oct 31, 2016

From @tonycoz

On Mon Oct 17 21​:47​:48 2016, tonyc wrote​:

On Mon Oct 17 17​:04​:40 2016, tonyc wrote​:

When you minimize the orig55 testcase with afl-tmin, you get
test55, which
triggers a heap-buffer-overflow in Perl_sv_setpvn (sv.c​:4899).

==10948==ERROR​: AddressSanitizer​: heap-buffer-overflow on address
0x60400000a4f8 at pc 0x0000004a9ff2 bp 0x7ffc3e2ad430 sp
0x7ffc3e2acbf0
READ of size 13 at 0x60400000a4f8 thread T0
#0 0x4a9ff1 in __asan_memmove (/root/perl/perl+0x4a9ff1)
#1 0x909695 in Perl_sv_setpvn /root/perl/sv.c​:4899​:5
#2 0x951c07 in Perl_newSVpvn_flags /root/perl/sv.c​:9154​:5
#3 0x66407b in Perl_yylex /root/perl/toke.c​:4899​:31
#4 0x6ac9d5 in Perl_yyparse /root/perl/perly.c​:334​:19
#5 0x59c4a1 in S_parse_body /root/perl/perl.c​:2372​:9
#6 0x59283c in perl_parse /root/perl/perl.c​:1688​:2
#7 0x4de835 in main /root/perl/perlmain.c​:121​:18
#8 0x7f4f249eeb44 in __libc_start_main

But not this.

Should be fixed by the attached.

Applied as 856bb39.

Since both issues are fixed, closing this ticket.

Tony

@p5pRT
Copy link
Author

p5pRT commented Oct 31, 2016

@tonycoz - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

From @khwilliamson

Thank you for filing this report. You have helped make Perl better.

With the release today of Perl 5.26.0, this and 210 other issues have been
resolved.

Perl 5.26.0 may be downloaded via​:
https://metacpan.org/release/XSAWYERX/perl-5.26.0

If you find that the problem persists, feel free to reopen this ticket.

@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

@khwilliamson - Status changed from 'pending release' to 'resolved'

@p5pRT p5pRT closed this as completed May 30, 2017
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