Created attachment 346729 [details] Test case that triggers the buffer overflow Description of problem: Compress::Raw::Zlib versions before 2.017 contain a buffer overflow in inflate(). A badly formed zlib-stream can trigger this buffer overflow and cause the perl process at least to hang or to crash. There is an e-mail virus in circulation that contains a zip file that causes such a memory corruption when being uncompressed using perl-applications that depend on Compress::Raw::Zlib. (E.g. spamassassin and amavisd-new.) (See http://thread.gmane.org/gmane.mail.virus.amavis.user/33635.) Version-Release number of selected component (if applicable): perl-5.10.0-68.fc10.i386 for Fedora 10 perl-5.8.8-18.el5_3.1 for RHEL5 How reproducible: Use the attached tarball that contains a testcase. Steps to Reproduce: 1. tar -xzvf compress-raw-zlib-buffer-overflow.tar.gz 2. cd compress-raw-zlib-buffer-overflow 3. valgrind perl compress-raw-zlib.pl Actual results: [...] inflating... ==6322== Invalid write of size 1 ==6322== at 0x46DB113: XS_Compress__Raw__Zlib__inflateStream_inflate (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Compress/Raw/Zlib/Zlib.so) ==6322== by 0x3E256F8: Perl_pp_entersub (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x3DE6F02: Perl_runops_debug (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x3E1FA88: perl_run (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x8048A2D: main (in /usr/bin/perl) ==6322== Address 0x423f554 is 0 bytes after a block of size 32,780 alloc'd ==6322== at 0x4006AEE: malloc (vg_replace_malloc.c:207) ==6322== by 0x3DF1EC2: Perl_safesysmalloc (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x3E5187F: Perl_sv_grow (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x46DAF83: XS_Compress__Raw__Zlib__inflateStream_inflate (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Compress/Raw/Zlib/Zlib.so) ==6322== by 0x3E256F8: Perl_pp_entersub (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x3DE6F02: Perl_runops_debug (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x3E1FA88: perl_run (in /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so) ==6322== by 0x8048A2D: main (in /usr/bin/perl) done: status: stream end [...] Expected results: No valgrind error. Additional info: Note that this bug also applies to F9 and RHEL5. The following changes between 2.015 and 2.017 fix the problem. Note the "+ 1" on buffer allocation... --- Compress-Raw-Zlib-2.015/Zlib.xs 2008-09-02 23:02:41.000000000 +0200 +++ Compress-Raw-Zlib-2.017/Zlib.xs 2009-03-26 10:40:57.000000000 +0100 @@ -1306,23 +1310,39 @@ if((s->flags & FLAG_APPEND) != FLAG_APPEND) { SvCUR_set(output, 0); } + + /* Assume no output buffer - the code below will update if there is any available */ + s->stream.avail_out = 0; + + if (SvLEN(output)) { prefix_length = cur_length = SvCUR(output) ; - s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; - increment = SvLEN(output) - cur_length - 1; - s->stream.avail_out = increment; - } - else { - s->stream.avail_out = 0; + + if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc) + { + Sv_Grow(output, bufinc + cur_length + 1) ; + } + + /* Only setup the stream output pointers if there is spare + capacity in the outout SV + */ + if (SvLEN(output) > cur_length + 1) + { + s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; + increment = SvLEN(output) - cur_length - 1; + s->stream.avail_out = increment; + } } + + s->bytesInflated = 0; RETVAL = Z_OK; while (RETVAL == Z_OK) { - if (s->stream.avail_out == 0 ) { + if (s->stream.avail_out == 0) { /* out of space in the output buffer so make it bigger */ - Sv_Grow(output, SvLEN(output) + bufinc) ; + Sv_Grow(output, SvLEN(output) + bufinc +1) ; cur_length += increment ; s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; increment = bufinc ;
Thank you for your investigation. In Fedora will be updated version of Compress::Raw::Zlib.
I suppose you have perl-Compress-Raw-Zlib from different source than RHEL or EPEL. I see it in EPEL-4 as a package and then as a part of perl-5.10 in Fedora.
OK, sorry, the package on my RHEL5 box is from rpmfusion. So RHEL5 doesn't seem to provide perl-Compress-Raw-Zlib at all...
Updates will be done for F-10, F-11 and rawhide perl. For the EPEL will be updated EPEL-4 and 5 for package perl-Compress-Raw-Zlib.
Even though there seem to be a directory in CVS for the package in EPEL-4, it does not seem to be included in either EPEL-4 or EPEL-5 on download FTPs. Module seems to be part of perl SRPM as of F-9.
Package Change Request ====================== Package Name: perl-Compress-Raw-Zlib New Branches: EL-5 Owners: kasal mmaslano Please branch from devel -D 2008-02-25 . (Or from F-8 branch if that's easier.)
Just a sanity self-check - this should only be an issue when inflated output size is exactly the same size as the output buffer (initial size is -Bufsize or 4096 by default, doubles in size on each buffer grow). This problem exists because Compress::Raw::Zlib's inflate NUL-terminates the output buffer (*SvEND(output) = '\0';), even it may not have enough space. So this should be heap off-by-one, unless I'm missing something. Do I have it right?
This corresponds to my interpretation of the source code. Archive::Zip which is used by amavisd-new uses a default ChunkSize of 32768. That's why it hangs when processing the zip file contained in my test-case.
Ok, thanks for confirmation. Leo, this bug will be made public sooner or later. Can we keep your test cases public, or would you prefer if we restrict access to your attachment? Can we share tests with other vendors? Thanks!
Opening bug to add it to bodhi update requests. Attachment marked as private for now. Test case can be re-created by deflating input of Bufsize and re-inflating it again.
I don't mind if you make the attachment available to the public. (I couldn't figure out how to do it myself... :-))
Thanks, done.
cvs done.
Updates: https://admin.fedoraproject.org/updates/perl-5.10.0-69.fc9 https://admin.fedoraproject.org/updates/perl-5.10.0-69.fc10 https://admin.fedoraproject.org/updates/perl-5.10.0-69.fc11
perl-Compress-Raw-Zlib-2.020-1 has been built for EPEL 4 and EPEL 5.
perl-5.10.0-69.fc11 has been pushed to the Fedora 11 stable repository. If problems still persist, please make note of it in this bug report.
perl-5.10.0-73.fc10 has been submitted as an update for Fedora 10. http://admin.fedoraproject.org/updates/perl-5.10.0-73.fc10
perl-5.10.0-73.fc9 has been submitted as an update for Fedora 9. http://admin.fedoraproject.org/updates/perl-5.10.0-73.fc9
perl-5.10.0-73.fc11 has been submitted as an update for Fedora 11. http://admin.fedoraproject.org/updates/perl-5.10.0-73.fc11
perl-5.10.0-73.fc10 has been pushed to the Fedora 10 stable repository. If problems still persist, please make note of it in this bug report.