Nmap Development mailing list archives

Re: nsock_core.c:293 assertion failure (EPIPE, pipe broken)


From: Brandon Enright <bmenrigh () ucsd edu>
Date: Fri, 27 Feb 2009 04:15:01 +0000

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, 27 Feb 2009 03:56:48 +0000 or thereabouts doug () hcsw org wrote:

On Fri, Feb 27, 2009 at 02:00:48AM +0000 or thereabouts, Brandon
Enright wrote:
I was running Nmap in Valgrind at the time although no interesting
output was produce and I don't think Valgrind was the issue.
...
David did some searching and there is mention of EPIPE being
returned on send() calls when the remote host closes the connection
unexpectedly. The Nsock output though seems to indicate that EPIPE
was broken during a connect()

In unix there is a SIGPIPE signal to make implementing efficient
pipelines simpler. Take this pipeline:

cat billion-line-file.txt | head

After head is done slurping and printing the first 10 lines of the
file, it will exit, breaking the pipe. So when the cat process calls
write() again, unix will send it a SIGPIPE signal which kills it.

However, if a process ignores the SIGPIPE signal, the write will
return an EPIPE error instead and it is up to the application to
handle the problem gracefully.

You are right that connect() shouldn't return this error but check
the nsock code closely:

    /* First we want to determine whether the socket really is
connected */ if (getsockopt(iod->sd, SOL_SOCKET, SO_ERROR, (char *)
&optval, &optlen) != 0) optval = socket_errno(); /* Stupid Solaris */

    ...

    switch(optval) {

    ...

    default:
      Snprintf(buf, sizeof(buf), "Strange connect error from %s
(%d)", inet_ntop_ez(&iod->peer, iod->peerlen), optval); perror(buf);
      assert(0); /* I'd like for someone to report it */
      break;
    }

optval is from getsockopt(SOL_SOCKET, SO_ERROR) so it is the so_error
field of the socket, not an error from connect().

My guess is that the connect succeeded but the remote end closed the
connection before nmap got around to registering the connection as
successful, setting the socket's so_error to EPIPE for some reason.

If this is the case it should be fine to add EPIPE to the list of
errors that will register nse->status = NSE_STATUS_ERROR instead
of triggering the assertion, although it would be nice to know more
about under what conditions this happens.

BTW what OS were you using? Linux?

Hope this helps,

Doug

PS. DJB has some notes about the portability of getsockopt() etc:

http://cr.yp.to/docs/connect.html

I don't have my copy of Stevens' "Advanced programming in the UNIX
environment" with me but that book has more info about all of this.


Thanks for the very detailed note, Doug.

David noticed after looking at the code in more detail that the
optval was coming from getsockopt().  We added EPIPE: to the case
statement to ignore the issue.  David will probably want to commit the
change after your note.

If you can think of a way to better test that the connection was closed
and there is some sort of race let me know.

And I'm using Linux:

$ uname -a
Linux compy386 2.6.26-gentoo-r1 #5 SMP PREEMPT Thu Sep 18 18:15:51 GMT 2008 x86_64 Intel(R) Xeon(R) CPU X5355 @ 2.66GHz 
GenuineIntel GNU/Linux

Brandon

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)

iEYEARECAAYFAkmnaM8ACgkQqaGPzAsl94KHEACbBswO9k1qoIq434xpX2YNGZco
ZqQAn3IvsKQTOa/gyWLmUYBHiu0pAOLD
=xsGm
-----END PGP SIGNATURE-----

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: