Nmap Development mailing list archives

Re: Assertion failure with zero-byte Nsock writes


From: David Fifield <david () bamsoftware com>
Date: Mon, 15 Feb 2010 14:07:38 -0700

On Thu, Jan 21, 2010 at 11:17:05PM -0800, Fyodor wrote:
On Thu, Jan 21, 2010 at 06:38:00PM -0700, David Fifield wrote:
You can crash Nmap with the following NSE script:

[...]

Do we want to change this? Some alternatives are to treat this as a
normal, handleable Nsock error, to treat the call as a no-op (in the TCP
case) and return success immediately, or to just do a zero-byte send
with whatever behavior that may invoke.

I don't think that the assertion was meant to prohibit zero-byte write,
though it has that effect. It looks like it was meant to catch errors in
Nsock's internal buffering code, where the internal send routine
shouldn't be called again once the buffer is exhausted.

It sounds worth changing to me.  NSE scripts shouldn't be able to
crash Nmap so easily.

Making it a normal, handleable Nsock error sounds like a good solution
to me.  I think such calls are generally a bug (or at least an
inefficiency), and returning an error will increase the chances that
they get noticed and fixed.

On the other hand, I'm fine with treating it as a no-op if you prefer
that.  I guess it avoids the higher level code having to check, and it
"just works" with only a small performance penalty caused by the
higher-level code doing a pointless write and dealing with the
callback.

I would only advocate the zero-byte send approach if you like the
no-op idea, and that is easier to implement.  Or if someone knows of a
legitimate reason for a zero-byte TCP write.

I did this in r16773, by only enforcing the assertion when at least one
byte has been written already for the event, allowing zero-byte writes
while still catching any error that would cause Nsock to exhaust its
data and do a send anyway.

This is the simplest way (just one added line). To raise an error for a
zero-byte TCP or UDP read, we could add a check in nsock_write. It would
not do the check if the socket's protocol was UDP.

I tested what zero-byte sends do with the change in NSE. On both Linux
and Windows, TCP sends nothing, while UDP sends a packet with no data.

I looked online, in TCP/IP Illustrated, and in the POSIX specification
at http://www.opengroup.org/onlinepubs/9699919799/, and I couldn't find
anything authoritative about what a zero-byte send is supposed to do.
The obvious thing for UDP is to send a datagram with zero bytes of data.
For TCP, it seems the only reasonable thing would be send a a packet
with zero bytes of data, or not send a packet at all. In SCTP, a
message (which is what send creates in the sockets API) can't have zero
bytes, so its only options are not to send a packet, or raise an error.

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


Current thread: