Skip Menu |
Report information
Id: 119961
Status: open
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: kentfredric [at] gmail.com
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: low
Type: unknown
Perl Version: (no value)
Fixed In: (no value)



Subject: PerlIO::via modules exhibit buffer leakage when READ doesn't touch $buffer
Date: Tue, 24 Sep 2013 03:53:42 +1200
To: perlbug [...] perl.org
From: Kent Fredric <kentfredric [...] gmail.com>
Download (untitled) / with headers
text/plain 4.1k
This is a bug report for perl from kentfredric@gmail.com,
generated with the help of perlbug 1.39 running under perl 5.19.3.


-----------------------------------------------------------------
[Please describe your issue here]

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.


[Please do not change anything below this line]
-----------------------------------------------------------------
---
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

RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 188b
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.
Download (untitled) / with headers
text/plain 159b
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:
Download via_io_stack.pl
text/x-perl 320b
#!/usr/bin/env perl use strict; use warnings; use utf8; { package PerlIO::via::Bug; sub PUSHED { return bless {}, $_[0]; } sub READ { return 1024; } } open my $fh, '<:raw:via(Bug)', '/dev/null' or die "Cannot open, $! $?"; my $stash = {}; read $fh, ( my $buf ), 1; print $buf;
Download stackdump
application/octet-stream 5.2k

Message body not shown because it is not plain text.

RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.2k
On Mon Sep 23 08:54:16 2013, kentfredric@gmail.com wrote: Show quoted text
> 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


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org