From a27ec46e8c0ab0ae162f2aa3142dccb6b79d9211 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 7 Feb 2026 21:57:30 +0100 Subject: [PATCH] system-helper: Only remove an ongoing pull if users match The code would always remove a pull from the hashtable, and then check if the users match and abort if they don't. Either way, the pull gets dropped. Fix this by only removing the pull if the dir and the user match. --- system-helper/flatpak-system-helper.c | 87 ++++++++++++--------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c index 778b3c59..f709f948 100644 --- a/system-helper/flatpak-system-helper.c +++ b/system-helper/flatpak-system-helper.c @@ -358,23 +358,31 @@ get_connection_uid (GDBusMethodInvocation *invocation, uid_t *out_uid, GError ** } static OngoingPull * -take_ongoing_pull_by_dir (const gchar *src_dir) +take_ongoing_pull_by_dir (const char *src_dir, + uid_t uid) { OngoingPull *pull = NULL; - gpointer key, value; + char *cache_dir_name = NULL; G_LOCK (cache_dirs_in_use); - /* Keep src_dir key inside hashtable but remove its OngoingPull - * value and set it to NULL. This way src_dir is still marked - * as in-use (as Deploy or CancelPull might be executing on it, - * whereas OngoingPull ownership is transferred to respective - * callers. */ - if (g_hash_table_steal_extended (cache_dirs_in_use, src_dir, &key, &value)) + if (g_hash_table_steal_extended (cache_dirs_in_use, src_dir, + (gpointer) &cache_dir_name, + (gpointer) &pull)) { - if (value) + if (pull && pull->uid == uid) { - g_hash_table_insert (cache_dirs_in_use, key, NULL); - pull = value; + /* Keep src_dir key inside hashtable but remove its OngoingPull + * value and set it to NULL. This way src_dir is still marked + * as in-use (as Deploy or CancelPull might be executing on it, + * whereas OngoingPull ownership is transferred to respective + * callers. */ + g_hash_table_insert (cache_dirs_in_use, cache_dir_name, NULL); + } + else + { + /* Otherwise, re-insert what is currently there and return NULL */ + g_hash_table_insert (cache_dirs_in_use, cache_dir_name, pull); + pull = NULL; } } G_UNLOCK (cache_dirs_in_use); @@ -426,6 +434,9 @@ handle_deploy (FlatpakSystemHelper *object, if (strlen (arg_repo_path) > 0) { + g_autoptr(GError) local_error = NULL; + uid_t uid; + if (!g_file_query_exists (repo_file, NULL)) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, @@ -433,30 +444,17 @@ handle_deploy (FlatpakSystemHelper *object, return G_DBUS_METHOD_INVOCATION_HANDLED; } + /* Ensure that pull's uid is same as the caller's uid */ + if (!get_connection_uid (invocation, &uid, &local_error)) + { + g_dbus_method_invocation_return_gerror (invocation, local_error); + return G_DBUS_METHOD_INVOCATION_HANDLED; + } + src_dir = g_path_get_dirname (arg_repo_path); - ongoing_pull = take_ongoing_pull_by_dir (src_dir); + ongoing_pull = take_ongoing_pull_by_dir (src_dir, uid); if (ongoing_pull != NULL) { - g_autoptr(GError) local_error = NULL; - uid_t uid; - - /* Ensure that pull's uid is same as the caller's uid */ - if (!get_connection_uid (invocation, &uid, &local_error)) - { - g_dbus_method_invocation_return_gerror (invocation, local_error); - return G_DBUS_METHOD_INVOCATION_HANDLED; - } - else - { - if (ongoing_pull->uid != uid) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "Ongoing pull's uid(%d) does not match with peer uid(%d)", - ongoing_pull->uid, uid); - return G_DBUS_METHOD_INVOCATION_HANDLED; - } - } - terminate_revokefs_backend (ongoing_pull); if (!flatpak_canonicalize_permissions (AT_FDCWD, @@ -738,7 +736,13 @@ handle_cancel_pull (FlatpakSystemHelper *object, return G_DBUS_METHOD_INVOCATION_HANDLED; } - ongoing_pull = take_ongoing_pull_by_dir (arg_src_dir); + if (!get_connection_uid (invocation, &uid, &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + return G_DBUS_METHOD_INVOCATION_HANDLED; + } + + ongoing_pull = take_ongoing_pull_by_dir (arg_src_dir, uid); if (ongoing_pull == NULL) { g_set_error (&error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, @@ -747,23 +751,6 @@ handle_cancel_pull (FlatpakSystemHelper *object, return G_DBUS_METHOD_INVOCATION_HANDLED; } - /* Ensure that pull's uid is same as the caller's uid */ - if (!get_connection_uid (invocation, &uid, &error)) - { - g_dbus_method_invocation_return_gerror (invocation, error); - return G_DBUS_METHOD_INVOCATION_HANDLED; - } - else - { - if (ongoing_pull->uid != uid) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "Ongoing pull's uid(%d) does not match with peer uid(%d)", - ongoing_pull->uid, uid); - return G_DBUS_METHOD_INVOCATION_HANDLED; - } - } - ongoing_pull->preserve_pull = (arg_flags & FLATPAK_HELPER_CANCEL_PULL_FLAGS_PRESERVE_PULL) != 0; ongoing_pull_free (ongoing_pull);