[gnome-software/1128-possible-thread-race-condition] GsApp: Fix possible thread race condition around 'launchable' property



commit d0eb5be26a6d68abefce08c698801ef653c0b961
Author: Milan Crha <mcrha redhat com>
Date:   Fri Mar 26 11:06:20 2021 +0100

    GsApp: Fix possible thread race condition around 'launchable' property
    
    The 'launchable' property can change due to change notifications
    after install/uninstall of the application, which can cause use-after-free
    in the functions, which read the property.
    
    Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1128

 lib/gs-app.c          | 28 +++++++++++++++++++++++++++-
 lib/gs-app.h          |  3 +++
 lib/gs-plugin.c       |  6 +++---
 src/gs-details-page.c |  6 +++---
 4 files changed, 36 insertions(+), 7 deletions(-)
---
diff --git a/lib/gs-app.c b/lib/gs-app.c
index 12ee9a292..4f9f773a3 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -2547,11 +2547,14 @@ gs_app_set_url_missing (GsApp *app, const gchar *url)
  * @app: a #GsApp
  * @kind: a #AsLaunchableKind, e.g. %AS_LAUNCHABLE_KIND_DESKTOP_ID
  *
- * Gets a launchable of a specific type.
+ * Gets a launchable of a specific type. Note, this function is not thread safe,
+ * use gs_app_dup_launchable() instead.
  *
  * Returns: a string, or %NULL for unset
  *
  * Since: 40
+ *
+ * Deprecated: 41: Use gs_app_dup_launchable() instead.
  **/
 const gchar *
 gs_app_get_launchable (GsApp *app, AsLaunchableKind kind)
@@ -2562,6 +2565,29 @@ gs_app_get_launchable (GsApp *app, AsLaunchableKind kind)
                                    as_launchable_kind_to_string (kind));
 }
 
+/**
+ * gs_app_dup_launchable:
+ * @app: a #GsApp
+ * @kind: a #AsLaunchableKind, e.g. %AS_LAUNCHABLE_KIND_DESKTOP_ID
+ *
+ * Gets a launchable of a specific type as a newly allocated string.
+ * Free it with g_free(), when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a newly allocated string, or %NULL when unset
+ *
+ * Since: 41
+ **/
+gchar *
+gs_app_dup_launchable (GsApp *app, AsLaunchableKind kind)
+{
+       GsAppPrivate *priv = gs_app_get_instance_private (app);
+       g_autoptr(GMutexLocker) locker = NULL;
+       g_return_val_if_fail (GS_IS_APP (app), NULL);
+       locker = g_mutex_locker_new (&priv->mutex);
+       return g_strdup (g_hash_table_lookup (priv->launchables,
+                                             as_launchable_kind_to_string (kind)));
+}
+
 /**
  * gs_app_set_launchable:
  * @app: a #GsApp
diff --git a/lib/gs-app.h b/lib/gs-app.h
index 3136b639f..fe59134a0 100644
--- a/lib/gs-app.h
+++ b/lib/gs-app.h
@@ -312,8 +312,11 @@ void                gs_app_set_url                 (GsApp          *app,
 const gchar    *gs_app_get_url_missing         (GsApp          *app);
 void            gs_app_set_url_missing         (GsApp          *app,
                                                 const gchar    *url);
+G_DEPRECATED_FOR(gs_app_dup_launchable)
 const gchar    *gs_app_get_launchable          (GsApp          *app,
                                                 AsLaunchableKind kind);
+gchar          *gs_app_dup_launchable          (GsApp *app,
+                                                AsLaunchableKind kind);
 void            gs_app_set_launchable          (GsApp          *app,
                                                 AsLaunchableKind kind,
                                                 const gchar    *launchable);
diff --git a/lib/gs-plugin.c b/lib/gs-plugin.c
index b9a609150..0a387fac8 100644
--- a/lib/gs-plugin.c
+++ b/lib/gs-plugin.c
@@ -944,12 +944,12 @@ gs_plugin_app_launch_cb (gpointer user_data)
 gboolean
 gs_plugin_app_launch (GsPlugin *plugin, GsApp *app, GError **error)
 {
-       const gchar *desktop_id;
+       g_autofree gchar *desktop_id = NULL;
        g_autoptr(GAppInfo) appinfo = NULL;
 
-       desktop_id = gs_app_get_launchable (app, AS_LAUNCHABLE_KIND_DESKTOP_ID);
+       desktop_id = gs_app_dup_launchable (app, AS_LAUNCHABLE_KIND_DESKTOP_ID);
        if (desktop_id == NULL)
-               desktop_id = gs_app_get_id (app);
+               desktop_id = g_strdup (gs_app_get_id (app));
        if (desktop_id == NULL) {
                g_set_error (error,
                             GS_PLUGIN_ERROR,
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 8723987b7..f0d6e3144 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -872,8 +872,8 @@ gs_details_page_get_alternates_cb (GObject *source_object,
 static gboolean
 gs_details_page_can_launch_app (GsDetailsPage *self)
 {
-       const gchar *desktop_id;
        GDesktopAppInfo *desktop_appinfo;
+       g_autofree gchar *desktop_id = NULL;
        g_autoptr(GAppInfo) appinfo = NULL;
 
        if (!self->app)
@@ -892,9 +892,9 @@ gs_details_page_can_launch_app (GsDetailsPage *self)
            gs_app_has_quirk (self->app, GS_APP_QUIRK_PARENTAL_NOT_LAUNCHABLE))
                return FALSE;
 
-       desktop_id = gs_app_get_launchable (self->app, AS_LAUNCHABLE_KIND_DESKTOP_ID);
+       desktop_id = gs_app_dup_launchable (self->app, AS_LAUNCHABLE_KIND_DESKTOP_ID);
        if (!desktop_id)
-               desktop_id = gs_app_get_id (self->app);
+               desktop_id = g_strdup (gs_app_get_id (self->app));
        if (!desktop_id)
                return FALSE;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]