diff options
author | Maciej S. Szmigiero <mail@maciej.szmigiero.name> | 2022-10-05 22:19:04 +0200 |
---|---|---|
committer | Maciej S. Szmigiero <mail@maciej.szmigiero.name> | 2022-10-06 00:10:45 +0200 |
commit | 3610c139deeffa8db5144f08430d5b33151cd0a9 (patch) | |
tree | c7d83725a3efff11e6920555819cc14d5e26faf0 | |
parent | 80fe4e92d7df9819f49004a9780e4b895ceba0ce (diff) |
wifi: Cancellation fixes
Make sure we pass an appropriate GCancellable to various async calls in
gclue-wifi and handle the resulting cancellation gracefully to avoid
hitting UAFs when stopping the source.
-rw-r--r-- | src/gclue-web-source.c | 3 | ||||
-rw-r--r-- | src/gclue-wifi.c | 73 |
2 files changed, 54 insertions, 22 deletions
diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c index 8331227..4db92d5 100644 --- a/src/gclue-web-source.c +++ b/src/gclue-web-source.c @@ -187,7 +187,8 @@ query_callback (GObject *source_object, location = GCLUE_WEB_SOURCE_GET_CLASS (web)->refresh_finish (web, result, &local_error); if (local_error != NULL && - !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED)) { + !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED) && + !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_warning ("Failed to query location: %s", local_error->message); return; } diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c index f872716..0afaf1a 100644 --- a/src/gclue-wifi.c +++ b/src/gclue-wifi.c @@ -135,6 +135,7 @@ static void location_cache_value_free (gpointer data) } struct _GClueWifiPrivate { + GCancellable *intf_cancellable, *bss_cancellable; GClueMozilla *mozilla; WPASupplicant *supplicant; WPAInterface *interface; @@ -197,6 +198,8 @@ gclue_wifi_finalize (GObject *gwifi) G_OBJECT_CLASS (gclue_wifi_parent_class)->finalize (gwifi); + g_cancellable_cancel (wifi->priv->intf_cancellable); + disconnect_bss_signals (wifi); disconnect_cache_prune_timeout (wifi); @@ -206,6 +209,7 @@ gclue_wifi_finalize (GObject *gwifi) g_clear_pointer (&wifi->priv->ignored_bss_proxies, g_hash_table_unref); g_clear_pointer (&wifi->priv->location_cache, g_hash_table_unref); g_clear_object (&wifi->priv->mozilla); + g_clear_object (&wifi->priv->intf_cancellable); } static void @@ -346,13 +350,19 @@ on_bss_proxy_ready (GObject *source_object, { GClueWifi *wifi = GCLUE_WIFI (user_data); WPABSS *bss; - GError *error = NULL; + g_autoptr(GError) error = NULL; char ssid[MAX_SSID_LEN + 1] = { 0 }; bss = wpa_bss_proxy_new_for_bus_finish (res, &error); if (bss == NULL) { - g_debug ("%s", error->message); - g_error_free (error); + if (error) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + return; + } + + g_warning ("BSS proxy setup failed: %s", + error->message); + } return; } @@ -364,7 +374,7 @@ on_bss_proxy_ready (GObject *source_object, } get_ssid_from_bss (bss, ssid); - g_debug ("WiFi AP '%s' added.", ssid); + g_debug ("Got WiFi AP '%s'", ssid); if (wpa_bss_get_signal (bss) <= WIFI_SCAN_BSS_NOISE_LEVEL) { const char *path; @@ -395,13 +405,15 @@ on_bss_added (WPAInterface *object, GVariant *properties, gpointer user_data) { + GClueWifi *wifi = GCLUE_WIFI (user_data); + wpa_bss_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, "fi.w1.wpa_supplicant1", path, - NULL, + wifi->priv->bss_cancellable, on_bss_proxy_ready, - user_data); + wifi); } static gboolean @@ -458,7 +470,7 @@ start_wifi_scan (GClueWifi *wifi) wpa_interface_call_scan (WPA_INTERFACE (priv->interface), args, - NULL, + priv->bss_cancellable, on_scan_call_done, wifi); } @@ -591,19 +603,22 @@ on_scan_call_done (GObject *source_object, gpointer user_data) { GClueWifi *wifi = GCLUE_WIFI (user_data); - GError *error = NULL; + g_autoptr(GError) error = NULL; if (!wpa_interface_call_scan_finish (WPA_INTERFACE (source_object), res, &error)) { - g_warning ("Scanning of WiFi networks failed: %s", - error->message); - g_error_free (error); + if (error) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + return; + } - cancel_wifi_scan (wifi); + g_warning ("Scanning of WiFi networks failed: %s", + error->message); + } - return; + cancel_wifi_scan (wifi); } } @@ -622,6 +637,9 @@ connect_bss_signals (GClueWifi *wifi) return; } + g_assert (!priv->bss_cancellable); + priv->bss_cancellable = g_cancellable_new (); + start_wifi_scan (wifi); priv->bss_list_changed = TRUE; @@ -650,6 +668,12 @@ disconnect_bss_signals (GClueWifi *wifi) { GClueWifiPrivate *priv = wifi->priv; + if (priv->bss_cancellable) { + g_debug ("Cancelling WiFi requests"); + g_cancellable_cancel (priv->bss_cancellable); + g_clear_object (&priv->bss_cancellable); + } + cancel_wifi_scan (wifi); if (priv->bss_added_id != 0) { @@ -867,12 +891,18 @@ on_interface_proxy_ready (GObject *source_object, { GClueWifi *wifi = GCLUE_WIFI (user_data); WPAInterface *interface; - GError *error = NULL; + g_autoptr(GError) error = NULL; interface = wpa_interface_proxy_new_for_bus_finish (res, &error); if (interface == NULL) { - g_debug ("%s", error->message); - g_error_free (error); + if (error) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + return; + } + + g_warning ("Interface proxy add failed: %s", + error->message); + } return; } @@ -907,7 +937,7 @@ on_interface_added (WPASupplicant *supplicant, G_DBUS_PROXY_FLAGS_NONE, "fi.w1.wpa_supplicant1", path, - NULL, + wifi->priv->intf_cancellable, on_interface_proxy_ready, wifi); } @@ -947,6 +977,7 @@ gclue_wifi_init (GClueWifi *wifi) { wifi->priv = gclue_wifi_get_instance_private (wifi); + wifi->priv->intf_cancellable = g_cancellable_new (); wifi->priv->mozilla = gclue_mozilla_get_singleton (); wifi->priv->bss_proxies = g_hash_table_new_full (g_str_hash, g_str_equal, @@ -968,7 +999,7 @@ gclue_wifi_constructed (GObject *object) GClueWifi *wifi = GCLUE_WIFI (object); GClueWifiPrivate *priv = wifi->priv; const gchar *const *interfaces; - GError *error = NULL; + g_autoptr(GError) error = NULL; G_OBJECT_CLASS (gclue_wifi_parent_class)->constructed (object); @@ -988,9 +1019,9 @@ gclue_wifi_constructed (GObject *object) NULL, &error); if (priv->supplicant == NULL) { - g_warning ("Failed to connect to wpa_supplicant service: %s", - error->message); - g_error_free (error); + if (error) + g_warning ("Failed to connect to wpa_supplicant service: %s", + error->message); goto refresh_n_exit; } |