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

segfault in PerlIOBuf_fill when filehandle is closed in a signal handler #10422

Closed
p5pRT opened this issue Jun 3, 2010 · 6 comments
Closed

segfault in PerlIOBuf_fill when filehandle is closed in a signal handler #10422

p5pRT opened this issue Jun 3, 2010 · 6 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Jun 3, 2010

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

Searchable as RT75556$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Jun 3, 2010

From chrisb@debian.org

This is a bug report for perl from chrisb@​debian.org,
generated with the help of perlbug 1.39 running under perl 5.10.1.


This bug was originally filed in the Debian Bug Tracking System​:
http​://bugs.debian.org/cgi-bin/bugreport.cgi?bug=275357

If a blocking read operation is interrupted by a signal, and the signal
handler then closes the filehandle, perl will segfault when it returns from
the signal.

== bug.pl ==
#!/usr/bin/perl

$SIG{ALRM} = sub { close(FIFO) };
open (FIFO, "< fifo");
alarm(1);
$_ = <FIFO>;

Steps to reproduce​:

$ mknod fifo p
$ cat > fifo &
$ perl bug.pl

When the alarm is triggered, the perl process will segfault​:

Starting program​: /usr/bin/debugperl 275357.pl
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault.
0x000000000059de23 in PerlIOBuf_fill (my_perl=0x870010, f=0x88ca88) at perlio.c​:3901
3901 perlio.c​: No such file or directory.
  in perlio.c
(gdb) bt
#0 0x000000000059de23 in PerlIOBuf_fill (my_perl=0x870010, f=0x88ca88) at perlio.c​:3901
#1 0x000000000059b228 in Perl_PerlIO_fill (my_perl=0x5, f=0x8a1638) at perlio.c​:1725
#2 0x000000000059c1fb in PerlIOBase_read (my_perl=0x870010, f=0x88ca88, vbuf=<value optimized out>, count=1) at perlio.c​:2143
#3 0x000000000059c338 in PerlIO_getc (f=0x88ca88) at perlio.c​:5066
#4 0x0000000000506251 in Perl_sv_gets (my_perl=<value optimized out>, sv=0x8a4038, fp=<value optimized out>, append=0) at sv.c​:6853
#5 0x00000000004cf66f in Perl_do_readline (my_perl=0x870010) at pp_hot.c​:1665
#6 0x000000000049b34b in Perl_runops_debug (my_perl=0x870010) at dump.c​:1968
#7 0x000000000043d04f in S_run_body (my_perl=<value optimized out>) at perl.c​:2431
#8 perl_run (my_perl=<value optimized out>) at perl.c​:2349
#9 0x0000000000421b4c in main (argc=2, argv=0x7fffffffdac8, env=0x7fffffffdae0) at perlmain.c​:117

This perlbug output and the above backtrace are with perl 5.10.1, but I've
also tested with blead and the issue is still present.

There's some extra analysis on the Debian bug report​:

==========
PerlIOUnix_read has a loop which makes a blocking read, and calls
PERL_ASYNC_CHECK() if the read is interrupted by a signal.

Once PERL_ASYNC_CHECK() has returned, the pointers "f" and "buf"
in PerlIOUnix_read are pointing to freed space, which looks fairly
simple to detect and handle. Similar bugs also need fixing
elsewhere in perlio.c.



Flags​:
  category=core
  severity=medium


Site configuration information for perl 5.10.1​:

Configured by Debian Project at Sun Apr 11 20​:09​:49 UTC 2010.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:
 
  Platform​:
  osname=linux, osvers=2.6.32-3-amd64, archname=x86_64-linux-gnu-thread-multi
  uname='linux madeleine 2.6.32-3-amd64 #1 smp wed feb 24 18​:07​:42 utc 2010 x86_64 gnulinux '
  config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.10 -Darchlib=/usr/lib/perl/5.10 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.10.1 -Dsitearch=/usr/local/lib/perl/5.10.1 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.10.1 -Dd_dosuid -des'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2 -g',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.4.3', 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 -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
  libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
  perllibs=-ldl -lm -lpthread -lc -lcrypt
  libc=/lib/libc-2.10.2.so, so=so, useshrplib=true, libperl=libperl.so.5.10.1
  gnulibc_version='2.10.2'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector'

Locally applied patches​:
  DEBPKG​:debian/arm_thread_stress_timeout - http​://bugs.debian.org/501970 Raise the timeout of ext/threads/shared/t/stress.t to accommodate slower build hosts
  DEBPKG​:debian/cpan_config_path - Set location of CPAN​::Config to /etc/perl as /usr may not be writable.
  DEBPKG​:debian/cpan_definstalldirs - Provide a sensible INSTALLDIRS default for modules installed from CPAN.
  DEBPKG​:debian/db_file_ver - http​://bugs.debian.org/340047 Remove overly restrictive DB_File version check.
  DEBPKG​:debian/doc_info - Replace generic man(1) instructions with Debian-specific information.
  DEBPKG​:debian/enc2xs_inc - http​://bugs.debian.org/290336 Tweak enc2xs to follow symlinks and ignore missing @​INC directories.
  DEBPKG​:debian/errno_ver - http​://bugs.debian.org/343351 Remove Errno version check due to upgrade problems with long-running processes.
  DEBPKG​:debian/extutils_hacks - Various debian-specific ExtUtils changes
  DEBPKG​:debian/fakeroot - Postpone LD_LIBRARY_PATH evaluation to the binary targets.
  DEBPKG​:debian/instmodsh_doc - Debian policy doesn't install .packlist files for core or vendor.
  DEBPKG​:debian/ld_run_path - Remove standard libs from LD_RUN_PATH as per Debian policy.
  DEBPKG​:debian/libnet_config_path - Set location of libnet.cfg to /etc/perl/Net as /usr may not be writable.
  DEBPKG​:debian/m68k_thread_stress - http​://bugs.debian.org/495826 Disable some threads tests on m68k for now due to missing TLS.
  DEBPKG​:debian/mod_paths - Tweak @​INC ordering for Debian
  DEBPKG​:debian/module_build_man_extensions - http​://bugs.debian.org/479460 Adjust Module​::Build manual page extensions for the Debian Perl policy
  DEBPKG​:debian/perl_synopsis - http​://bugs.debian.org/278323 Rearrange perl.pod
  DEBPKG​:debian/prune_libs - http​://bugs.debian.org/128355 Prune the list of libraries wanted to what we actually need.
  DEBPKG​:debian/use_gdbm - Explicitly link against -lgdbm_compat in ODBM_File/NDBM_File.
  DEBPKG​:fixes/assorted_docs - http​://bugs.debian.org/443733 [384f06a] Math​::BigInt​::CalcEmu documentation grammar fix
  DEBPKG​:fixes/net_smtp_docs - http​://bugs.debian.org/100195 [rt.cpan.org #36038] Document the Net​::SMTP 'Port' option
  DEBPKG​:fixes/processPL - http​://bugs.debian.org/357264 [rt.cpan.org #17224] Always use PERLRUNINST when building perl modules.
  DEBPKG​:debian/perlivp - http​://bugs.debian.org/510895 Make perlivp skip include directories in /usr/local
  DEBPKG​:fixes/pod2man-index-backslash - http​://bugs.debian.org/521256 Escape backslashes in .IX entries
  DEBPKG​:debian/disable-zlib-bundling - Disable zlib bundling in Compress​::Raw​::Zlib
  DEBPKG​:fixes/kfreebsd_cppsymbols - http​://bugs.debian.org/533098 [3b910a0] Add gcc predefined macros to $Config{cppsymbols} on GNU/kFreeBSD.
  DEBPKG​:debian/cpanplus_definstalldirs - http​://bugs.debian.org/533707 Configure CPANPLUS to use the site directories by default.
  DEBPKG​:debian/cpanplus_config_path - Save local versions of CPANPLUS​::Config​::System into /etc/perl.
  DEBPKG​:fixes/kfreebsd-filecopy-pipes - http​://bugs.debian.org/537555 [16f708c] Fix File​::Copy​::copy with pipes on GNU/kFreeBSD
  DEBPKG​:fixes/anon-tmpfile-dir - http​://bugs.debian.org/528544 [perl #66452] Honor TMPDIR when open()ing an anonymous temporary file
  DEBPKG​:fixes/abstract-sockets - http​://bugs.debian.org/329291 [89904c0] Add support for Abstract namespace sockets.
  DEBPKG​:fixes/hurd_cppsymbols - http​://bugs.debian.org/544307 [eeb92b7] Add gcc predefined macros to $Config{cppsymbols} on GNU/Hurd.
  DEBPKG​:fixes/autodie-flock - http​://bugs.debian.org/543731 Allow for flock returning EAGAIN instead of EWOULDBLOCK on linux/parisc
  DEBPKG​:fixes/archive-tar-instance-error - http​://bugs.debian.org/539355 [rt.cpan.org #48879] Separate Archive​::Tar instance error strings from each other
  DEBPKG​:fixes/positive-gpos - http​://bugs.debian.org/545234 [perl #69056] [c584a96] Fix \\G crash on first match
  DEBPKG​:debian/devel-ppport-ia64-optim - http​://bugs.debian.org/548943 Work around an ICE on ia64
  DEBPKG​:fixes/trie-logic-match - http​://bugs.debian.org/552291 [perl #69973] [0abd0d7] Fix a DoS in Unicode processing [CVE-2009-3626]
  DEBPKG​:fixes/hppa-thread-eagain - http​://bugs.debian.org/554218 make the threads-shared test suite more robust, fixing failures on hppa
  DEBPKG​:fixes/crash-on-undefined-destroy - http​://bugs.debian.org/564074 [perl #71952] [1f15e67] Fix a NULL pointer dereference when looking for a DESTROY method
  DEBPKG​:fixes/tainted-errno - http​://bugs.debian.org/574129 [perl #61976] [be1cf43] fix an errno stringification bug in taint mode
  DEBPKG​:patchlevel - http​://bugs.debian.org/567489 List packaged patches for 5.10.1-12 in patchlevel.h


@​INC for perl 5.10.1​:
  /etc/perl
  /usr/local/lib/perl/5.10.1
  /usr/local/share/perl/5.10.1
  /usr/lib/perl5
  /usr/share/perl5
  /usr/lib/perl/5.10
  /usr/share/perl/5.10
  /usr/local/lib/site_perl
  .


Environment for perl 5.10.1​:
  HOME=/home/chrisb
  LANG=en_GB.UTF-8
  LANGUAGE (unset)
  LC_ALL=en_GB.UTF-8
  LC_CTYPE=en_GB.UTF-8
  LC_MESSAGES=en_GB.UTF-8
  LC_TIME=en_GB.UTF-8
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/home/chrisb/bin​:/home/chrisb/bin​:/usr/bin​:/home/chrisb/bin​:/usr/local/bin​:/usr/bin​:/bin​:/usr/games
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Jul 19, 2010

From @iabyn

Still present in blead

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Jul 25, 2010

From @cpansprout

PerlIOUnix_read has a loop which makes a blocking read, and calls
PERL_ASYNC_CHECK() if the read is interrupted by a signal.

Once PERL_ASYNC_CHECK() has returned, the pointers "f" and "buf"
in PerlIOUnix_read are pointing to freed space, which looks fairly
simple to detect and handle. Similar bugs also need fixing
elsewhere in perlio.c.

I don’t know a lot about C, but I think that the freed memory could be re-used for something else, in which case checking that it has been freed (how do you do that, BTW?) will not be reliable. (Someone please correct me if I’m wrong.) Maybe we need some sort of refcounting mechanism for PerlIOl’s. How much of the PerlIO API is public?

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Jul 25, 2010

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

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 26, 2010

From @iabyn

On Sun, Jul 25, 2010 at 01​:02​:01PM -0700, Father Chrysostomos wrote​:

PerlIOUnix_read has a loop which makes a blocking read, and calls
PERL_ASYNC_CHECK() if the read is interrupted by a signal.

Once PERL_ASYNC_CHECK() has returned, the pointers "f" and "buf"
in PerlIOUnix_read are pointing to freed space, which looks fairly
simple to detect and handle. Similar bugs also need fixing
elsewhere in perlio.c.

I don’t know a lot about C, but I think that the freed memory could be
re-used for something else, in which case checking that it has been
freed (how do you do that, BTW?) will not be reliable. (Someone please
correct me if I’m wrong.) Maybe we need some sort of refcounting
mechanism for PerlIOl’s. How much of the PerlIO API is public?

Now fixed (sort-of) by the following set of commits​:

  303f2dc
  16865ff
  8995e67
  cc6623a
  abf9167

but most specifically by that last one​:

commit abf9167
Author​: David Mitchell <davem@​iabyn.com>
AuthorDate​: Mon Nov 22 19​:18​:49 2010 +0000
Commit​: David Mitchell <davem@​iabyn.com>
CommitDate​: Fri Nov 26 16​:01​:34 2010 +0000

  Make PerlIO marginally reentrant
 
  Currently if an operation on a file handle is interrupted, and if
  the signal handler accesses that same file handle (e.g. closes it),
  then perl will crash. See [perl #75556].
 
  This commit provides some basic infrastructure to avoid segfaults.
  Basically it adds a lock count field to each handle (by re-purposing the
  unused flags field in the PL_perlio array), then each time a signal
  handler is called, the count is incremented. Then various parts of PerlIO
  use a positive count to change behaviour. Most importantly, when layers
  are popped, the PerlIOl structure is cleared, but not freed, and is left
  in the chain of layers. This means that callers still holding pointers to
  the various layers won't access freed structures. It does however mean
  that PerlIOl structs may be leaked, and possibly slots in PL_perlio. But
  this is better than crashing.
 
  Not much has been done to give sensible behaviour on re-entrancy; for
  example, a buffer that has already been written once might get written
  again. Fixing this sort of thing would require a large-scale audit of
  perlio.c.

Note that the glib fread() function crashes if you call fclose() in a
signal-handler, so we're better than that now :-)

--
"The GPL violates the U.S. Constitution, together with copyright,
antitrust and export control laws"
  -- SCO smoking crack again.

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 28, 2010

@iabyn - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant