From c97905c8188ddaad01ee146b57bba6c3fa294113 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Fri, 9 Jan 2026 19:24:44 +0100 Subject: [PATCH] utils: Only remove cached files in the cache directory The function flatpak_switch_symlink_and_remove is used to implement a cache for ld.so (regenerate_ld_cache). If the active symlink changes to a new cache file, the old cache file is supposed to get removed. The symlink still points to the old cache file, so we would remove the file that it points to and then point at the new file. Because the symlink is under the app's control, the symlink can point anywhere, and the removal happens in the host context, which allows an app to remove arbitrary files on the host. The filename of the cache files are checksums, which means that we can ensure that the link is a file in the same directory of the link by checking that it only contains the chars a-zA-Z0-9. (cherry picked from commit FIXME) --- common/flatpak-utils.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c index 7a30969c..dbc46951 100644 --- a/common/flatpak-utils.c +++ b/common/flatpak-utils.c @@ -922,6 +922,22 @@ out: return ret; } +static gboolean +flatpak_str_is_alphanumeric (const char *arg) +{ + while (*arg != '\0') + { + char c = *arg; + + if (!g_ascii_isalnum (c)) + return FALSE; + + arg++; + } + + return TRUE; +} + /* This atomically replaces a symlink with a new value, removing the * existing symlink target, if it exstis and is different from * @target. This is atomic in the sense that we're guaranteed to @@ -931,6 +947,9 @@ out: * symlink for some reason, ending up with neither the old or the new * target. That is fine if the reason for the symlink is keeping a * cache though. + * The target shall only be a file in the same directory as the symlink, and + * shall only contain the characters a-zA-Z0-9. This is so that the target of + * the symlink that gets removed is in the same directory as the link. */ gboolean flatpak_switch_symlink_and_remove (const char *symlink_path, @@ -974,10 +993,21 @@ flatpak_switch_symlink_and_remove (const char *symlink_path, g_autofree char *old_target = flatpak_readlink (tmp_path, error); if (old_target == NULL) return FALSE; - if (strcmp (old_target, target) != 0) /* Don't remove old file if its the same as the new one */ + + /* Don't remove old file if its the same as the new one */ + if (strcmp (old_target, target) != 0) { - g_autofree char *old_target_path = g_build_filename (symlink_dir, old_target, NULL); - unlink (old_target_path); + if (flatpak_str_is_alphanumeric (old_target)) + { + g_autofree char *old_target_path = NULL; + + old_target_path = g_build_filename (symlink_dir, old_target, NULL); + unlink (old_target_path); + } + else + { + g_warning ("Refusing to delete old link target %s", old_target); + } } } else if (errno != ENOENT)