aboutsummaryrefslogtreecommitdiff
path: root/src/mm-base-manager.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2021-05-25 15:42:11 +0200
committerAleksander Morgado <aleksander@aleksander.es>2021-05-26 12:46:49 +0000
commit940063419a1c2eb9f6e197d60b4c7cb42702de8d (patch)
tree28d668fa2a6ed228ead32020a8e0cc6ecefa553a /src/mm-base-manager.c
parent10651ba93f89ed1320b5a88ae11679230bcac4fc (diff)
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
Diffstat (limited to 'src/mm-base-manager.c')
-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 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;
+
+ subsystem = g_udev_device_get_subsystem (ctx->device);
+ name = g_udev_device_get_name (ctx->device);
- 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);
+ /* 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);