From 940063419a1c2eb9f6e197d60b4c7cb42702de8d Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Tue, 25 May 2021 15:42:11 +0200 Subject: [PATCH] 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 --- src/mm-base-manager.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c index 71363af9..24812932 100644 --- a/src/mm-base-manager.c +++ b/src/mm-base-manager.c @@ -473,6 +473,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; @@ -482,7 +493,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; } } @@ -496,11 +507,20 @@ typedef struct { static gboolean start_device_added_idle (StartDeviceAdded *ctx) { - MMKernelDevice *kernel_device; + const gchar *subsystem; + const gchar *name; - kernel_device = mm_kernel_device_udev_new (ctx->self->priv->udev, ctx->device); - device_added (ctx->self, kernel_device, FALSE, ctx->manual_scan); - g_object_unref (kernel_device); + subsystem = g_udev_device_get_subsystem (ctx->device); + name = g_udev_device_get_name (ctx->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->self->priv->udev, ctx->device); + device_added (ctx->self, kernel_device, FALSE, ctx->manual_scan); + } g_object_unref (ctx->self); g_object_unref (ctx->device);