mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Fix memory leak in dhcp integration (#45378)
* Fix memory leak in dhcp integration Passing the L2socket to AsyncSniffer caused a memory leak on some systems. To ensure we can create a socket, we do a test creation before starting AsyncSniffer since the sniffer will create it in another thread and we cannot see any permission error otherwise. * Update tests * space * do not store packets
This commit is contained in:
parent
2925474a5d
commit
e8cda598ac
@ -8,7 +8,6 @@ import os
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
from scapy.config import conf
|
from scapy.config import conf
|
||||||
from scapy.data import ETH_P_ALL
|
|
||||||
from scapy.error import Scapy_Exception
|
from scapy.error import Scapy_Exception
|
||||||
from scapy.layers.dhcp import DHCP
|
from scapy.layers.dhcp import DHCP
|
||||||
from scapy.layers.l2 import Ether
|
from scapy.layers.l2 import Ether
|
||||||
@ -208,14 +207,7 @@ class DHCPWatcher(WatcherBase):
|
|||||||
async def async_start(self):
|
async def async_start(self):
|
||||||
"""Start watching for dhcp packets."""
|
"""Start watching for dhcp packets."""
|
||||||
try:
|
try:
|
||||||
sniff_socket = conf.L2socket(type=ETH_P_ALL)
|
_verify_l2socket_creation_permission()
|
||||||
self._sniffer = AsyncSniffer(
|
|
||||||
filter=FILTER,
|
|
||||||
opened_socket=[sniff_socket],
|
|
||||||
started_callback=self._started.set,
|
|
||||||
prn=self.handle_dhcp_packet,
|
|
||||||
)
|
|
||||||
self._sniffer.start()
|
|
||||||
except (Scapy_Exception, OSError) as ex:
|
except (Scapy_Exception, OSError) as ex:
|
||||||
if os.geteuid() == 0:
|
if os.geteuid() == 0:
|
||||||
_LOGGER.error("Cannot watch for dhcp packets: %s", ex)
|
_LOGGER.error("Cannot watch for dhcp packets: %s", ex)
|
||||||
@ -225,6 +217,14 @@ class DHCPWatcher(WatcherBase):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self._sniffer = AsyncSniffer(
|
||||||
|
filter=FILTER,
|
||||||
|
started_callback=self._started.set,
|
||||||
|
prn=self.handle_dhcp_packet,
|
||||||
|
store=0,
|
||||||
|
)
|
||||||
|
self._sniffer.start()
|
||||||
|
|
||||||
def handle_dhcp_packet(self, packet):
|
def handle_dhcp_packet(self, packet):
|
||||||
"""Process a dhcp packet."""
|
"""Process a dhcp packet."""
|
||||||
if DHCP not in packet:
|
if DHCP not in packet:
|
||||||
@ -271,3 +271,15 @@ def _decode_dhcp_option(dhcp_options, key):
|
|||||||
def _format_mac(mac_address):
|
def _format_mac(mac_address):
|
||||||
"""Format a mac address for matching."""
|
"""Format a mac address for matching."""
|
||||||
return format_mac(mac_address).replace(":", "")
|
return format_mac(mac_address).replace(":", "")
|
||||||
|
|
||||||
|
|
||||||
|
def _verify_l2socket_creation_permission():
|
||||||
|
"""Create a socket using the scapy configured l2socket.
|
||||||
|
|
||||||
|
Try to create the socket
|
||||||
|
to see if we have permissions
|
||||||
|
since AsyncSniffer will do it another
|
||||||
|
thread so we will not be able to capture
|
||||||
|
any permission or bind errors.
|
||||||
|
"""
|
||||||
|
conf.L2socket()
|
||||||
|
@ -303,7 +303,8 @@ async def test_setup_fails_as_root(hass, caplog):
|
|||||||
wait_event = threading.Event()
|
wait_event = threading.Event()
|
||||||
|
|
||||||
with patch("os.geteuid", return_value=0), patch(
|
with patch("os.geteuid", return_value=0), patch(
|
||||||
"homeassistant.components.dhcp.AsyncSniffer.start", side_effect=Scapy_Exception
|
"homeassistant.components.dhcp._verify_l2socket_creation_permission",
|
||||||
|
side_effect=Scapy_Exception,
|
||||||
):
|
):
|
||||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@ -327,7 +328,8 @@ async def test_setup_fails_non_root(hass, caplog):
|
|||||||
wait_event = threading.Event()
|
wait_event = threading.Event()
|
||||||
|
|
||||||
with patch("os.geteuid", return_value=10), patch(
|
with patch("os.geteuid", return_value=10), patch(
|
||||||
"homeassistant.components.dhcp.AsyncSniffer.start", side_effect=Scapy_Exception
|
"homeassistant.components.dhcp._verify_l2socket_creation_permission",
|
||||||
|
side_effect=Scapy_Exception,
|
||||||
):
|
):
|
||||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user