-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a patch for scapy to fix fd leak issue in AsyncSniffer (#20415)
Why I did it This PR is to add a patch to fix potential fd leak issue in AsyncSniffer in scapy python library. There are two fd leak scenarios. When starting worker thread _run, if an interface is down, an OSError is thrown, and the sockets that have been created will be leaked as it never got a chance to be closed. When stopping the worker thread, same error can happen when calling close. The sockets not closed will be leaked. How I did it Catch OSError when creating sockets, and catch any exception when closing socket to ensure all sockets are closed. How to verify it Verified by the testing code above. No fd leak happened.
- Loading branch information
1 parent
6c05500
commit bf1bcb2
Showing
2 changed files
with
48 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py | ||
index f97fc415..dbcc372f 100644 | ||
--- a/scapy/sendrecv.py | ||
+++ b/scapy/sendrecv.py | ||
@@ -1111,17 +1111,19 @@ class AsyncSniffer(object): | ||
# The _RL2 function resolves the L2socket of an iface | ||
_RL2 = lambda i: L2socket or resolve_iface(i).l2listen() # type: Callable[[_GlobInterfaceType], Callable[..., SuperSocket]] # noqa: E501 | ||
if isinstance(iface, list): | ||
- sniff_sockets.update( | ||
- (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg), | ||
- ifname) | ||
- for ifname in iface | ||
- ) | ||
+ for ifname in iface: | ||
+ try: | ||
+ sniff_sockets.update({_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg): ifname}) | ||
+ except OSError: | ||
+ # Ignore OSError when opening the socket | ||
+ # The error can happen when the port goes down during the creation of the socket | ||
+ pass | ||
elif isinstance(iface, dict): | ||
- sniff_sockets.update( | ||
- (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg), | ||
- iflabel) | ||
- for ifname, iflabel in six.iteritems(iface) | ||
- ) | ||
+ for ifname, iflabel in six.iteritems(iface): | ||
+ try: | ||
+ sniff_sockets.update({_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg): iflabel}) | ||
+ except OSError: | ||
+ pass | ||
else: | ||
iface = iface or conf.iface | ||
sniff_sockets[_RL2(iface)(type=ETH_P_ALL, iface=iface, | ||
@@ -1221,7 +1223,11 @@ class AsyncSniffer(object): | ||
self.running = False | ||
if opened_socket is None: | ||
for s in sniff_sockets: | ||
- s.close() | ||
+ try: | ||
+ s.close() | ||
+ except Exception: | ||
+ # Ignore exceptions to ensure all sockets are closed | ||
+ pass | ||
elif close_pipe: | ||
close_pipe.close() | ||
self.results = session.toPacketList() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
0001-Fix-version-string-generation-when-scapy-is-a-submod.patch | ||
0002-Check-if-the-network-interface-still-exists.patch | ||
0003-Do-not-resolve-the-interface-name-globally.patch | ||
0004-Fix-fd-leak-in-worker-thread.patch |