From b04d5e78f32737b7a087e2b38ffafef25e175413 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 14 Jan 2025 14:13:01 +0100 Subject: [PATCH] Add tun to static device list in hardware manager Some devices are provided by kernel modules which potentially get loaded later at startup. Those are not listed by udev, and hence add-ons do not get permissions for these types of devices as long as the kernel module is not loaded. Typically, such devices are created by the kmod-static-nodes.service systemd service. Ideally, we would read the output of that service and add those specifically. However, there are very few devices which use static nodes, and we actually only really interested in tun. So let's simply add this static node in case udev does not list it already. --- supervisor/hardware/manager.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/supervisor/hardware/manager.py b/supervisor/hardware/manager.py index d169577cef2..998344b89e0 100644 --- a/supervisor/hardware/manager.py +++ b/supervisor/hardware/manager.py @@ -16,6 +16,33 @@ _LOGGER: logging.Logger = logging.getLogger(__name__) +# Some device nodes get created system on startup by kmod-static-nodes.service, +# which in turn uses /usr/bin/kmod to get a list of static device nodes which +# are provided by kernel modules. These type of devices are not listed by udev +# and hence not listed through pyudev. However, on first access the kernel +# module is loaded automatically. +# Which nodes are exposed by module is system specific, so ideally Supervisor +# should read the output of kmod (e.g. /run/tmpfiles.d/static-nodes.conf). But +# this seems a bit overkill, since we are currently only interested in tun. +_STATIC_NODES: list[Device] = [ + Device( + "tun", + Path("/dev/net/tun"), + Path("/sys/devices/virtual/misc/tun"), + "misc", + None, + [], + { + "DEVNAME": "/dev/net/tun", + "DEVPATH": "/devices/virtual/misc/tun", + "MAJOR": "10", + "MINOR": "200", + "SUBSYSTEM": "misc", + }, + [], + ) +] + class HardwareManager(CoreSysAttributes): """Hardware manager for supervisor.""" @@ -114,6 +141,11 @@ def _import_devices(self) -> None: continue self._devices[device.sys_name] = Device.import_udev(device) + # Add static nodes if not found through udev (e.g. module not yet loaded) + for device in _STATIC_NODES: + if device.name not in self._devices: + self._devices[device.name] = device + async def load(self) -> None: """Load hardware backend.""" self._import_devices()