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
This commit is contained in:
Aleksander Morgado
2021-05-25 15:42:11 +02:00
parent 10651ba93f
commit 940063419a

View File

@@ -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);