Gmane
Favicon
From: William McVey <wam <at> cisco.com>
Subject: fix for sndrcv bug (was Re: [scapy.ml] Bug in sndrcv timeouts when combined with filters.)
Newsgroups: gmane.comp.security.scapy.general
Date: 2006-03-09 21:01:15 GMT (3 years, 16 weeks, 6 days, 7 hours and 26 minutes ago)
I told myself I'd just file the bug and let someone else work out the
fix, but I just couldn't let it go... Attached is a patch that fixes the
behavior I reported with timeouts not being honored when filters
matching the sent packet are applied.

The problem was in the logic associated with various Socket class's
recv() methods. For example, in L3PacketSocket:

    def recv(self, x):
        while 1:
            pkt, sa_ll = self.ins.recvfrom(x)
            if sa_ll[2] != socket.PACKET_OUTGOING:
                break
	<snip>

Note that in this case, multiple invocations of recvfrom() could be
called, even though we haven't gone through another select() to
determine if there is any more data waiting to be read. When there is a
lot packets matching an applied filter, this isn't a problem, but when
the only packet matching the filter is the outbound packet, the first
recvfrom() will pick up the sent packet, the 'while' will loop and
recvfrom() will block with no timeout on the second invocation.

The fix was easy, instead of looping in recv(), we just kick back a None
from recv, and sndrecv already handles the cycling the loop again
(stopping along the way with a select() with a timeout). I did a quick
search looking for invocations of 'recv()' which would have a problem
with a None return and there didn't appear to be any places other than
sndrcv() that calls recv() in on a L3PacketSocket or a L2Socket,
although I guess it's possible... perhaps 'recv()' method should take an
'ignore_sent' parameter that sndrecv() could flag, but all other
invocations of recv() would not concern themselves with filtering out
sent packets... Anyway, I would personally imagine that recv()
potentially returning None is not likely to hurt anything, so that's the
behavior my patch implements.

  -- William

P.S. My test case for the bug submitted in my prior mesg obviously
succeeds with this patch installed.
--- scapy-1.0.3.24.py	2006-03-09 20:28:35.258593327 +0000
+++ scapy.py	2006-03-09 20:30:11.578408537 +0000
@@ -7957,10 +7957,9 @@
                 set_promisc(self.ins, i, 0)
         SuperSocket.close(self)
     def recv(self, x):
-        while 1:
-            pkt, sa_ll = self.ins.recvfrom(x)
-            if sa_ll[2] != socket.PACKET_OUTGOING:
-                break
+        pkt, sa_ll = self.ins.recvfrom(x)
+        if sa_ll[2] != socket.PACKET_OUTGOING:
+            return None
         if LLTypes.has_key(sa_ll[3]):
             cls = LLTypes[sa_ll[3]]
             lvl = 2
@@ -8028,10 +8027,9 @@
             self.LL = Ether

     def recv(self, x):
-        while 1:
-            pkt, sa_ll = self.ins.recvfrom(x)
-            if sa_ll[2] != socket.PACKET_OUTGOING:
-                break
+        pkt, sa_ll = self.ins.recvfrom(x)
+        if sa_ll[2] == socket.PACKET_OUTGOING:
+            return None
         try:
             q = self.LL(pkt)
         except:

---------------------------------------------------------------------
Desinscription: envoyez un message a: scapy.ml-unsubscribe <at> secdev.org
Pour obtenir de l'aide, ecrivez a: scapy.ml-help <at> secdev.org