[mp2] Segfault on using $r->content_type()

[mp2] Segfault on using $r->content_type()

am 26.06.2008 21:49:11 von Stephen Howard

1. Problem Description:

I have an intermittent segfault with one particular ResponseHandler.
The segfault, when it occurs, is triggered by calling $r->content_type
in a lightly modified CGI::Simple (I made changes to it as it wasn't
playing well with mod_perl2). What might be going awry? The relevant
changes to CGI::Simple are in the header sub:

for ( @other ) {

# Don't use \s because of perl bug 21951
next
unless my ( $header, $value ) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
$header =~ s/^(\w)(.*)/\u$1\L$2/;
$_ = [ $header, $self->unescapeHTML($value) ];
}
$type ||= 'text/html' unless defined $type;
$type .= "; charset=$charset"
if $type
and $type =~ m!^text/!
and $type !~ /\bcharset\b/;
my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0';
push @header, $protocol . ' ' . ( $status || '200 OK' ) if $nph;
push @header, ["Server", server_software() ] if $nph;
push @header, ["Status", $status ] if $status;
push @header, ["Window-Target", $target ] if $target;

if ( $p3p ) {
$p3p = join ' ', @$p3p if ref( $p3p ) eq 'ARRAY';
push( @header, ["P3P", qq(policyref="/w3c/p3p.xml", CP="$p3p")] );
}

# push all the cookies -- there may be several
if ( $cookie ) {
my @cookie = ref $cookie eq 'ARRAY' ? @{$cookie} : $cookie;
for my $cookie ( @cookie ) {
my $cs =
ref $cookie eq 'CGI::Simple::Cookie'
? $cookie->as_string
: $cookie;
push @header, ["Set-Cookie", $cs] if $cs;
}
}

# if the user indicates an expiration time, then we need both an Expires
# and a Date header (so that the browser is using OUR clock)
$expires = 'now'
if $self->no_cache; # encourage no caching via expires now
push @header, ["Expires", CGI::Simple::Util::expires( $expires,
'http' ) ]
if $expires;
push @header, ["Date", CGI::Simple::Util::expires( 0, 'http' ) ]
if defined $expires || $cookie || $nph;
push @header, ["Pragma", "no-cache"] if $self->cache or $self->no_cache;
push @header, ["Content-Disposition", "attachment;
filename=\"$attachment\"" ]
if $attachment;
push @header, @other;
push @header, ["Content-Type", $type] if $type;

if ( $self->{'.mod_perl'} and not $nph ) {
my $r = $self->_mod_perl_request();
$r->content_type( $type ) if $type; <----------- segfault here
-----------
$r->status($status) if $status;
$r->err_headers_out->add( @$_ ) foreach @header;
return '';
}
my $CRLF = $self->crlf;
my $header = join $CRLF, map { join ': ', @$_ } @header;
$header .= $CRLF . $CRLF; # add the statutory two CRLFs
return $header;

2. Used Components and their Configuration:

*** mod_perl version 2.000004

*** using /tmp/mod_perl-2.0.4/lib/Apache2/BuildConfig.pm

*** Makefile.PL options:
MP_APR_LIB => aprext
MP_APXS => /usr/sbin/apxs
MP_COMPAT_1X => 1
MP_GENERATE_XS => 1
MP_LIBNAME => mod_perl
MP_USE_DSO => 1


*** /usr/sbin/httpd -V
Server version: Apache/2.0.52
Server built: Aug 2 2006 05:21:10
Server's Module Magic Number: 20020903:9
Architecture: 32-bit
Server compiled with....
-D APACHE_MPM_DIR="server/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D HTTPD_ROOT="/etc/httpd"
-D SUEXEC_BIN="/usr/sbin/suexec"
-D DEFAULT_PIDLOG="logs/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_LOCKFILE="logs/accept.lock"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"
*** /usr/bin/ldd /usr/sbin/httpd
libpcre.so.0 => /lib/libpcre.so.0 (0x00c7b000)
libpcreposix.so.0 => /usr/lib/libpcreposix.so.0 (0x009f1000)
libaprutil-0.so.0 => /usr/lib/libaprutil-0.so.0 (0x00dba000)
libldap-2.2.so.7 => /usr/lib/libldap-2.2.so.7 (0x00aa7000)
liblber-2.2.so.7 => /usr/lib/liblber-2.2.so.7 (0x00a82000)
libdb-4.2.so => /lib/tls/i686/libdb-4.2.so (0x003ca000)
libexpat.so.0 => /usr/lib/libexpat.so.0 (0x00357000)
libapr-0.so.0 => /usr/lib/libapr-0.so.0 (0x00111000)
librt.so.1 => /lib/tls/librt.so.1 (0x00133000)
libm.so.6 => /lib/tls/libm.so.6 (0x004f7000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x0096f000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x00cec000)
libdl.so.2 => /lib/libdl.so.2 (0x0074a000)
libc.so.6 => /lib/tls/libc.so.6 (0x00217000)
libresolv.so.2 => /lib/libresolv.so.2 (0x00d53000)
libsasl2.so.2 => /usr/lib/libsasl2.so.2 (0x00147000)
libssl.so.4 => /lib/libssl.so.4 (0x00bdf000)
libcrypto.so.4 => /lib/libcrypto.so.4 (0x0051a000)
/lib/ld-linux.so.2 (0x00dd9000)
libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x0015b000)
libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x0016f000)
libcom_err.so.2 => /lib/libcom_err.so.2 (0x001d4000)
libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x001d7000)
libz.so.1 => /usr/lib/libz.so.1 (0x00f4b000)


*** (apr|apu)-config linking info

-laprutil-0 -lldap -llber -ldb-4.2 -lexpat
-lapr-0 -lrt -lm -lcrypt -lpthread -ldl



*** /usr/bin/perl -V
Summary of my perl5 (revision 5 version 8 subversion 5) configuration:
Platform:
osname=linux, osvers=2.6.9-22.18.bz155725.elsmp,
archname=i386-linux-thread-multi
uname='linux hs20-bc1-4.build.redhat.com 2.6.9-22.18.bz155725.elsmp
#1 smp thu nov 17 15:34:08 est 2005 i686 i686 i386 gnulinux '
config_args='-des -Doptimize=-O2 -g -pipe -m32 -march=i386
-mtune=pentium4 -Dversion=5.8.5 -Dmyhostname=localhost
-Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc.
-Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux
-Dvendorprefix=/usr -Dsiteprefix=/usr -Duseshrplib -Dusethreads
-Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db
-Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio
-Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less
-isr -Dinc_version_list=5.8.4 5.8.3 5.8.2 5.8.1 5.8.0'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING
-fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
optimize='-O2 -g -pipe -m32 -march=i386 -mtune=pentium4',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING
-fno-strict-aliasing -pipe -I/usr/local/include -I/usr/include/gdbm'
ccversion='', gccversion='3.4.6 20060404 (Red Hat 3.4.6-2)',
gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='gcc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
libc=/lib/libc-2.3.4.so, so=so, useshrplib=true, libperl=libperl.so
gnulibc_version='2.3.4'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E
-Wl,-rpath,/usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE '
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'


Characteristics of this binary (from libperl):
Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS
USE_LARGE_FILES PERL_IMPLICIT_CONTEXT
Built under linux
Compiled at Jul 24 2006 18:28:10
%ENV:
PERL_LWP_USE_HTTP_10="1"
@INC:
/usr/lib/perl5/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/5.8.5
/usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.4/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.2/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.5
/usr/lib/perl5/site_perl/5.8.4
/usr/lib/perl5/site_perl/5.8.3
/usr/lib/perl5/site_perl/5.8.2
/usr/lib/perl5/site_perl/5.8.1
/usr/lib/perl5/site_perl/5.8.0
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.4/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.2/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.1/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.5
/usr/lib/perl5/vendor_perl/5.8.4
/usr/lib/perl5/vendor_perl/5.8.3
/usr/lib/perl5/vendor_perl/5.8.2
/usr/lib/perl5/vendor_perl/5.8.1
/usr/lib/perl5/vendor_perl/5.8.0
/usr/lib/perl5/vendor_perl
.

*** Packages of interest status:

Apache2 : -
Apache2::Request : -
CGI : 3.29
ExtUtils::MakeMaker: 6.17
LWP : 5.79, 5.805
mod_perl : 1.9916
mod_perl2 : 2.000004


3. This is the core dump trace: (if you get a core dump):

#0 0x00db86e8 in apr_palloc () from /usr/lib/libapr-0.so.0
#1 0x00da66bd in apr_pmemdup () from /usr/lib/libapr-0.so.0
#2 0x00577fb9 in XS_Apache2__RequestRec_content_type
(my_perl=0x8776388, cv=0x89fd810) at
/root/.cpan/build/mod_perl-2.0.4/xs/Apache2/RequestRec/Apach e2__RequestRec.h:27
#3 0x01074a22 in Perl_pp_entersub () from
/usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so
#4 0x01057edd in Perl_runops_debug () from
/usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so
#5 0x01002b26 in Perl_get_cv () from
/usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so
#6 0x01008ef1 in Perl_call_sv () from
/usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE/libperl.so
#7 0x004756a5 in modperl_callback (my_perl=0x8776388,
handler=0x87b7770, p=0x89ef260, r=0x89ef298, s=0x87b4830,
args=0x945b51c) at modperl_callback.c:101
#8 0x00475f1d in modperl_callback_run_handlers (idx=6, type=4,
r=0x89ef298, c=0x0, s=0x87b4830, pconf=0x0, plog=0x0, ptemp=0x0,
run_mode=MP_HOOK_RUN_FIRST)
at modperl_callback.c:262
#9 0x0047656d in modperl_callback_per_dir (idx=0, r=0x18,
run_mode=MP_HOOK_RUN_ALL) at modperl_callback.c:369
#10 0x0046f3b1 in modperl_response_handler_run (r=0x89ef298, finish=0)
at mod_perl.c:1000
#11 0x0046f699 in modperl_response_handler_cgi (r=0x89ef298) at
mod_perl.c:1100
#12 0x008289d7 in ap_run_handler () from /usr/sbin/httpd
#13 0x00828e43 in ap_invoke_handler () from /usr/sbin/httpd
#14 0x008258c5 in ap_process_request () from /usr/sbin/httpd
#15 0x0082063f in _start () from /usr/sbin/httpd
#16 0x089ef298 in ?? ()
#17 0x00000004 in ?? ()
#18 0x089ef298 in ?? ()
#19 0x0048ccf5 in modperl_process_connection_handler (c=0x0) at
modperl_hooks.c:17
#20 0x00833369 in ap_run_process_connection () from /usr/sbin/httpd
#21 0x008336d4 in ap_process_connection () from /usr/sbin/httpd
#22 0x00826919 in ap_graceful_stop_signalled () from /usr/sbin/httpd
#23 0x00826b5c in ap_graceful_stop_signalled () from /usr/sbin/httpd
#24 0x00827313 in ap_mpm_run () from /usr/sbin/httpd
#25 0x0082e36a in main () from /usr/sbin/httpd

This report was generated by /usr/bin/mp2bug on Thu Jun 26 18:45:21 2008
GMT.

Re: [mp2] Segfault on using $r->content_type()

am 01.07.2008 03:33:03 von gozer

This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enig8A55D52B7AF300B082BFD10A
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable



Stephen Howard wrote:
> 1. Problem Description:
>=20
> I have an intermittent segfault with one particular ResponseHandler. =20
> The segfault, when it occurs, is triggered by calling $r->content_type =

> in a lightly modified CGI::Simple (I made changes to it as it wasn't=20
> playing well with mod_perl2). What might be going awry? The relevant=20
> changes to CGI::Simple are in the header sub:
>=20
> for ( @other ) {
>=20
> # Don't use \s because of perl bug 21951
> next
> unless my ( $header, $value ) =3D /([^ \r\n\t=3D]+)=3D\"?(.+?=
)\"?$/;
> $header =3D~ s/^(\w)(.*)/\u$1\L$2/;
> $_ =3D [ $header, $self->unescapeHTML($value) ];
> }
> $type ||=3D 'text/html' unless defined $type;
> $type .=3D "; charset=3D$charset"
> if $type
> and $type =3D~ m!^text/!
> and $type !~ /\bcharset\b/;
> my $protocol =3D $ENV{SERVER_PROTOCOL} || 'HTTP/1.0';
> push @header, $protocol . ' ' . ( $status || '200 OK' ) if $nph;
> push @header, ["Server", server_software() ] if $nph;
> push @header, ["Status", $status ] if $status;
> push @header, ["Window-Target", $target ] if $target;
>=20
> if ( $p3p ) {
> $p3p =3D join ' ', @$p3p if ref( $p3p ) eq 'ARRAY';
> push( @header, ["P3P", qq(policyref=3D"/w3c/p3p.xml", CP=3D"$p3=
p")] );
> }
>=20
> # push all the cookies -- there may be several
> if ( $cookie ) {
> my @cookie =3D ref $cookie eq 'ARRAY' ? @{$cookie} : $cookie;
> for my $cookie ( @cookie ) {
> my $cs =3D
> ref $cookie eq 'CGI::Simple::Cookie'
> ? $cookie->as_string
> : $cookie;
> push @header, ["Set-Cookie", $cs] if $cs;
> }
> }
>=20
> # if the user indicates an expiration time, then we need both an Ex=
pires
> # and a Date header (so that the browser is using OUR clock)
> $expires =3D 'now'
> if $self->no_cache; # encourage no caching via expires now
> push @header, ["Expires", CGI::Simple::Util::expires( $expires,=20
> 'http' ) ]
> if $expires;
> push @header, ["Date", CGI::Simple::Util::expires( 0, 'http' ) ]
> if defined $expires || $cookie || $nph;
> push @header, ["Pragma", "no-cache"] if $self->cache or $self->no_c=
ache;
> push @header, ["Content-Disposition", "attachment;=20
> filename=3D\"$attachment\"" ]
> if $attachment;
> push @header, @other;
> push @header, ["Content-Type", $type] if $type;
>=20
> if ( $self->{'.mod_perl'} and not $nph ) {
> my $r =3D $self->_mod_perl_request();
> $r->content_type( $type ) if $type; <----------- segfault here =

> -----------

Any change of dumping out what was in $type at that point, just before it=
segfaults?

Data::Dumper + Devel::Peek::Dump() would be usefull.

> $r->status($status) if $status;
> $r->err_headers_out->add( @$_ ) foreach @header;
> return '';
> }
> my $CRLF =3D $self->crlf;
> my $header =3D join $CRLF, map { join ': ', @$_ } @header;
> $header .=3D $CRLF . $CRLF; # add the statutory two CRLFs
> return $header;
>=20
> [...]
> 3. This is the core dump trace: (if you get a core dump):

Thanks for the yummy backtrace !

> #0 0x00db86e8 in apr_palloc () from /usr/lib/libapr-0.so.0
> #1 0x00da66bd in apr_pmemdup () from /usr/lib/libapr-0.so.0
> #2 0x00577fb9 in XS_Apache2__RequestRec_content_type=20
> (my_perl=3D0x8776388, cv=3D0x89fd810) at=20
> /root/.cpan/build/mod_perl-2.0.4/xs/Apache2/RequestRec/Apach e2__Request=
Rec.h:27

const char *val =3D SvPV(type, len);
ap_set_content_type(r, apr_pmemdup(r->pool, val, len+1));

The only way I could see this trace hapenning is if:
val !=3D NULL, so it's something
len is VERY large.

So my guess is that SV *type might be somewhat corrupt and causing
APR to just try and allocate way too much memory (or too litle, -123)

Any chance you could build a debugging mod_perl-2 and catch this in
gdb ?

If so, it's just a matter of

gdb> display locals

in frame #2

to figure out what the value of val and len is.

--=20
Philippe M. Chiasson GPG: F9BFE0C2480E7680 1AE53631CB32A107 88C3A5A5
http://gozer.ectoplasm.org/ m/gozer\@(apache|cpan|ectoplasm)\.org/


--------------enig8A55D52B7AF300B082BFD10A
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFIaYlVyzKhB4jDpaURAvyxAJ0Yfdo38fI6fZvf3ChwT/M96kiXvQCe OpJn
KAvbaf75jfhqPVoPfcvyBzU=
=skNw
-----END PGP SIGNATURE-----

--------------enig8A55D52B7AF300B082BFD10A--