m-reserve-device: cancel get proxy callback properly

Cancel the async calls that get the name of the application owning the
service, when WpReserveDevice is finalized or we are going to make
another call.

Fixes UAF accessing self when the async callback runs.
This commit is contained in:
Pauli Virtanen 2024-11-01 20:40:42 +02:00
parent 71f8682337
commit b65b53b200
2 changed files with 19 additions and 1 deletions

View file

@ -53,6 +53,14 @@ on_got_proxy (GObject * src, GAsyncResult * res, WpReserveDevice *self)
g_autoptr (GError) error = NULL; g_autoptr (GError) error = NULL;
g_autoptr (WpOrgFreedesktopReserveDevice1) proxy = g_autoptr (WpOrgFreedesktopReserveDevice1) proxy =
wp_org_freedesktop_reserve_device1_proxy_new_finish (res, &error); wp_org_freedesktop_reserve_device1_proxy_new_finish (res, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
/* Operation canceled: self may be invalid by now. */
return;
}
g_clear_object (&self->get_owner_call);
if (!proxy) { if (!proxy) {
wp_info_object (self, "%s: Could not get proxy of remote reservation: %s", wp_info_object (self, "%s: Could not get proxy of remote reservation: %s",
self->name, error->message); self->name, error->message);
@ -73,15 +81,20 @@ on_got_proxy (GObject * src, GAsyncResult * res, WpReserveDevice *self)
static void static void
update_owner_app_name (WpReserveDevice *self) update_owner_app_name (WpReserveDevice *self)
{ {
g_cancellable_cancel (self->get_owner_call);
g_clear_object (&self->get_owner_call);
if (self->state == WP_RESERVE_DEVICE_STATE_BUSY && !self->owner_app_name) { if (self->state == WP_RESERVE_DEVICE_STATE_BUSY && !self->owner_app_name) {
/* create proxy */ /* create proxy */
g_autoptr (WpReserveDevicePlugin) plugin = g_weak_ref_get (&self->plugin); g_autoptr (WpReserveDevicePlugin) plugin = g_weak_ref_get (&self->plugin);
g_autoptr (GDBusConnection) conn = NULL; g_autoptr (GDBusConnection) conn = NULL;
g_object_get (plugin->dbus, "connection", &conn, NULL); g_object_get (plugin->dbus, "connection", &conn, NULL);
self->get_owner_call = g_cancellable_new ();
wp_org_freedesktop_reserve_device1_proxy_new (conn, wp_org_freedesktop_reserve_device1_proxy_new (conn,
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
self->service_name, self->object_path, NULL, self->service_name, self->object_path, self->get_owner_call,
(GAsyncReadyCallback) on_got_proxy, self); (GAsyncReadyCallback) on_got_proxy, self);
} }
else if (self->state != WP_RESERVE_DEVICE_STATE_BUSY && self->owner_app_name) { else if (self->state != WP_RESERVE_DEVICE_STATE_BUSY && self->owner_app_name) {
@ -152,6 +165,9 @@ wp_reserve_device_finalize (GObject * object)
if (self->owner_id > 0) if (self->owner_id > 0)
g_bus_unown_name (self->owner_id); g_bus_unown_name (self->owner_id);
g_cancellable_cancel (self->get_owner_call);
g_clear_object (&self->get_owner_call);
g_weak_ref_clear (&self->plugin); g_weak_ref_clear (&self->plugin);
g_weak_ref_clear (&self->transition); g_weak_ref_clear (&self->transition);
g_clear_pointer (&self->name, g_free); g_clear_pointer (&self->name, g_free);

View file

@ -42,6 +42,8 @@ struct _WpReserveDevice
WpReserveDeviceState state; WpReserveDeviceState state;
guint watcher_id; guint watcher_id;
guint owner_id; guint owner_id;
GCancellable *get_owner_call;
}; };
void wp_reserve_device_export_object (WpReserveDevice *self); void wp_reserve_device_export_object (WpReserveDevice *self);