From f81c2d57ea4fb580db958de0eb97d66d01e99025 Mon Sep 17 00:00:00 2001 From: Ludovico de Nittis <ludovico.denittis@collabora.com> Date: Wed, 2 Sep 2020 15:09:02 +0200 Subject: [PATCH] bwrap: Build arguments to bind /usr if already in a container The filesystem that is providing /usr might not be mounted in the same place in the current namespace, and on the host system where bwrap will be run. If it isn't, we need to use one path to do file I/O when inspecting it, but pass a different path to bwrap. Signed-off-by: Ludovico de Nittis <ludovico.denittis@collabora.com> --- src/bwrap.c | 70 +++++++++++++++++++++++++++++++++++---------------- src/bwrap.h | 5 ++-- src/runtime.c | 16 +++++++++--- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/bwrap.c b/src/bwrap.c index 747271ad1..82e118851 100644 --- a/src/bwrap.c +++ b/src/bwrap.c @@ -23,6 +23,8 @@ #include "bwrap.h" +#include "resolve-in-sysroot.h" + /** * pv_bwrap_run_sync: * @bwrap: A #FlatpakBwrap on which flatpak_bwrap_finish() has been called @@ -156,9 +158,20 @@ pv_bwrap_execve (FlatpakBwrap *bwrap, /** * pv_bwrap_bind_usr: * @bwrap: The #FlatpakBwrap - * @host_path: Absolute path to a directory in the host filesystem - * @mount_point: Absolute path of the location at which to mount @host_path - * in the container + * @provider_in_host_namespace: The directory we will + * use to provide the container's `/usr`, `/lib*` etc., + * in the form of an absolute path that can be resolved + * on the host system + * @provider_in_current_namespace: The same directory, this time + * in the form of an absolute path that can be resolved + * in the namespace where pressure-vessel-wrap is running. + * For example, if we run in a Flatpak container and we intend + * to mount the host system's `/usr`, then + * @provider_in_host_namespace would be `/` + * but @provider_in_current_namespace would be `/run/host`. + * @provider_in_container_namespace: Absolute path of the location + * at which we will mount @provider_in_host_namespace in the + * final container * @error: Used to raise an error on failure * * Append arguments to @bwrap that will bind-mount `/usr` and associated @@ -182,11 +195,13 @@ pv_bwrap_execve (FlatpakBwrap *bwrap, */ gboolean pv_bwrap_bind_usr (FlatpakBwrap *bwrap, - const char *host_path, - const char *mount_point, + const char *provider_in_host_namespace, + const char *provider_in_current_namespace, + const char *provider_in_container_namespace, GError **error) { g_autofree gchar *usr = NULL; + g_autofree gchar *usr_in_current_namespace = NULL; g_autofree gchar *dest = NULL; gboolean host_path_is_usr = FALSE; g_autoptr(GDir) dir = NULL; @@ -202,16 +217,20 @@ pv_bwrap_bind_usr (FlatpakBwrap *bwrap, g_return_val_if_fail (bwrap != NULL, FALSE); g_return_val_if_fail (!pv_bwrap_was_finished (bwrap), FALSE); - g_return_val_if_fail (host_path != NULL, FALSE); - g_return_val_if_fail (host_path[0] == '/', FALSE); - g_return_val_if_fail (mount_point != NULL, FALSE); - g_return_val_if_fail (mount_point[0] == '/', FALSE); + g_return_val_if_fail (provider_in_host_namespace != NULL, FALSE); + g_return_val_if_fail (provider_in_host_namespace[0] == '/', FALSE); + g_return_val_if_fail (provider_in_current_namespace != NULL, FALSE); + g_return_val_if_fail (provider_in_current_namespace[0] == '/', FALSE); + g_return_val_if_fail (provider_in_container_namespace != NULL, FALSE); + g_return_val_if_fail (provider_in_container_namespace[0] == '/', FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - usr = g_build_filename (host_path, "usr", NULL); - dest = g_build_filename (mount_point, "usr", NULL); + usr = g_build_filename (provider_in_host_namespace, "usr", NULL); + usr_in_current_namespace = g_build_filename (provider_in_current_namespace, + "usr", NULL); + dest = g_build_filename (provider_in_container_namespace, "usr", NULL); - if (g_file_test (usr, G_FILE_TEST_IS_DIR)) + if (g_file_test (usr_in_current_namespace, G_FILE_TEST_IS_DIR)) { flatpak_bwrap_add_args (bwrap, "--ro-bind", usr, dest, @@ -222,13 +241,13 @@ pv_bwrap_bind_usr (FlatpakBwrap *bwrap, /* host_path is assumed to be a merged /usr */ host_path_is_usr = TRUE; flatpak_bwrap_add_args (bwrap, - "--ro-bind", host_path, dest, + "--ro-bind", provider_in_host_namespace, dest, NULL); } g_clear_pointer (&dest, g_free); - dir = g_dir_open (host_path, 0, error); + dir = g_dir_open (provider_in_current_namespace, 0, error); if (dir == NULL) return FALSE; @@ -243,7 +262,7 @@ pv_bwrap_bind_usr (FlatpakBwrap *bwrap, || g_str_equal (member, "sbin") || g_str_equal (member, ".ref")) { - dest = g_build_filename (mount_point, member, NULL); + dest = g_build_filename (provider_in_container_namespace, member, NULL); if (host_path_is_usr) { @@ -256,9 +275,14 @@ pv_bwrap_bind_usr (FlatpakBwrap *bwrap, } else { - g_autofree gchar *path = g_build_filename (host_path, - member, NULL); - g_autofree gchar *target = glnx_readlinkat_malloc (-1, path, NULL, NULL); + g_autofree gchar *path_in_host = g_build_filename (provider_in_host_namespace, + member, NULL); + g_autofree gchar *path_in_current_namespace = + g_build_filename (provider_in_current_namespace, member, NULL); + + g_autofree gchar *target = glnx_readlinkat_malloc (-1, + path_in_current_namespace, + NULL, NULL); if (target != NULL) { @@ -269,7 +293,7 @@ pv_bwrap_bind_usr (FlatpakBwrap *bwrap, else { flatpak_bwrap_add_args (bwrap, - "--ro-bind", path, dest, + "--ro-bind", path_in_host, dest, NULL); } } @@ -280,12 +304,14 @@ pv_bwrap_bind_usr (FlatpakBwrap *bwrap, for (i = 0; i < G_N_ELEMENTS (bind_etc); i++) { - g_autofree gchar *path = g_build_filename (host_path, "etc", + g_autofree gchar *path = g_build_filename (provider_in_host_namespace, "etc", bind_etc[i], NULL); + g_autofree gchar *path_in_current_namespace = g_build_filename (provider_in_current_namespace, + "etc", bind_etc[i], NULL); - if (g_file_test (path, G_FILE_TEST_EXISTS)) + if (g_file_test (path_in_current_namespace, G_FILE_TEST_EXISTS)) { - dest = g_build_filename (mount_point, "etc", bind_etc[i], NULL); + dest = g_build_filename (provider_in_container_namespace, "etc", bind_etc[i], NULL); flatpak_bwrap_add_args (bwrap, "--ro-bind", path, dest, diff --git a/src/bwrap.h b/src/bwrap.h index 9446a53c0..c8e5a5a9c 100644 --- a/src/bwrap.h +++ b/src/bwrap.h @@ -34,8 +34,9 @@ gboolean pv_bwrap_execve (FlatpakBwrap *bwrap, int original_stdout, GError **error); gboolean pv_bwrap_bind_usr (FlatpakBwrap *bwrap, - const char *host_path, - const char *mount_point, + const char *provider_in_host_namespace, + const char *provider_in_current_namespace, + const char *provider_in_container_namespace, GError **error); void pv_bwrap_copy_tree (FlatpakBwrap *bwrap, const char *source, diff --git a/src/runtime.c b/src/runtime.c index 6a9010257..dcf451f02 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -64,6 +64,7 @@ struct _PvRuntime FlatpakBwrap *container_access_adverb; const gchar *runtime_files; /* either source_files or mutable_sysroot */ gchar *runtime_usr; /* either runtime_files or that + "/usr" */ + gchar *runtime_files_on_host; const gchar *adverb_in_container; PvRuntimeFlags flags; @@ -741,6 +742,8 @@ pv_runtime_initable_init (GInitable *initable, self->runtime_files = self->source_files; } + //TODO This will be used in the future. + self->runtime_files_on_host = g_strdup (self->runtime_files); g_mkdir (self->overrides, 0700); self->runtime_usr = g_build_filename (self->runtime_files, "usr", NULL); @@ -800,6 +803,7 @@ pv_runtime_finalize (GObject *object) g_free (self->mutable_parent); glnx_close_fd (&self->mutable_sysroot_fd); g_free (self->mutable_sysroot); + g_free (self->runtime_files_on_host); g_free (self->runtime_usr); g_free (self->source_files); g_free (self->tools_dir); @@ -1024,6 +1028,7 @@ pv_runtime_provide_container_access (PvRuntime *self, "--tmpfs", self->container_access, NULL); if (!pv_bwrap_bind_usr (self->container_access_adverb, + self->runtime_files_on_host, self->runtime_files, self->container_access, error)) @@ -1365,7 +1370,7 @@ bind_runtime (PvRuntime *self, g_return_val_if_fail (!pv_bwrap_was_finished (bwrap), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - if (!pv_bwrap_bind_usr (bwrap, self->runtime_files, "/", error)) + if (!pv_bwrap_bind_usr (bwrap, self->runtime_files_on_host, self->runtime_files, "/", error)) return FALSE; /* In the case where we have a mutable sysroot, we mount the overrides @@ -1413,7 +1418,7 @@ bind_runtime (PvRuntime *self, "/run/host/os-release", NULL); - if (!pv_bwrap_bind_usr (bwrap, "/", "/run/host", error)) + if (!pv_bwrap_bind_usr (bwrap, "/", "/", "/run/host", error)) return FALSE; for (i = 0; i < G_N_ELEMENTS (bind_mutable); i++) @@ -2128,12 +2133,17 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self, NULL); if (!pv_bwrap_bind_usr (temp_bwrap, + self->runtime_files_on_host, self->runtime_files, "/", error)) return FALSE; - if (!pv_bwrap_bind_usr (temp_bwrap, "/", "/run/host", error)) + if (!pv_bwrap_bind_usr (temp_bwrap, + "/", + "/", + "/run/host", + error)) return FALSE; flatpak_bwrap_add_args (temp_bwrap, -- GitLab