diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2021-05-25 15:42:11 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-05-26 12:46:49 +0000 |
commit | 940063419a1c2eb9f6e197d60b4c7cb42702de8d (patch) | |
tree | 28d668fa2a6ed228ead32020a8e0cc6ecefa553a /src | |
parent | 10651ba93f89ed1320b5a88ae11679230bcac4fc (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')
-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 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); |