Perl / perl5

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

PerlIO::via modules exhibit buffer leakage when READ doesn't touch $buffer #13304

Open p5pRT opened 11 years ago

p5pRT commented 11 years ago

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

Searchable as RT119961$

p5pRT commented 11 years ago

From @kentfredric

Created by @kentfredric

I discovered accidentally\, that if you're writing a PerlIO layer with PerlIO​::via\, that you can accidentally leak the contents of the previously loaded file to calling code.

In the given example on my machine\, the contents of XSLoader.pm are spewed to my terminal with arbitrary binary data around it\, suggesting to me some kind of memory leakage/buffer overflow.

---- use strict; use warnings; use utf8;

{   package PerlIO​::via​::Bug;

  sub PUSHED {   return bless {}\, $_[0];   }   sub READ {   return $_[2];   } }

open my $fh\, '\<​:raw​:via(Bug)'\, '/dev/null' or die "Cannot open\, $! $?";

read $fh\, ( my $buf )\, 1024;

print $buf;

---

The failure still occurs without any of the aforementioned "use" statements\,   just 'use utf8' is convenient for me\, because it somehow causes the contents of "XSLoader.pm"   to be dumped\, which is a clear indication of error.

different values of "use" will result in different output.

Perl Info ``` Flags: category=core severity=medium Site configuration information for perl 5.19.3: Configured by kent at Thu Sep 5 10:45:54 NZST 2013. Summary of my perl5 (revision 5 version 19 subversion 3) configuration: Platform: osname=linux, osvers=3.10.9-gentoo, archname=x86_64-linux uname='linux katipo2 3.10.9-gentoo #40 smp tue aug 27 01:15:13 nzst 2013 x86_64 intel(r) core(tm) i5-2410m cpu @ 2.30ghz genuineintel gnulinux ' config_args='-de -Dprefix=/home/kent/perl5/perlbrew/perls/perl-5.19.3 -Dusedevel -Aeval:scriptdir=/home/kent/perl5/perlbrew/perls/perl-5.19.3/bin' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-fno-strict-aliasing -pipe -fstack-protector' ccversion='', gccversion='4.7.2', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -fstack-protector' libpth=/lib/../lib64 /usr/lib/../lib64 /lib /usr/lib /lib64 /usr/lib64 libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc libc=/lib/libc-2.15.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.15' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -fstack-protector' @INC for perl 5.19.3: /home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl/5.19.3/x86_64-linux /home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl/5.19.3 /home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/5.19.3/x86_64-linux /home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/5.19.3 . Environment for perl 5.19.3: HOME=/home/kent LANG (unset) LANGUAGE (unset) LC_CTYPE=en_NZ.UTF8 LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/kent/perl5/perlbrew/bin:/home/kent/perl5/perlbrew/perls/perl-5.19.3/bin:/home/kent/.perl6/2013.04/bin:/home/kent/.gem/ruby/1.8/bin/:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.7.2:/usr/games/bin PERLBREW_BASHRC_VERSION=0.61 PERLBREW_HOME=/home/kent/.perlbrew PERLBREW_MANPATH=/home/kent/perl5/perlbrew/perls/perl-5.19.3/man PERLBREW_PATH=/home/kent/perl5/perlbrew/bin:/home/kent/perl5/perlbrew/perls/perl-5.19.3/bin PERLBREW_PERL=perl-5.19.3 PERLBREW_ROOT=/home/kent/perl5/perlbrew PERLBREW_VERSION=0.61 PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 11 years ago

From @kentfredric

I should also note\, even assigning to $buffer doesn't help you.

It just assumes you're not lying when you return $length

So as long as $length > length($buffer)\, corruption will be seen.

p5pRT commented 11 years ago

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

p5pRT commented 11 years ago

From @kentfredric

More\, if you change the return to a fixed number such as 1024\, and then invoke the read as simply 'read $fh\, ( my $buf )\, 1'\, it invokes a GLIBC corruption​:

p5pRT commented 11 years ago

From @kentfredric

via_io_stack.pl

p5pRT commented 11 years ago

From @kentfredric

stackdump

p5pRT commented 11 years ago

From @Leont

On Mon Sep 23 08​:54​:16 2013\, kentfredric@​gmail.com wrote​:

I discovered accidentally\, that if you're writing a PerlIO layer with PerlIO​::via\, that you can accidentally leak the contents of the previously loaded file to calling code.

In the given example on my machine\, the contents of XSLoader.pm are spewed to my terminal with arbitrary binary data around it\, suggesting to me some kind of memory leakage/buffer overflow.

---- use strict; use warnings; use utf8;

{ package PerlIO​::via​::Bug;

sub PUSHED { return bless {}\, $_[0]; } sub READ { return $_[2]; } }

open my $fh\, '\<​:raw​:via(Bug)'\, '/dev/null' or die "Cannot open\, $! $?";

read $fh\, ( my $buf )\, 1024;

print $buf;

---

The failure still occurs without any of the aforementioned "use" statements\, just 'use utf8' is convenient for me\, because it somehow causes the contents of "XSLoader.pm" to be dumped\, which is a clear indication of error.

different values of "use" will result in different output.

The bug is in PerlIOVia_read. It's doing a two things wrong​: 1) It does not ensure the buffer is in fact a string before using SvPVX. 2) It does not check if the length is in any way sane.

Leon