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

crash when peerhost called #13101

Closed
p5pRT opened this issue Jul 10, 2013 · 12 comments
Closed

crash when peerhost called #13101

p5pRT opened this issue Jul 10, 2013 · 12 comments

Comments

@p5pRT
Copy link

p5pRT commented Jul 10, 2013

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

Searchable as RT118843$

@p5pRT
Copy link
Author

p5pRT commented Jul 10, 2013

From xyf.xiao@gmail.com

Created by xyf.xiao@gmail.com

calling peerhost function after recv, can result crash and throw​:

Bad arg length for Socket​::unpack_sockaddr_in, length is 4096, should
be 16 at /usr/lib/perl5/5.14/i686-cygwin-threads-64int/Socket.pm line
559.

Below is test code which works fine in windows​:

use IO​::Select;
use IO​::Socket​::INET;

my $data;

my $servSock = IO​::Socket​::INET->new(LocalPort => 6666,
  Listen => 100,);

my $select =IO​::Select->new($servSock);
while(1){

  my $clientSock = $servSock->accept();
  $select->add($clientSock);
  $clientSock->recv( $data, 100, 0);
  warn $clientSock->peerhost();
  close($clientSock);
}

Perl Info

Flags:
    category=library
    severity=low
    module=IO::Socket::INET

Site configuration information for perl 5.14.2:

Configured by rurban at Thu Jul 12 13:58:56 CDT 2012.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration:

  Platform:
    osname=cygwin, osvers=1.7.15(0.26053), archname=cygwin-thread-multi-64int
    uname='cygwin_nt-5.1 winxp 1.7.15(0.26053) 2012-05-09 10:25 i686 cygwin '
    config_args='-de -Dlibperl=cygperl5_14.dll -Dcc=gcc-4 -Dld=g++-4
-Darchname=i686-cygwin-threads-64int -Dmksymlinks -Dusethreads
-Accflags=-g'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc-4', ccflags ='-DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -g
-fno-strict-aliasing -pipe -fstack-protector',
    optimize='-O3',
    cppflags='-DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -g
-fno-strict-aliasing -pipe -fstack-protector'
    ccversion='', gccversion='4.5.3', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='double', nvsize=8,
Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='g++-4', ldflags =' -Wl,--enable-auto-import
-Wl,--export-all-symbols -Wl,--enable-auto-image-base
-fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib /lib
    libs=-lgdbm -ldb -ldl -lcrypt -lgdbm_compat
    perllibs=-ldl -lcrypt
    libc=/usr/lib/libc.a, so=dll, useshrplib=true, libperl=cygperl5_14.dll
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' --shared  -Wl,--enable-auto-import
-Wl,--export-all-symbols -Wl,--enable-auto-image-base -L/usr/local/lib
-fstack-protector'

Locally applied patches:
    Bug#55162 File::Spec::case_tolerant performance
    CYG07 $vendorarch/auto/.rebase
    CYG15 static Win32CORE
    CYG17 cyg-1.7 paths-utf8
    0c612ce82 Fix building static extensions on cygwin, -UUSEIMPORTLIB
    1bac5ecc1 Fix 64-bit threading sv.c: S_anonymise_cv_maybe
    Cygwin::sync_winenv added


@INC for perl 5.14.2:
    /usr/lib/perl5/site_perl/5.14/i686-cygwin-threads-64int
    /usr/lib/perl5/site_perl/5.14
    /usr/lib/perl5/vendor_perl/5.14/i686-cygwin-threads-64int
    /usr/lib/perl5/vendor_perl/5.14
    /usr/lib/perl5/5.14/i686-cygwin-threads-64int
    /usr/lib/perl5/5.14
    /usr/lib/perl5/site_perl/5.10
    /usr/lib/perl5/vendor_perl/5.10
    /usr/lib/perl5/site_perl/5.8
    .


Environment for perl 5.14.2:
    HOME=/home/Administrator
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/usr/bin:/cygdrive/c/Perl/site/lib/auto/MinGW/bin:/cygdrive/c/oracle/product/10.2.0/db_1/bin:/cygdrive/c/Perl/site/bin:/cygdrive/c/Perl/bin:/cygdrive/c/Program
Files/Common Files/NetSarang:%JAVE-HOME%/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program
Files/ATI Technologies/ATI.ACE/Core-Static:/cygdrive/c/Program
Files/Common Files/Thunder
Network/KanKan/Codecs:/cygdrive/c/Converge/bin:/cygdrive/c/Converge/bin/asm:/cygdrive/c/Wind/Wind.NET.Client/WindNET/bin:/cygdrive/c/Program
Files/Calibre2
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @jkeenan

On Wed Jul 10 00​:13​:27 2013, xyf.xiao@​gmail.com wrote​:

This is a bug report for perl from xyf.xiao@​gmail.com,
generated with the help of perlbug 1.39 running under perl 5.14.2.

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

calling peerhost function after recv, can result crash and throw​:

Bad arg length for Socket​::unpack_sockaddr_in, length is 4096, should
be 16 at /usr/lib/perl5/5.14/i686-cygwin-threads-64int/Socket.pm line
559.

Below is test code which works fine in windows​:

use IO​::Select;
use IO​::Socket​::INET;

my $data;

my $servSock = IO​::Socket​::INET->new(LocalPort => 6666,
Listen => 100,);

my $select =IO​::Select->new($servSock);
while(1){

    my $clientSock = $servSock\->accept\(\);
    $select\->add\($clientSock\);
    $clientSock\->recv\( $data\, 100\, 0\);
    warn $clientSock\->peerhost\(\);
    close\($clientSock\);

}

How would I run this program on a Unix-like system and get meaningful
output?

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

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

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @tonycoz

On Thu Jul 11 18​:08​:56 2013, jkeenan wrote​:

How would I run this program on a Unix-like system and get meaningful
output?

Run it in one terminal, then connect to port 6666 with any TCP client​:

(first terminal)
tony@​mars​:.../git/perl$ ./perl -Ilib /home/tony/play/rt11843-server.pl
127.0.0.1 at /home/tony/play/rt11843-server.pl line 15.

(second terminal)
tony@​mars​:.../git/bse$ telnet localhost 6666
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
^]
telnet> Connection closed.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From xyf.xiao@gmail.com

On Fri, Jul 12, 2013 at 9​:44 AM, Tony Cook via RT
<perlbug-followup@​perl.org> wrote​:

On Thu Jul 11 18​:08​:56 2013, jkeenan wrote​:

How would I run this program on a Unix-like system and get meaningful
output?

Run it in one terminal, then connect to port 6666 with any TCP client​:

(first terminal)
tony@​mars​:.../git/perl$ ./perl -Ilib /home/tony/play/rt11843-server.pl
127.0.0.1 at /home/tony/play/rt11843-server.pl line 15.

(second terminal)
tony@​mars​:.../git/bse$ telnet localhost 6666
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
^]
telnet> Connection closed.

Tony

---
via perlbug​: queue​: perl5 status​: open
https://rt-archive.perl.org/perl5/Ticket/Display.html?id=118843

Hi,
Thanks all to reply ! it seems a OS specific issue, The test script
works fine in both windos and linux platform. I'll do some dig at this
weekend to find the underlying reason.

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @tonycoz

On Fri, Jul 12, 2013 at 12​:26​:18PM +0800, Xiao Yafeng wrote​:

Hi,
Thanks all to reply ! it seems a OS specific issue, The test script
works fine in both windos and linux platform. I'll do some dig at this
weekend to find the underlying reason.

It's possible​:

https://rt.cpan.org/Ticket/Display.html?id=86613

is related to this.

Tony

@p5pRT
Copy link
Author

p5pRT commented Sep 12, 2013

From @tonycoz

On Thu Jul 11 21​:54​:34 2013, tonyc wrote​:

On Fri, Jul 12, 2013 at 12​:26​:18PM +0800, Xiao Yafeng wrote​:

Hi,
Thanks all to reply ! it seems a OS specific issue, The test script
works fine in both windos and linux platform. I'll do some dig at this
weekend to find the underlying reason.

It's possible​:

https://rt.cpan.org/Ticket/Display.html?id=86613

is related to this.

The fix for 86613 doesn't appear to have fixed this problem.

tony@​phobos ~/dev/perl/git/perl
$ ./perl -Ilib ../socket.test
Bad arg length for Socket​::unpack_sockaddr_in, length is 68719480832,
should be 1 at lib/Socket.pm line 830.

tony@​phobos ~/dev/perl/git/perl
$ ./perl -v

This is perl 5, version 19, subversion 4 (v5.19.4
(v5.19.3-441-g9c7618b)) built for cygwin-thread-multi-64int

Copyright 1987-2013, Larry Wall

Perl may be copied only under the terms of either the Artistic License
or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.

tony@​phobos ~/dev/perl/git/perl
$ uname -a
CYGWIN_NT-6.1-WOW64 phobos 1.7.25(0.270/5/3) 2013-08-31 20​:39 i686 Cygwin

tony@​phobos ~/dev/perl/git/perl
$

@p5pRT
Copy link
Author

p5pRT commented Dec 18, 2013

From @tonycoz

On Thu Jul 11 21​:27​:20 2013, xyf.xiao@​gmail.com wrote​:

Thanks all to reply ! it seems a OS specific issue, The test script
works fine in both windos and linux platform. I'll do some dig at this
weekend to find the underlying reason.

It looks like the bug is cygwin (or maybe a limitation of Win32) doesn't update the socklen parameter supplied to recvfrom(), so if you supply a large buffer (as perl does, since it needs to allow for non-IPv4 protocols like UNIX sockets), the whole buffer is returned, not just the struct sockaddr_in part.

As to whether this is a Win32 limitation - the Win32 documentation for both recvfrom() [1] and WSARecvFrom() [2] both indicate that the from/fromlen parameters are ignored for connection oriented sockets.

Tony

@p5pRT
Copy link
Author

p5pRT commented Dec 19, 2013

From @tonycoz

On Wed Dec 18 15​:59​:59 2013, tonyc wrote​:

On Thu Jul 11 21​:27​:20 2013, xyf.xiao@​gmail.com wrote​:

Thanks all to reply ! it seems a OS specific issue, The test script
works fine in both windos and linux platform. I'll do some dig at
this
weekend to find the underlying reason.

It looks like the bug is cygwin (or maybe a limitation of Win32)
doesn't update the socklen parameter supplied to recvfrom(), so if you
supply a large buffer (as perl does, since it needs to allow for non-
IPv4 protocols like UNIX sockets), the whole buffer is returned, not
just the struct sockaddr_in part.

As to whether this is a Win32 limitation - the Win32 documentation for
both recvfrom() [1] and WSARecvFrom() [2] both indicate that the
from/fromlen parameters are ignored for connection oriented sockets.

Thinking about it some more, I wonder if the definition and implementation of recv()s return value is simply broken.

From my reading, POSIX[1] makes no guarantees about the value of *I<address_len> (or the memory addressed by I<address>) when reading from a socket​:

  If the address argument is not a null pointer and the protocol does not provide
  the source address of messages, the value stored in the object pointed to by
  address is unspecified.

Both Linux, OS/X and OpenBSD (and probably others) happen to set *address_len to 0, but I don't see that behaviour specified anywhere.

An implementation might ignore address and *address_len instead, as Win32[2] and cygwin both do.

All that said, I might just workaround this in the same way as win32_recvfrom() does - call getpeername() if the output address_len is the same as the input.

Tony

[1] http​://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html
[2] we workaround this

@p5pRT
Copy link
Author

p5pRT commented Jan 7, 2014

From @tonycoz

On Wed Dec 18 16​:42​:30 2013, tonyc wrote​:

All that said, I might just workaround this in the same way as
win32_recvfrom() does - call getpeername() if the output address_len
is the same as the input.

Pushed as a smoke-me, including some socket tests, which we don't appear to have
in t/ at all.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2014

From @tonycoz

On Mon Jan 06 21​:11​:34 2014, tonyc wrote​:

On Wed Dec 18 16​:42​:30 2013, tonyc wrote​:

All that said, I might just workaround this in the same way as
win32_recvfrom() does - call getpeername() if the output address_len
is the same as the input.

Pushed as a smoke-me, including some socket tests, which we don't
appear to have
in t/ at all.

Pushed with some race condition fixes as e122534.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 14, 2014

@tonycoz - 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