From 88ad0c5381ea17550a6c012ca4e33fb173459f0b Mon Sep 17 00:00:00 2001 From: gpotter2 <10530980+gpotter2@users.noreply.github.com> Date: Sun, 2 Nov 2025 23:16:18 +0100 Subject: [PATCH] BPF filter: fix memory leak --- scapy/arch/bpf/core.py | 4 +++- scapy/arch/common.py | 8 ++++++++ scapy/arch/linux/__init__.py | 9 +++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/scapy/arch/bpf/core.py b/scapy/arch/bpf/core.py index db03a03c3a9..b2424fe38f6 100644 --- a/scapy/arch/bpf/core.py +++ b/scapy/arch/bpf/core.py @@ -14,7 +14,7 @@ import struct from scapy.arch.bpf.consts import BIOCSETF, BIOCSETIF -from scapy.arch.common import compile_filter +from scapy.arch.common import compile_filter, free_filter from scapy.config import conf from scapy.consts import LINUX from scapy.error import Scapy_Exception @@ -76,6 +76,8 @@ def attach_filter(fd, bpf_filter, iface): ret = fcntl.ioctl(fd, BIOCSETF, bp) if ret < 0: raise Scapy_Exception("Can't attach the BPF filter !") + # Free + free_filter(bp) def in6_getifaddr(): diff --git a/scapy/arch/common.py b/scapy/arch/common.py index 8077c3dd286..697b759db1e 100644 --- a/scapy/arch/common.py +++ b/scapy/arch/common.py @@ -132,6 +132,14 @@ def compile_filter(filter_exp, # type: str return bpf +def free_filter(bp: bpf_program) -> None: + """ + Free a bpf_program created with compile_filter + """ + from scapy.libs.winpcapy import pcap_freecode + pcap_freecode(ctypes.byref(bp)) + + ####### # DNS # ####### diff --git a/scapy/arch/linux/__init__.py b/scapy/arch/linux/__init__.py index f4e380487ba..29ad12cddc9 100644 --- a/scapy/arch/linux/__init__.py +++ b/scapy/arch/linux/__init__.py @@ -21,7 +21,7 @@ from scapy.compat import raw from scapy.consts import LINUX -from scapy.arch.common import compile_filter +from scapy.arch.common import compile_filter, free_filter from scapy.config import conf from scapy.data import MTU, ETH_P_ALL, SOL_PACKET, SO_ATTACH_FILTER, \ SO_TIMESTAMPNS @@ -130,13 +130,14 @@ def attach_filter(sock, bpf_filter, iface): if conf.use_pypy and sys.pypy_version_info <= (7, 3, 2): # type: ignore # PyPy < 7.3.2 has a broken behavior # https://foss.heptapod.net/pypy/pypy/-/issues/3298 - bp = struct.pack( # type: ignore + fp = struct.pack( 'HL', bp.bf_len, ctypes.addressof(bp.bf_insns.contents) ) else: - bp = sock_fprog(bp.bf_len, bp.bf_insns) # type: ignore - sock.setsockopt(socket.SOL_SOCKET, SO_ATTACH_FILTER, bp) + fp = sock_fprog(bp.bf_len, bp.bf_insns) # type: ignore + sock.setsockopt(socket.SOL_SOCKET, SO_ATTACH_FILTER, fp) + free_filter(bp) def set_promisc(s, iff, val=1):