scapy icon indicating copy to clipboard operation
scapy copied to clipboard

Zombie tcpdump Process After Using sniff() on pcap with Filter

Open romanhu opened this issue 1 year ago • 3 comments

Brief description

When using Scapy's sniff() function to read from a pcap file, a zombie tcpdump process is left behind if the filter argument is set to a non-None value. This issue occurs consistently when a BPF filter is applied during packet sniffing, leading to potential resource leakage and system instability due to the accumulation of zombie processes.

Scapy version

2.5

Python version

3.11

Operating system

Linux Debian 6.1.99-1

Additional environment information

No response

How to reproduce

  1. Start scapy interactive console
  2. Call sniff(offline="/path/to/any.pcap", filter="")
  3. In another terminal execute ps x | grep tcpdump

Actual result

The ps command lists the tcpdump process with a <defunct> status, indicating that the process has become a zombie. This status means the process has completed execution but remains in the process table because its parent process has not yet read its exit status.

Expected result

ps should not show any tcpdump processes if sniff is done reading the pcap file

Related resources

No response

romanhu avatar Aug 28 '24 08:08 romanhu

Thanks for this report. You're right. Also, Python reports this (at least Python 3.12):

/usr/lib/python3.12/subprocess.py:1127: ResourceWarning: subprocess 123456 is still running
  _warn("subprocess %s is still running" % self.pid,
ResourceWarning: Enable tracemalloc to get the object allocation traceback

p-l- avatar Aug 28 '24 16:08 p-l-

An option to patch this would be to prevent tcpdump() from being used with getfd=True without using a with pattern.

p-l- avatar Aug 28 '24 17:08 p-l-

@p-l- Here are few of my observations about your suggestion of using with pattern:

  • Calling tcpdump with getfd=True returns us a Popen.stdout.
  • Using with on Popen.stdout closes the stdout pipe when its context ends, but the Popen object still exists for the tcpdump subprocess.

Few ways we can handle this:

  1. Straight out just refrain from using tcpdump() in the sniffer when we have a falsy value of flt instead of just validating flt against None.
  2. Instead of using getfd=True in tcpdump inside the sniffer, we use getproc=True which provides the sniffer with the tcpdump Popen object, which we can then use along with to properly close the tcpdump's Popen object when its context ends.

Please let me know which of these fixes make the most sense to implement and I will create a PR with the fix.

Thanks !

AbhishekPandey1998 avatar Aug 24 '25 09:08 AbhishekPandey1998