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

socket on fd 1 gets duped to fd 0 on close(STDIN)+close(STDOUT) #7595

Closed
p5pRT opened this issue Nov 15, 2004 · 10 comments
Closed

socket on fd 1 gets duped to fd 0 on close(STDIN)+close(STDOUT) #7595

p5pRT opened this issue Nov 15, 2004 · 10 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 15, 2004

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

Searchable as RT32446$

@p5pRT
Copy link
Author

p5pRT commented Nov 15, 2004

From Steffen_Ullrich@genua.de

Created by steffen@genua.de

- create a socket
- duplicate it to STDIN+STDOUT, close original socket
- close STDIN + STDOUT
--> socket stays open at fd 0

Example program follows, including output from ktrace/kdump
for the relevant sections. Example is a small server which
listens, and duplicates the client socket to STDIN+STDOUT after
accept and closes the original socket. After the server is done
with the client STDIN+STDOUT will be closed which should release
the socket. But instead it closes STDIN (releasing fd 0)
and instead of closing STDOUT it duplicates STDOUT to fd 0 and
then closes fd 1. Later attempts to open STDIN get a fd != 0.

Example works a openbsd3.6/perl5.8.5. I can't reproduce the
bug on Linux/perl5.8.3.
Looking at the code in perlio.c there might be a problem in
PerlIOStdio_close.

  1 use strict;
  2 use IO​::Socket;
  3
  4 my $srv = IO​::Socket​::INET->new( LocalAddr => $ARGV[0], Listen => 10, Reuse => 1 )
  5 || die "listen​: $!";
  6 __TRACE__(1);
  7 my ($cl,$peer) = $srv->accept || next;
  8 print STDERR "NEW CONNECTION\n";

duplicate socket to STDIN,STDOUT and close socket fd

  9 open( STDIN,"<&".fileno($cl));
  10 open( STDOUT,">&".fileno($cl));
  11 select(STDOUT); $|=1;
  12 __TRACE__(2);
  13 $cl->close;
  14 __TRACE__(3);
  15 print "hallo\n";
  16
  17
  18 print STDERR "END CONNECTION\n";

  19 __TRACE__(4);
  20 close(STDIN);

closing STDIN gives the following kdump

| 22650 perl CALL close(0)
| 22650 perl RET close 0

  21 __TRACE__(5);
  22 close(STDOUT);

closing STDOUT shows it duplicating fd 1 to fd 0
and the closing fd 1 two times.

| 22650 perl CALL dup(0x1)
| 22650 perl RET dup 0
| 22650 perl CALL close(0x1)
| 22650 perl RET close 0
| 22650 perl CALL close(0x1)
| 22650 perl RET close -1 errno 9 Bad file descriptor

  23 __TRACE__(6);
  24 sub __TRACE__ { print STDERR "TRACE @​_\n" }
  25 #sub __TRACE__ { system( "fstat -p$$ >t@​_" ) }

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl v5.8.5:

Configured by root at Wed Oct 27 10:28:52 CEST 2004.

Summary of my perl5 (revision 5 version 8 subversion 5) configuration:
  Platform:
    osname=openbsd, osvers=3.6, archname=i386-openbsd
    uname='openbsd'
    config_args='-dsE -Dopenbsd_distribution=defined'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -I/usr/local/include',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='2.95.3 20010125 (prerelease, propolice)', gccosandvers='openbsd3.6'
    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='cc', ldflags ='-Wl,-E '
    libpth=/usr/lib
    libs=-lm -lutil -lc
    perllibs=-lm -lutil -lc
    libc=/usr/lib/libc.so.34.1, so=so, useshrplib=true, libperl=libperl.so.10.0
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-R/usr/libdata/perl5/i386-openbsd/5.8.5/CORE'
    cccdlflags='-DPIC -fPIC ', lddlflags='-shared -fPIC '

Locally applied patches:
    


@INC for perl v5.8.5:
    /usr/libdata/perl5/i386-openbsd/5.8.5
    /usr/local/libdata/perl5/i386-openbsd/5.8.5
    /usr/libdata/perl5
    /usr/local/libdata/perl5
    /usr/local/libdata/perl5/site_perl/i386-openbsd
    /usr/libdata/perl5/site_perl/i386-openbsd
    /usr/local/libdata/perl5/site_perl
    /usr/libdata/perl5/site_perl
    /usr/local/lib/perl5/site_perl
    .


Environment for perl v5.8.5:
    HOME=/home/steffen
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/steffen/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin
    PERL_BADLANG (unset)
    SHELL=/bin/ksh

@p5pRT
Copy link
Author

p5pRT commented Dec 1, 2004

From coyote.frank@gmx.net

This is a patch which resolves the problem for OpenBSD by using the
same code like Linux,FreeBSD... do.
Apperantly there is something buggy with the planned fallback in
perlio.c, function PerlIOStdio_invalidate_fileno, called from
PerlIOStdio_close.

So this fix should fix the problem for OpenBSD, but not for the other
platforms which have no special handling in PerlIOStdio_invalidate_fileno.

@p5pRT
Copy link
Author

p5pRT commented Dec 1, 2004

From coyote.frank@gmx.net

perlbug-32446.patch
--- /usr/src/gnu/usr.bin/perl/perlio.c	Mon Aug  9 20:08:55 2004
+++ perlio.c	Wed Dec  1 14:22:48 2004
@@ -2875,6 +2875,13 @@
      */
     f->_file = -1;
     return 1;
+#  elif defined(__OpenBSD__)
+    /* There may be a better way on OpenBSD:
+        - we could insert a dummy func in the _close function entry
+	f->_close = (int (*)(void *)) dummy_close;
+     */
+    f->_file = -1;
+    return 1;
 #  elif defined(__EMX__)
     /* f->_flags &= ~_IOOPEN; */	/* Will leak stream->_buffer */
     f->_handle = -1;

@p5pRT
Copy link
Author

p5pRT commented Dec 1, 2004

From coyote.frank@gmx.net

perl #32446 describes a bug with perl5.8 on OpenBSD, where a STDOUT gets
duped to a socket and a close(STDOUT) later leaves the socket open.
Attached is a proposed and tested fix for the problem, which simply
duplicates the FreeBSD code for OpenBSD.

Details​:
In perlio.c there is a function PerlIOStdio_invalidate_fileno which gets
used to close a stdio FILE* without closing the fd. There are a lot of
special cases for various platforms and then there is a fallback.
Apperantly the fallback is buggy.
The patch does not attempt to fix the fallback, it simply adds another
special case, this time for __OpenBSD__

@p5pRT
Copy link
Author

p5pRT commented Dec 1, 2004

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

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2004

From coyote.frank@gmx.net

for whatever reason the second message with the patch included did not
make it on the list. I'll try again. Here is the patch​:

Inline Patch
--- perlio.c.orig  Mon Aug  9 20:08:55 2004
+++ perlio.c    Wed Dec  1 14:22:48 2004
@@ -2875,6 +2875,13 @@
       */
      f->_file = -1;
      return 1;
+#  elif defined(__OpenBSD__)
+    /* There may be a better way on OpenBSD:
+        - we could insert a dummy func in the _close function entry
+   f->_close = (int (*)(void *)) dummy_close;
+     */
+    f->_file = -1;
+    return 1;
  #  elif defined(__EMX__)
      /* f->_flags &= ~_IOOPEN; */   /* Will leak stream->_buffer */
      f->_handle = -1;



Steffen Ullrich wrote: > perl \#32446 describes a bug with perl5\.8 on OpenBSD\, where a STDOUT gets > duped to a socket and a close\(STDOUT\) later leaves the socket open\. > Attached is a proposed and tested fix for the problem\, which simply > duplicates the FreeBSD code for OpenBSD\. > > Details​: > In perlio\.c there is a function PerlIOStdio\_invalidate\_fileno which gets > used to close a stdio FILE\* without closing the fd\. There are a lot of > special cases for various platforms and then there is a fallback\. > Apperantly the fallback is buggy\. > The patch does not attempt to fix the fallback\, it simply adds another > special case\, this time for \_\_OpenBSD\_\_ > >

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2004

From coyote.frank@gmx.net

ooops, forgot to attach the patch

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2004

From coyote.frank@gmx.net

perlbug-32446.patch
--- /usr/src/gnu/usr.bin/perl/perlio.c	Mon Aug  9 20:08:55 2004
+++ perlio.c	Wed Dec  1 14:22:48 2004
@@ -2875,6 +2875,13 @@
      */
     f->_file = -1;
     return 1;
+#  elif defined(__OpenBSD__)
+    /* There may be a better way on OpenBSD:
+        - we could insert a dummy func in the _close function entry
+	f->_close = (int (*)(void *)) dummy_close;
+     */
+    f->_file = -1;
+    return 1;
 #  elif defined(__EMX__)
     /* f->_flags &= ~_IOOPEN; */	/* Will leak stream->_buffer */
     f->_handle = -1;

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2005

From @rgs

Steffen Ullrich wrote​:

perl #32446 describes a bug with perl5.8 on OpenBSD, where a STDOUT gets
duped to a socket and a close(STDOUT) later leaves the socket open.
Attached is a proposed and tested fix for the problem, which simply
duplicates the FreeBSD code for OpenBSD.

Details​:
In perlio.c there is a function PerlIOStdio_invalidate_fileno which gets
used to close a stdio FILE* without closing the fd. There are a lot of
special cases for various platforms and then there is a fallback.
Apperantly the fallback is buggy.
The patch does not attempt to fix the fallback, it simply adds another
special case, this time for __OpenBSD__

Thanks, your patch applied as change #23844 to bleadperl.

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2005

@rgs - 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
Development

No branches or pull requests

1 participant