From 3b1b9c65cd99e45548787d0aa475dfb4ec1b88fa Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 1 Feb 2018 12:10:28 +0100 Subject: [PATCH] Move chunk of filesystem setup from flatpak-run.c to FlatpakContext This way the filesystem setup is centralized in one place. Closes: #1374 Approved by: alexlarsson --- common/flatpak-context.c | 156 +++++++++++++++++++++++++++++++++- common/flatpak-context.h | 12 +-- common/flatpak-run.c | 177 +-------------------------------------- 3 files changed, 163 insertions(+), 182 deletions(-) diff --git a/common/flatpak-context.c b/common/flatpak-context.c index 10aba9db..aae2726f 100644 --- a/common/flatpak-context.c +++ b/common/flatpak-context.c @@ -494,6 +494,41 @@ get_xdg_dir_from_prefix (const char *prefix, return FALSE; } +/* This looks only in the xdg dirs (config, cache, data), not the user + definable ones */ +static char * +get_xdg_dir_from_string (const char *filesystem, + const char **suffix, + const char **where) +{ + char *slash; + const char *rest; + g_autofree char *prefix = NULL; + const char *dir = NULL; + gsize len; + + slash = strchr (filesystem, '/'); + + if (slash) + len = slash - filesystem; + else + len = strlen (filesystem); + + rest = filesystem + len; + while (*rest == '/') + rest++; + + if (suffix != NULL) + *suffix = rest; + + prefix = g_strndup (filesystem, len); + + if (get_xdg_dir_from_prefix (prefix, where, &dir)) + return g_build_filename (dir, rest, NULL); + + return NULL; +} + static gboolean get_xdg_user_dir_from_string (const char *filesystem, const char **config_key, @@ -1696,7 +1731,7 @@ const char *dont_mount_in_root[] = { "tmp", "etc", "app", "run", "proc", "sys", "dev", "var", NULL }; -void +static void flatpak_context_export (FlatpakContext *context, FlatpakExports *exports, GFile *app_id_dir, @@ -1845,3 +1880,122 @@ flatpak_context_get_exports (FlatpakContext *context, flatpak_context_export (context, exports, app_id_dir, FALSE, NULL, NULL); return g_steal_pointer (&exports); } + +void +flatpak_context_append_bwrap_filesystem (FlatpakContext *context, + FlatpakBwrap *bwrap, + const char *app_id, + GFile *app_id_dir, + FlatpakExports **exports_out) +{ + g_autoptr(FlatpakExports) exports = flatpak_exports_new (); + g_autoptr(GString) xdg_dirs_conf = g_string_new (""); + g_autoptr(GFile) user_flatpak_dir = NULL; + gboolean home_access = FALSE; + GHashTableIter iter; + gpointer key, value; + + flatpak_context_export (context, exports, app_id_dir, TRUE, xdg_dirs_conf, &home_access); + if (app_id_dir != NULL) + flatpak_run_apply_env_appid (bwrap, app_id_dir); + + if (!home_access) + { + /* Enable persistent mapping only if no access to real home dir */ + + g_hash_table_iter_init (&iter, context->persistent); + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + const char *persist = key; + g_autofree char *src = g_build_filename (g_get_home_dir (), ".var/app", app_id, persist, NULL); + g_autofree char *dest = g_build_filename (g_get_home_dir (), persist, NULL); + + g_mkdir_with_parents (src, 0755); + + /* We stick to flatpak_bwrap_add_args instead of flatpak_bwrap_add_bind_arg because persisted + * folders don't need to exist outside the chroot. + */ + flatpak_bwrap_add_args (bwrap, "--bind", src, dest, NULL); + } + } + + { + g_autofree char *run_user_app_dst = g_strdup_printf ("/run/user/%d/app/%s", getuid (), app_id); + g_autofree char *run_user_app_src = g_build_filename (g_get_user_runtime_dir (), "app", app_id, NULL); + + if (glnx_shutil_mkdir_p_at (AT_FDCWD, + run_user_app_src, + 0700, + NULL, + NULL)) + flatpak_bwrap_add_args (bwrap, + "--bind", run_user_app_src, run_user_app_dst, + NULL); + } + + /* Hide the flatpak dir by default (unless explicitly made visible) */ + user_flatpak_dir = flatpak_get_user_base_dir_location (); + flatpak_exports_add_path_tmpfs (exports, flatpak_file_get_path_cached (user_flatpak_dir)); + + /* Ensure we always have a homedir */ + flatpak_exports_add_path_dir (exports, g_get_home_dir ()); + + /* This actually outputs the args for the hide/expose operations above */ + flatpak_exports_append_bwrap_args (exports, bwrap); + + /* Special case subdirectories of the cache, config and data xdg + * dirs. If these are accessible explicilty, then we bind-mount + * these in the app-id dir. This allows applications to explicitly + * opt out of keeping some config/cache/data in the app-specific + * directory. + */ + if (app_id_dir) + { + g_hash_table_iter_init (&iter, context->filesystems); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + const char *filesystem = key; + FlatpakFilesystemMode mode = GPOINTER_TO_INT (value); + g_autofree char *xdg_path = NULL; + const char *rest, *where; + + xdg_path = get_xdg_dir_from_string (filesystem, &rest, &where); + + if (xdg_path != NULL && *rest != 0 && + mode >= FLATPAK_FILESYSTEM_MODE_READ_ONLY) + { + g_autoptr(GFile) app_version = g_file_get_child (app_id_dir, where); + g_autoptr(GFile) app_version_subdir = g_file_resolve_relative_path (app_version, rest); + + if (g_file_test (xdg_path, G_FILE_TEST_IS_DIR) || + g_file_test (xdg_path, G_FILE_TEST_IS_REGULAR)) + { + g_autofree char *xdg_path_in_app = g_file_get_path (app_version_subdir); + flatpak_bwrap_add_bind_arg (bwrap, + mode == FLATPAK_FILESYSTEM_MODE_READ_ONLY ? "--ro-bind" : "--bind", + xdg_path, xdg_path_in_app); + } + } + } + } + + if (home_access && app_id_dir != NULL) + { + g_autofree char *src_path = g_build_filename (g_get_user_config_dir (), + "user-dirs.dirs", + NULL); + g_autofree char *path = g_build_filename (flatpak_file_get_path_cached (app_id_dir), + "config/user-dirs.dirs", NULL); + if (g_file_test (src_path, G_FILE_TEST_EXISTS)) + flatpak_bwrap_add_bind_arg (bwrap, "--ro-bind", src_path, path); + } + else if (xdg_dirs_conf->len > 0 && app_id_dir != NULL) + { + g_autofree char *path = + g_build_filename (flatpak_file_get_path_cached (app_id_dir), + "config/user-dirs.dirs", NULL); + + flatpak_bwrap_add_args_data (bwrap, "xdg-config-dirs", + xdg_dirs_conf->str, xdg_dirs_conf->len, path, NULL); + } +} diff --git a/common/flatpak-context.h b/common/flatpak-context.h index aaf874ee..ad92eecc 100644 --- a/common/flatpak-context.h +++ b/common/flatpak-context.h @@ -115,12 +115,12 @@ FlatpakContext *flatpak_context_load_for_app (const char *app_id, FlatpakExports *flatpak_context_get_exports (FlatpakContext *context, const char *app_id); -void flatpak_context_export (FlatpakContext *context, - FlatpakExports *exports, - GFile *app_id_dir, - gboolean do_create, - GString *xdg_dirs_conf, - gboolean *home_access_out); + +void flatpak_context_append_bwrap_filesystem (FlatpakContext *context, + FlatpakBwrap *bwrap, + const char *app_id, + GFile *app_id_dir, + FlatpakExports **exports_out); G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakContext, flatpak_context_free) diff --git a/common/flatpak-run.c b/common/flatpak-run.c index 0682d89d..a91c3451 100644 --- a/common/flatpak-run.c +++ b/common/flatpak-run.c @@ -67,73 +67,6 @@ add_dbus_proxy_args (GPtrArray *argv_array, const char *app_info_path, GError **error); -static gboolean -get_xdg_dir_from_prefix (const char *prefix, - const char **where, - const char **dir) -{ - if (strcmp (prefix, "xdg-data") == 0) - { - if (where) - *where = "data"; - if (dir) - *dir = g_get_user_data_dir (); - return TRUE; - } - if (strcmp (prefix, "xdg-cache") == 0) - { - if (where) - *where = "cache"; - if (dir) - *dir = g_get_user_cache_dir (); - return TRUE; - } - if (strcmp (prefix, "xdg-config") == 0) - { - if (where) - *where = "config"; - if (dir) - *dir = g_get_user_config_dir (); - return TRUE; - } - return FALSE; -} - -/* This looks only in the xdg dirs (config, cache, data), not the user - definable ones */ -static char * -get_xdg_dir_from_string (const char *filesystem, - const char **suffix, - const char **where) -{ - char *slash; - const char *rest; - g_autofree char *prefix = NULL; - const char *dir = NULL; - gsize len; - - slash = strchr (filesystem, '/'); - - if (slash) - len = slash - filesystem; - else - len = strlen (filesystem); - - rest = filesystem + len; - while (*rest == '/') - rest++; - - if (suffix != NULL) - *suffix = rest; - - prefix = g_strndup (filesystem, len); - - if (get_xdg_dir_from_prefix (prefix, where, &dir)) - return g_build_filename (dir, rest, NULL); - - return NULL; -} - static char * extract_unix_path_from_dbus_address (const char *address) { @@ -702,15 +635,11 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, GCancellable *cancellable, GError **error) { - gboolean home_access = FALSE; - GHashTableIter iter; - gpointer key, value; gboolean unrestricted_session_bus; gboolean unrestricted_system_bus; - g_autoptr(GString) xdg_dirs_conf = g_string_new (""); g_autoptr(GError) my_error = NULL; g_autoptr(GFile) user_flatpak_dir = NULL; - g_autoptr(FlatpakExports) exports = flatpak_exports_new (); + g_autoptr(FlatpakExports) exports = NULL; g_autoptr(GPtrArray) session_bus_proxy_argv = NULL; g_autoptr(GPtrArray) system_bus_proxy_argv = NULL; g_autoptr(GPtrArray) a11y_bus_proxy_argv = NULL; @@ -775,109 +704,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, } } - flatpak_context_export (context, exports, app_id_dir, TRUE, xdg_dirs_conf, &home_access); - if (app_id_dir != NULL) - flatpak_run_apply_env_appid (bwrap, app_id_dir); - - if (!home_access) - { - /* Enable persistent mapping only if no access to real home dir */ - - g_hash_table_iter_init (&iter, context->persistent); - while (g_hash_table_iter_next (&iter, &key, NULL)) - { - const char *persist = key; - g_autofree char *src = g_build_filename (g_get_home_dir (), ".var/app", app_id, persist, NULL); - g_autofree char *dest = g_build_filename (g_get_home_dir (), persist, NULL); - - g_mkdir_with_parents (src, 0755); - - /* We stick to flatpak_bwrap_add_args instead of flatpak_bwrap_add_bind_arg because persisted - * folders don't need to exist outside the chroot. - */ - flatpak_bwrap_add_args (bwrap, "--bind", src, dest, NULL); - } - } - - { - g_autofree char *run_user_app_dst = g_strdup_printf ("/run/user/%d/app/%s", getuid (), app_id); - g_autofree char *run_user_app_src = g_build_filename (g_get_user_runtime_dir (), "app", app_id, NULL); - - if (glnx_shutil_mkdir_p_at (AT_FDCWD, - run_user_app_src, - 0700, - NULL, - NULL)) - flatpak_bwrap_add_args (bwrap, - "--bind", run_user_app_src, run_user_app_dst, - NULL); - } - - /* Hide the flatpak dir by default (unless explicitly made visible) */ - user_flatpak_dir = flatpak_get_user_base_dir_location (); - flatpak_exports_add_path_tmpfs (exports, flatpak_file_get_path_cached (user_flatpak_dir)); - - /* Ensure we always have a homedir */ - flatpak_exports_add_path_dir (exports, g_get_home_dir ()); - - /* This actually outputs the args for the hide/expose operations above */ - flatpak_exports_append_bwrap_args (exports, bwrap); - - /* Special case subdirectories of the cache, config and data xdg - * dirs. If these are accessible explicilty, then we bind-mount - * these in the app-id dir. This allows applications to explicitly - * opt out of keeping some config/cache/data in the app-specific - * directory. - */ - if (app_id_dir) - { - g_hash_table_iter_init (&iter, context->filesystems); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const char *filesystem = key; - FlatpakFilesystemMode mode = GPOINTER_TO_INT (value); - g_autofree char *xdg_path = NULL; - const char *rest, *where; - - xdg_path = get_xdg_dir_from_string (filesystem, &rest, &where); - - if (xdg_path != NULL && *rest != 0 && - mode >= FLATPAK_FILESYSTEM_MODE_READ_ONLY) - { - g_autoptr(GFile) app_version = g_file_get_child (app_id_dir, where); - g_autoptr(GFile) app_version_subdir = g_file_resolve_relative_path (app_version, rest); - - if (g_file_test (xdg_path, G_FILE_TEST_IS_DIR) || - g_file_test (xdg_path, G_FILE_TEST_IS_REGULAR)) - { - g_autofree char *xdg_path_in_app = g_file_get_path (app_version_subdir); - flatpak_bwrap_add_bind_arg (bwrap, - mode == FLATPAK_FILESYSTEM_MODE_READ_ONLY ? "--ro-bind" : "--bind", - xdg_path, xdg_path_in_app); - } - } - } - } - - if (home_access && app_id_dir != NULL) - { - g_autofree char *src_path = g_build_filename (g_get_user_config_dir (), - "user-dirs.dirs", - NULL); - g_autofree char *path = g_build_filename (flatpak_file_get_path_cached (app_id_dir), - "config/user-dirs.dirs", NULL); - if (g_file_test (src_path, G_FILE_TEST_EXISTS)) - flatpak_bwrap_add_bind_arg (bwrap, "--ro-bind", src_path, path); - } - else if (xdg_dirs_conf->len > 0 && app_id_dir != NULL) - { - g_autofree char *path = - g_build_filename (flatpak_file_get_path_cached (app_id_dir), - "config/user-dirs.dirs", NULL); - - flatpak_bwrap_add_args_data (bwrap, "xdg-config-dirs", - xdg_dirs_conf->str, xdg_dirs_conf->len, path, NULL); - } + flatpak_context_append_bwrap_filesystem (context, bwrap, app_id, app_id_dir, &exports); flatpak_run_add_x11_args (bwrap, (context->sockets & FLATPAK_CONTEXT_SOCKET_X11) != 0);