summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2021-05-25 15:42:11 +0200
committerAleksander Morgado <aleksander@aleksander.es>2021-06-03 13:00:10 +0200
commit977452e155163983e4638c39a82dfad9d847904b (patch)
tree1cf6d24efe7c73f4575325fe2d1f9e041432aaec
parent812463c9a82c3e921a392bf06789194ccad42cc5 (diff)
downloadModemManager-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.c30
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);