diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2021-05-25 15:42:11 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-06-03 13:00:10 +0200 |
commit | 977452e155163983e4638c39a82dfad9d847904b (patch) | |
tree | 1cf6d24efe7c73f4575325fe2d1f9e041432aaec | |
parent | 812463c9a82c3e921a392bf06789194ccad42cc5 (diff) | |
download | ModemManager-977452e155163983e4638c39a82dfad9d847904b.tar.gz |
base-manager: ensure all GUdevDevices have subsystem and name set
Under certain rare conditions (e.g. race between querying devices of a
given subsystem and the kernel tearing those devices down), the
subsystem reported for a GUdevDevice seems to be NULL.
So, ensure both subsystem and name are set on the GUdevDevice before we
process them.
The issue has been observed on GUdevDevices listed by
g_udev_client_query_by_subsystem(), not on the ones asynchronously
reported via uevents, but we add the validity check on both places for
consistency.
Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/343
(cherry picked from commit 940063419a1c2eb9f6e197d60b4c7cb42702de8d)
-rw-r--r-- | src/mm-base-manager.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c index 130e5ad13..851c1d6ee 100644 --- a/src/mm-base-manager.c +++ b/src/mm-base-manager.c @@ -433,6 +433,17 @@ handle_uevent (MMBaseManager *self, const gchar *action, GUdevDevice *device) { + const gchar *subsystem; + const gchar *name; + + subsystem = g_udev_device_get_subsystem (device); + name = g_udev_device_get_name (device); + + /* Valid udev devices must have subsystem and name set; if they don't have + * both things, we silently ignore them. */ + if (!subsystem || !name) + return; + if (g_str_equal (action, "add") || g_str_equal (action, "move") || g_str_equal (action, "change")) { g_autoptr(MMKernelDevice) kernel_device = NULL; @@ -442,7 +453,7 @@ handle_uevent (MMBaseManager *self, } if (g_str_equal (action, "remove")) { - device_removed (self, g_udev_device_get_subsystem (device), g_udev_device_get_name (device)); + device_removed (self, subsystem, name); return; } } @@ -456,11 +467,20 @@ typedef struct { static gboolean start_device_added_idle (StartDeviceAdded *ctx) { - MMKernelDevice *kernel_device; + const gchar *subsystem; + const gchar *name; + + subsystem = g_udev_device_get_subsystem (ctx->device); + name = g_udev_device_get_name (ctx->device); - kernel_device = mm_kernel_device_udev_new (ctx->device); - device_added (ctx->self, kernel_device, FALSE, ctx->manual_scan); - g_object_unref (kernel_device); + /* Valid udev devices must have subsystem and name set; if they don't have + * both things, we silently ignore them. */ + if (subsystem && name) { + g_autoptr(MMKernelDevice) kernel_device = NULL; + + kernel_device = mm_kernel_device_udev_new (ctx->device); + device_added (ctx->self, kernel_device, FALSE, ctx->manual_scan); + } g_object_unref (ctx->self); g_object_unref (ctx->device); |