From 1f53e73bf3869c17c729993a67ab0df0851ef62c Mon Sep 17 00:00:00 2001 From: Phaedrus Leeds Date: Thu, 19 Nov 2020 22:19:50 -0800 Subject: [PATCH] dir: Fix spurious permission denied errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently this error is happening on the eos3.9 dev branch of Endless OS: Nov 19 12:05:55 endless eos-updater-flatpak-installer[464]: eos-updater-flatpak-installer: Couldn’t apply some flatpak update actions for this boot: Error opening directory '/root/.local/share/flatpak/app': Permission denied The reason is that we have a check in flatpak_dir_list_unused_refs() to check if the per-user installation exists and only try to list the refs there if so, but the existence check falsely succeeds due to the systemd sandboxing on eos-updater-flatpak-installer.service, and flatpak_dir_list_refs() then fails in find_used_refs(). Specifically the ProtectHome=yes systemd service option makes /root inaccessible, and due to a bug in GLib[1] this makes g_file_query_exists() falsely return TRUE for any paths under /root. So, check for not found and permission denied errors rather than doing an existence check, as we should be doing anyway to avoid a time-of-check/time-of-use race, as explained in the g_file_query_exists() documentation. [1] https://gitlab.gnome.org/GNOME/glib/-/issues/1237 --- common/flatpak-dir.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index bb2395ee..41f0428a 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -15846,14 +15846,21 @@ flatpak_dir_list_unused_refs (FlatpakDir *self, */ if (!flatpak_dir_is_user (self)) { - g_autoptr(GFile) user_base_dir = flatpak_get_user_base_dir_location (); - if (g_file_query_exists (user_base_dir, cancellable)) - { - g_autoptr(FlatpakDir) user_dir = flatpak_dir_get_user (); + g_autoptr(FlatpakDir) user_dir = flatpak_dir_get_user (); + g_autoptr(GError) local_error = NULL; - if (!find_used_refs (self, user_dir, arch, metadata_injection, excluded_refs_ht, - used_refs, cancellable, error)) - return NULL; + if (!find_used_refs (self, user_dir, arch, metadata_injection, excluded_refs_ht, + used_refs, cancellable, &local_error)) + { + /* We may get permission denied if the process is sandboxed with + * systemd's ProtectHome= + */ + if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && + !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return NULL; + } } }