summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2018-05-02 13:53:39 +0200
committerAlexander Larsson <alexl@redhat.com>2018-05-02 13:53:39 +0200
commitb4484aa97eb62948d59cbd8413fc08e08b16dd3e (patch)
tree4354c159a4eeb8772857778af1166edaedfb648e
parent2c22aa17e0aacd1dc1c8cb1b87a8bd5e908b4c56 (diff)
downloadflatpak-b4484aa97eb62948d59cbd8413fc08e08b16dd3e.tar.gz
Re-fix export filename checks, this time also for build-finishre-fix-exports
The fix in 5122766284295c460320153c1213bccc7c8e3609 was not right. First of all it didn't changethe regressing behaviour for build-finish, just install. Secondly, it changed the prefix matches to always use flatpak_name_matches_one_wildcard_prefix() which had slight differences in behaviour that the previously used flatpak_name_matches_one_prefix. For example, it always removed the extension, no matter what it was. This has all been replaced with a shared (between install and build-finish) version that is more strict with extensions, and with what names can be exported as service files (these have to match exactly, with the wildcard and cannot have suffixes). To test this i tried to install these apps from flathub that has some more complex exports: org.sparkleshare.SparkleShare: org.sparkleshare.SparkleShare.Invites.desktop org.sparkleshare.SparkleShare-symbolic.svg org.libreoffice.LibreOffice: org.libreoffice.LibreOffice.desktop org.libreoffice.LibreOffice-impress.desktop org.libreoffice.LibreOffice-writer.png org.libreoffice.LibreOffice-calc.png com.github.bajoja.indicator-kdeconnect: com.github.bajoja.indicator-kdeconnect.desktop com.github.bajoja.indicator-kdeconnect.settings.desktop com.github.bajoja.indicator-kdeconnect.tablettrusted.svg com.github.philip_scott.spice-up: com.github.philip_scott.spice-up.svg com.github.philip_scott.spice-up-mime.svg com.github.philip_scott.spice-up.mime.xml org.gnome.Recipes: org.gnome.Recipes.desktop org.gnome.Recipes.service org.gnome.Recipes-search-provider.ini org.gnome.Recipes.png org.gnome.Recipes-symbolic.symbolic.png org.gnome.Recipes-mime.xml org.gnome.Characters: org.gnome.Characters.desktop org.gnome.Characters.BackgroundService.service org.gnome.Characters.service org.gnome.Characters.search-provider.ini org.gnome.Characters.png org.gnome.Characters-symbolic.svg org.gnome.Weather org.gnome.Weather.Application.desktop org.gnome.Weather.Application.service org.gnome.Weather.BackgroundService.service org.gnome.Weather.Application.search-provider.ini org.gpodder.gpodder: org.gpodder.gpodder.desktop org.gpodder.gpodder.gpodder-url-handler.desktop
-rw-r--r--app/flatpak-builtins-build-finish.c152
-rw-r--r--common/flatpak-dir.c70
-rw-r--r--common/flatpak-utils.c146
-rw-r--r--common/flatpak-utils.h15
4 files changed, 197 insertions, 186 deletions
diff --git a/app/flatpak-builtins-build-finish.c b/app/flatpak-builtins-build-finish.c
index e0b23270..0a93728b 100644
--- a/app/flatpak-builtins-build-finish.c
+++ b/app/flatpak-builtins-build-finish.c
@@ -60,57 +60,15 @@ static GOptionEntry options[] = {
{ NULL }
};
-typedef gboolean (*DirectoryExportFileFilterFunc) (char *path, gpointer user_data);
-
-typedef struct _BuiltinExportedDirectoryInfo {
- char *path;
- DirectoryExportFileFilterFunc filter_func;
- gpointer user_data;
- GDestroyNotify user_data_destroy;
-} BuiltinExportedDirectoryInfo;
-
-static BuiltinExportedDirectoryInfo *
-builtin_exported_directory_info_new (const char *path,
- DirectoryExportFileFilterFunc filter_func,
- gpointer user_data,
- GDestroyNotify user_data_destroy)
-{
- BuiltinExportedDirectoryInfo *info = g_new0 (BuiltinExportedDirectoryInfo, 1);
-
- info->path = g_strdup (path);
- info->filter_func = filter_func;
- info->user_data = user_data;
- info->user_data_destroy = user_data_destroy;
-
- return info;
-}
-
-static BuiltinExportedDirectoryInfo *
-builtin_exported_directory_info_new_simple (const char *path,
- const char *permissible_prefix)
-{
- return builtin_exported_directory_info_new (path,
- (DirectoryExportFileFilterFunc) flatpak_has_name_prefix,
- g_strdup (permissible_prefix),
- g_free);
-}
-
-static void
-builtin_exported_directory_info_free (BuiltinExportedDirectoryInfo *info)
-{
- g_clear_pointer (&info->path, g_free);
-
- if (info->user_data_destroy != NULL)
- g_clear_pointer (&info->user_data, info->user_data_destroy);
-}
-
static gboolean
export_dir (int source_parent_fd,
const char *source_name,
const char *source_relpath,
int destination_parent_fd,
const char *destination_name,
- BuiltinExportedDirectoryInfo *exported_directory_info,
+ char **allowed_prefixes,
+ char **allowed_extensions,
+ gboolean require_exact_match,
GCancellable *cancellable,
GError **error)
{
@@ -173,17 +131,34 @@ export_dir (int source_parent_fd,
g_autofree gchar *child_relpath = g_build_filename (source_relpath, dent->d_name, NULL);
if (!export_dir (source_iter.fd, dent->d_name, child_relpath, destination_dfd, dent->d_name,
- exported_directory_info, cancellable, error))
+ allowed_prefixes, allowed_extensions, require_exact_match,
+ cancellable, error))
return FALSE;
}
else if (S_ISREG (stbuf.st_mode))
{
+ g_autofree gchar *name_without_extension = NULL;
+ int i;
+
source_printable = g_build_filename (source_relpath, dent->d_name, NULL);
- if (!exported_directory_info->filter_func (dent->d_name,
- exported_directory_info->user_data))
+ for (i = 0; allowed_extensions[i] != NULL; i++)
{
- g_print (_("Not exporting %s, wrong prefix\n"), source_printable);
+ if (g_str_has_suffix (dent->d_name, allowed_extensions[i]))
+ break;
+ }
+
+ if (allowed_extensions[i] == NULL)
+ {
+ g_print (_("Not exporting %s, wrong extension\n"), source_printable);
+ continue;
+ }
+
+ name_without_extension = g_strndup (dent->d_name, strlen (dent->d_name) - strlen (allowed_extensions[i]));
+
+ if (!flatpak_name_matches_one_wildcard_prefix (name_without_extension, (const char * const *) allowed_prefixes, require_exact_match))
+ {
+ g_print (_("Not exporting %s, non-allowed export filename\n"), source_printable);
continue;
}
@@ -224,7 +199,9 @@ static gboolean
copy_exports (GFile *source,
GFile *destination,
const char *source_prefix,
- BuiltinExportedDirectoryInfo *exported_directory_info,
+ char **allowed_prefixes,
+ char **allowed_extensions,
+ gboolean require_exact_match,
GCancellable *cancellable,
GError **error)
{
@@ -234,30 +211,13 @@ copy_exports (GFile *source,
/* The fds are closed by this call */
if (!export_dir (AT_FDCWD, flatpak_file_get_path_cached (source), source_prefix,
AT_FDCWD, flatpak_file_get_path_cached (destination),
- exported_directory_info, cancellable, error))
+ allowed_prefixes, allowed_extensions, require_exact_match,
+ cancellable, error))
return FALSE;
return TRUE;
}
-static GStrv
-lookup_permitted_dbus_service_file_prefixes (FlatpakContext *arg_context,
- const char *app_id)
-{
- g_auto(GStrv) dbus_own_name_prefixes =
- flatpak_context_get_session_bus_policy_allowed_own_names (arg_context);
- g_autoptr(GPtrArray) permitted_prefixes = g_ptr_array_new_with_free_func (g_free);
- GStrv iter = dbus_own_name_prefixes;
-
- g_ptr_array_add (permitted_prefixes, g_strdup (app_id));
-
- for (; *iter != NULL; ++iter)
- g_ptr_array_add (permitted_prefixes, g_strdup (*iter));
-
- g_ptr_array_add (permitted_prefixes, NULL);
- return (GStrv) g_ptr_array_free (g_steal_pointer (&permitted_prefixes), FALSE);
-}
-
static gboolean
collect_exports (GFile *base,
const char *app_id,
@@ -267,34 +227,16 @@ collect_exports (GFile *base,
{
g_autoptr(GFile) files = NULL;
g_autoptr(GFile) export = NULL;
- g_autoptr(GPtrArray) exported_directory_infos =
- g_ptr_array_new_with_free_func ((GDestroyNotify) builtin_exported_directory_info_free);
- g_auto(GStrv) permitted_dbus_service_file_prefixes =
- lookup_permitted_dbus_service_file_prefixes (arg_context, app_id);
int i;
+ const char *paths[] = {
+ "share/applications", /* Copy desktop files */
+ "share/mime/packages", /* Copy MIME Type files */
+ "share/icons", /* Icons */
+ "share/dbus-1/services", /* D-Bus service files */
+ "share/gnome-shell/search-providers", /* Search providers */
+ NULL,
+ };
- /* Copy desktop files */
- g_ptr_array_add (exported_directory_infos,
- builtin_exported_directory_info_new_simple ("share/applications", app_id));
-
- /* Copy MIME type files */
- g_ptr_array_add (exported_directory_infos,
- builtin_exported_directory_info_new_simple ("share/mime/packages", app_id));
-
- /* Copy icons */
- g_ptr_array_add (exported_directory_infos,
- builtin_exported_directory_info_new_simple ("share/icons", app_id));
-
- /* Copy D-Bus service files */
- g_ptr_array_add (exported_directory_infos,
- builtin_exported_directory_info_new ("share/dbus-1/services",
- (DirectoryExportFileFilterFunc) flatpak_name_matches_one_wildcard_prefix,
- g_steal_pointer (&permitted_dbus_service_file_prefixes),
- (GDestroyNotify) g_strfreev));
-
- /* Copy Search Providers */
- g_ptr_array_add (exported_directory_infos,
- builtin_exported_directory_info_new_simple ("share/gnome-shell/search-providers", app_id));
files = g_file_get_child (base, "files");
@@ -306,12 +248,18 @@ collect_exports (GFile *base,
if (opt_no_exports)
return TRUE;
- for (i = 0; i < exported_directory_infos->len; i++)
+ for (i = 0; paths[i]; i++)
{
- g_autoptr(GFile) src = NULL;
- BuiltinExportedDirectoryInfo *info = g_ptr_array_index (exported_directory_infos, i);
- const char * path = info->path;
- src = g_file_resolve_relative_path (files, path);
+ const char * path = paths[i];
+ g_autoptr(GFile) src = g_file_resolve_relative_path (files, path);
+ g_auto(GStrv) allowed_prefixes = NULL;
+ g_auto(GStrv) allowed_extensions = NULL;
+ gboolean require_exact_match = FALSE;
+
+ if (!flatpak_get_allowed_exports (path, app_id, arg_context,
+ &allowed_extensions, &allowed_prefixes, &require_exact_match))
+ return flatpak_fail (error, "Unexpectedly not allowed to export %s", path);
+
if (g_file_query_exists (src, cancellable))
{
g_debug ("Exporting from %s", path);
@@ -326,7 +274,9 @@ collect_exports (GFile *base,
if (!copy_exports (src,
dest,
path,
- info,
+ allowed_prefixes,
+ allowed_extensions,
+ require_exact_match,
cancellable,
error))
return FALSE;
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 36877090..d7831e7c 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -4954,39 +4954,6 @@ out:
return ret;
}
-typedef gboolean (*MultiplePrefixesComparisonFunc) (const char *path,
- const char * const *prefixes);
-
-static GStrv
-get_permissible_prefixes (FlatpakContext *context,
- const char *source_path,
- const char *app_id,
- GError **error)
-{
- g_autoptr(GPtrArray) prefixes = NULL;
-
- prefixes = g_ptr_array_new_with_free_func (g_free);
-
- /* Create a new pointer array with prefixes including the app
- * ID and in the case of d-bus service files, the allowed own
- * names. */
- g_ptr_array_add (prefixes, g_strdup_printf ("%s.*", app_id));
-
- if (flatpak_has_path_prefix (source_path, "share/dbus-1/services"))
- {
- g_auto(GStrv) owned_dbus_names =
- flatpak_context_get_session_bus_policy_allowed_own_names (context);
- GStrv iter = owned_dbus_names;
-
- for (; *iter != NULL; ++iter)
- g_ptr_array_add (prefixes, g_strdup (*iter));
- }
-
- g_ptr_array_add (prefixes, NULL);
-
- return (GStrv) g_ptr_array_free (g_steal_pointer (&prefixes), FALSE);
-}
-
static gboolean
rewrite_export_dir (const char *app,
const char *branch,
@@ -5004,10 +4971,17 @@ rewrite_export_dir (const char *app,
g_auto(GLnxDirFdIterator) source_iter = {0};
g_autoptr(GHashTable) visited_children = NULL;
struct dirent *dent;
+ gboolean exports_allowed = FALSE;
+ g_auto(GStrv) allowed_prefixes = NULL;
+ g_auto(GStrv) allowed_extensions = NULL;
+ gboolean require_exact_match = FALSE;
if (!glnx_dirfd_iterator_init_at (source_parent_fd, source_name, FALSE, &source_iter, error))
goto out;
+ exports_allowed = flatpak_get_allowed_exports (source_path, app, context,
+ &allowed_extensions, &allowed_prefixes, &require_exact_match);
+
visited_children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
while (TRUE)
@@ -5048,18 +5022,32 @@ rewrite_export_dir (const char *app,
path, cancellable, error))
goto out;
}
- else if (S_ISREG (stbuf.st_mode))
+ else if (S_ISREG (stbuf.st_mode) && exports_allowed)
{
- g_auto(GStrv) permissible_prefixes = get_permissible_prefixes (context,
- source_path,
- app,
- error);
+ g_autofree gchar *name_without_extension = NULL;
g_autofree gchar *new_name = NULL;
+ int i;
- if (permissible_prefixes == NULL)
- return FALSE;
+ for (i = 0; allowed_extensions[i] != NULL; i++)
+ {
+ if (g_str_has_suffix (dent->d_name, allowed_extensions[i]))
+ break;
+ }
+
+ if (allowed_extensions[i] == NULL)
+ {
+ g_warning ("Invalid extension for %s in app %s, removing.", dent->d_name, app);
+ if (unlinkat (source_iter.fd, dent->d_name, 0) != 0 && errno != ENOENT)
+ {
+ glnx_set_error_from_errno (error);
+ goto out;
+ }
+ continue;
+ }
+
+ name_without_extension = g_strndup (dent->d_name, strlen (dent->d_name) - strlen (allowed_extensions[i]));
- if (!flatpak_name_matches_one_wildcard_prefix (dent->d_name, (const char * const *) permissible_prefixes))
+ if (!flatpak_name_matches_one_wildcard_prefix (name_without_extension, (const char * const *) allowed_prefixes, require_exact_match))
{
g_warning ("Non-prefixed filename %s in app %s, removing.", dent->d_name, app);
if (unlinkat (source_iter.fd, dent->d_name, 0) != 0 && errno != ENOENT)
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
index 2a93a19f..a370691b 100644
--- a/common/flatpak-utils.c
+++ b/common/flatpak-utils.c
@@ -761,63 +761,131 @@ out:
}
gboolean
-flatpak_has_name_prefix (const char *string,
- const char *name)
+flatpak_name_matches_one_wildcard_prefix (const char *name,
+ const char * const *wildcarded_prefixes,
+ gboolean require_exact_match)
{
- const char *rest;
+ const char * const *iter = wildcarded_prefixes;
+ const char *remainder;
+ gsize longest_match_len = 0;
+
+ /* Find longest valid match */
+ for (; *iter != NULL; ++iter)
+ {
+ const char *prefix = *iter;
+ gsize prefix_len = strlen (prefix);
+ gsize match_len = strlen (prefix);
+ gboolean has_wildcard = FALSE;
+ const char *end_of_match;
+
+ if (g_str_has_suffix (prefix, ".*"))
+ {
+ has_wildcard = TRUE;
+ prefix_len -= 2;
+ }
+
+ if (strncmp (name, prefix, prefix_len) != 0)
+ continue;
+
+ end_of_match = name + prefix_len;
+
+ if (has_wildcard &&
+ end_of_match[0] == '.' &&
+ is_valid_initial_name_character (end_of_match[1], TRUE))
+ {
+ end_of_match += 2;
+ while (*end_of_match != 0 &&
+ is_valid_name_character (*end_of_match, TRUE))
+ end_of_match++;
+ }
- if (!g_str_has_prefix (string, name))
+ match_len = end_of_match - name;
+
+ if (match_len > longest_match_len)
+ longest_match_len = match_len;
+ }
+
+ if (longest_match_len == 0)
return FALSE;
- rest = string + strlen (name);
+ if (require_exact_match)
+ return name[longest_match_len] == 0;
+
+ /* non-exact matches can be exact, or can be followed by characters that would make
+ * not be part of the last element in the matched prefix, due to being invalid or
+ * a new element. As a special case we explicitly disallow dash here, even though
+ * it iss typically allowed in the final element of a name, this allows you too sloppily
+ * match org.the.App with org.the.App-symbolic[.png] or org.the.App-settings[.desktop].
+ */
+ remainder = name + longest_match_len;
return
- *rest == 0 ||
- *rest == '.' ||
- !is_valid_name_character (*rest, FALSE);
+ *remainder == 0 ||
+ *remainder == '.' ||
+ !is_valid_name_character (*remainder, FALSE);
}
gboolean
-flatpak_name_matches_one_prefix (const char *name,
- const char * const *prefixes)
+flatpak_get_allowed_exports (const char *source_path,
+ const char *app_id,
+ FlatpakContext *context,
+ char ***allowed_extensions_out,
+ char ***allowed_prefixes_out,
+ gboolean *require_exact_match_out)
{
- const char * const *iter = prefixes;
+ g_autoptr(GPtrArray) allowed_extensions = g_ptr_array_new_with_free_func (g_free);
+ g_autoptr(GPtrArray) allowed_prefixes = g_ptr_array_new_with_free_func (g_free);
+ gboolean require_exact_match = FALSE;
- for (; *iter != NULL; ++iter)
- if (flatpak_has_name_prefix (name, *iter))
- return TRUE;
+ g_ptr_array_add (allowed_prefixes, g_strdup_printf ("%s.*", app_id));
- return FALSE;
-}
+ if (flatpak_has_path_prefix (source_path, "share/applications"))
+ {
+ g_ptr_array_add (allowed_extensions, g_strdup (".desktop"));
+ }
+ else if (flatpak_has_path_prefix (source_path, "share/icons"))
+ {
+ g_ptr_array_add (allowed_extensions, g_strdup (".svgz"));
+ g_ptr_array_add (allowed_extensions, g_strdup (".png"));
+ g_ptr_array_add (allowed_extensions, g_strdup (".svg"));
+ g_ptr_array_add (allowed_extensions, g_strdup (".ico"));
+ }
+ else if (flatpak_has_path_prefix (source_path, "share/dbus-1/services"))
+ {
+ g_auto(GStrv) owned_dbus_names = flatpak_context_get_session_bus_policy_allowed_own_names (context);
-gboolean
-flatpak_name_matches_one_wildcard_prefix (const char *name,
- const char * const *wildcarded_prefixes)
-{
- const char * const *iter = wildcarded_prefixes;
- g_autofree char *name_without_suffix = g_strdup (name);
+ g_ptr_array_add (allowed_extensions, g_strdup (".service"));
- char *first_dot = strrchr (name_without_suffix, '.');
- *first_dot = '\0';
+ for (GStrv iter = owned_dbus_names; *iter != NULL; ++iter)
+ g_ptr_array_add (allowed_prefixes, g_strdup (*iter));
- for (; *iter != NULL; ++iter)
+ /* We need an exact match with no extra garbage, because the filename refers to busnames
+ * and we can *only* match exactly these */
+ require_exact_match = TRUE;
+ }
+ else if (flatpak_has_path_prefix (source_path, "share/gnome-shell/search-providers"))
+ {
+ g_ptr_array_add (allowed_extensions, g_strdup (".ini"));
+ }
+ else if (flatpak_has_path_prefix (source_path, "share/mime/packages"))
{
- const char *maybe_wildcarded_prefix = *iter;
+ g_ptr_array_add (allowed_extensions, g_strdup (".xml"));
+ }
+ else
+ return FALSE;
- if (g_str_has_suffix (maybe_wildcarded_prefix, ".*"))
- {
- g_autofree char *truncated_wildcarded_prefix = g_strndup (maybe_wildcarded_prefix,
- strlen (maybe_wildcarded_prefix) - 2);
+ g_ptr_array_add (allowed_extensions, NULL);
+ g_ptr_array_add (allowed_prefixes, NULL);
- if (flatpak_has_name_prefix (name_without_suffix, truncated_wildcarded_prefix))
- return TRUE;
- }
- else if (g_strcmp0 (name_without_suffix, maybe_wildcarded_prefix) == 0)
- {
- return TRUE;
- }
- }
+ if (allowed_extensions_out)
+ *allowed_extensions_out = (char **)g_ptr_array_free (g_steal_pointer (&allowed_extensions), FALSE);
- return FALSE;
+ if (allowed_prefixes_out)
+ *allowed_prefixes_out = (char **)g_ptr_array_free (g_steal_pointer (&allowed_prefixes), FALSE);
+
+ if (require_exact_match_out)
+ *require_exact_match_out = require_exact_match;
+
+ return TRUE;
}
static gboolean
diff --git a/common/flatpak-utils.h b/common/flatpak-utils.h
index fcd19bb8..535932e6 100644
--- a/common/flatpak-utils.h
+++ b/common/flatpak-utils.h
@@ -141,12 +141,17 @@ gboolean flatpak_summary_lookup_ref (GVariant *summary,
char **out_checksum,
GVariant **out_variant);
-gboolean flatpak_has_name_prefix (const char *string,
- const char *name);
-gboolean flatpak_name_matches_one_prefix (const char *string,
- const char * const *prefixes);
gboolean flatpak_name_matches_one_wildcard_prefix (const char *string,
- const char * const *maybe_wildcard_prefixes);
+ const char * const *maybe_wildcard_prefixes,
+ gboolean require_exact_match);
+
+gboolean flatpak_get_allowed_exports (const char *source_path,
+ const char *app_id,
+ FlatpakContext *context,
+ char ***allowed_extensions_out,
+ char ***allowed_prefixes_out,
+ gboolean *require_exact_match_out);
+
gboolean flatpak_is_valid_name (const char *string,
GError **error);
gboolean flatpak_is_valid_branch (const char *string,