From 791337fa468e58a5d3e3228e598f81daf832cbdc Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 30 Nov 2023 11:12:55 -0500 Subject: [PATCH 1/4] sysroot: Expose deployment container executor internally Prep for using this for zipl. --- src/libostree/ostree-sysroot-deploy.c | 12 +++++++----- src/libostree/ostree-sysroot-private.h | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 74c84d2738..077b4863df 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -3164,9 +3164,9 @@ child_setup_fchdir (gpointer data) /* * Derived from rpm-ostree's rust/src/bwrap.rs */ -static gboolean -run_in_deployment (int deployment_dfd, const gchar *const *child_argv, gint *exit_status, - gchar **stdout, GError **error) +gboolean +_ostree_sysroot_run_in_deployment (int deployment_dfd, const gchar *const *child_argv, + gint *exit_status, gchar **stdout, GError **error) { static const gchar *const COMMON_ARGV[] = { "/usr/bin/bwrap", "--dev", @@ -3264,7 +3264,8 @@ sysroot_finalize_selinux_policy (int deployment_dfd, GError **error) * flag is not supported by semodule. */ static const gchar *const SEMODULE_HELP_ARGV[] = { "semodule", "--help", NULL }; - if (!run_in_deployment (deployment_dfd, SEMODULE_HELP_ARGV, &exit_status, &stdout, error)) + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, SEMODULE_HELP_ARGV, &exit_status, &stdout, + error)) return FALSE; if (!g_spawn_check_exit_status (exit_status, error)) return glnx_prefix_error (error, "failed to run semodule"); @@ -3278,7 +3279,8 @@ sysroot_finalize_selinux_policy (int deployment_dfd, GError **error) ot_journal_print (LOG_INFO, "Refreshing SELinux policy"); guint64 start_msec = g_get_monotonic_time () / 1000; - if (!run_in_deployment (deployment_dfd, SEMODULE_REBUILD_ARGV, &exit_status, NULL, error)) + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, SEMODULE_REBUILD_ARGV, &exit_status, NULL, + error)) return FALSE; guint64 end_msec = g_get_monotonic_time () / 1000; ot_journal_print (LOG_INFO, "Refreshed SELinux policy in %" G_GUINT64_FORMAT " ms", diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 5be07c24ba..d18e4082c4 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -150,6 +150,9 @@ gboolean _ostree_sysroot_rmrf_deployment (OstreeSysroot *sysroot, OstreeDeployme char *_ostree_sysroot_get_runstate_path (OstreeDeployment *deployment, const char *key); +gboolean _ostree_sysroot_run_in_deployment (int deployment_dfd, const gchar *const *child_argv, + gint *exit_status, gchar **stdout, GError **error); + char *_ostree_sysroot_join_lines (GPtrArray *lines); gboolean _ostree_sysroot_ensure_boot_fd (OstreeSysroot *self, GError **error); From 744569723d4310f919ca0e661c4aec235752180a Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 1 Dec 2023 08:14:15 -0500 Subject: [PATCH 2/4] sysroot: Support specifying bwrap arguments Prep for use with zipl. --- src/libostree/ostree-sysroot-deploy.c | 18 ++++++++++++------ src/libostree/ostree-sysroot-private.h | 5 +++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 077b4863df..7648f29943 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -3165,8 +3165,9 @@ child_setup_fchdir (gpointer data) * Derived from rpm-ostree's rust/src/bwrap.rs */ gboolean -_ostree_sysroot_run_in_deployment (int deployment_dfd, const gchar *const *child_argv, - gint *exit_status, gchar **stdout, GError **error) +_ostree_sysroot_run_in_deployment (int deployment_dfd, const char *const *bwrap_argv, + const gchar *const *child_argv, gint *exit_status, + gchar **stdout, GError **error) { static const gchar *const COMMON_ARGV[] = { "/usr/bin/bwrap", "--dev", @@ -3229,6 +3230,11 @@ _ostree_sysroot_run_in_deployment (int deployment_dfd, const gchar *const *child for (char **it = (char **)COMMON_ARGV; it && *it; it++) g_ptr_array_add (args, *it); + for (char **it = (char **)bwrap_argv; it && *it; it++) + g_ptr_array_add (args, *it); + + // Separate bwrap args from child args + g_ptr_array_add (args, "--"); for (char **it = (char **)child_argv; it && *it; it++) g_ptr_array_add (args, *it); @@ -3264,8 +3270,8 @@ sysroot_finalize_selinux_policy (int deployment_dfd, GError **error) * flag is not supported by semodule. */ static const gchar *const SEMODULE_HELP_ARGV[] = { "semodule", "--help", NULL }; - if (!_ostree_sysroot_run_in_deployment (deployment_dfd, SEMODULE_HELP_ARGV, &exit_status, &stdout, - error)) + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, NULL, SEMODULE_HELP_ARGV, &exit_status, + &stdout, error)) return FALSE; if (!g_spawn_check_exit_status (exit_status, error)) return glnx_prefix_error (error, "failed to run semodule"); @@ -3279,8 +3285,8 @@ sysroot_finalize_selinux_policy (int deployment_dfd, GError **error) ot_journal_print (LOG_INFO, "Refreshing SELinux policy"); guint64 start_msec = g_get_monotonic_time () / 1000; - if (!_ostree_sysroot_run_in_deployment (deployment_dfd, SEMODULE_REBUILD_ARGV, &exit_status, NULL, - error)) + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, NULL, SEMODULE_REBUILD_ARGV, &exit_status, + NULL, error)) return FALSE; guint64 end_msec = g_get_monotonic_time () / 1000; ot_journal_print (LOG_INFO, "Refreshed SELinux policy in %" G_GUINT64_FORMAT " ms", diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index d18e4082c4..851bc1f8e6 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -150,8 +150,9 @@ gboolean _ostree_sysroot_rmrf_deployment (OstreeSysroot *sysroot, OstreeDeployme char *_ostree_sysroot_get_runstate_path (OstreeDeployment *deployment, const char *key); -gboolean _ostree_sysroot_run_in_deployment (int deployment_dfd, const gchar *const *child_argv, - gint *exit_status, gchar **stdout, GError **error); +gboolean _ostree_sysroot_run_in_deployment (int deployment_dfd, const char *const *bwrap_argv, + const gchar *const *child_argv, gint *exit_status, + gchar **stdout, GError **error); char *_ostree_sysroot_join_lines (GPtrArray *lines); From aa635bf559a5f847d061648ecb9486263195f8f8 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 1 Dec 2023 15:05:40 -0500 Subject: [PATCH 3/4] sysroot: Expose deployment runner outside of selinux We will use it in e.g. s390x zipl backend. --- src/libostree/ostree-sysroot-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 7648f29943..8f93d4ab72 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -3151,7 +3151,6 @@ get_var_dfd (OstreeSysroot *self, int osdeploy_dfd, OstreeDeployment *deployment return glnx_opendirat (base_dfd, base_path, TRUE, ret_fd, error); } -#ifdef HAVE_SELINUX static void child_setup_fchdir (gpointer data) { @@ -3245,6 +3244,7 @@ _ostree_sysroot_run_in_deployment (int deployment_dfd, const char *const *bwrap_ (gpointer)(uintptr_t)deployment_dfd, stdout, NULL, exit_status, error); } +#ifdef HAVE_SELINUX /* * Run semodule to check if the module content changed after merging /etc * and rebuild the policy if needed. From c3aa2958c26a65543ed0448c51b4f142b40e5da3 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 30 Nov 2023 18:16:33 -0500 Subject: [PATCH 4/4] bootloader/zipl: Run in target deployment as container if needed xref https://issues.redhat.com/browse/MGMT-16303 Basically the OCP Assisted installer has now grown code to try to do OS updates offline post-install, and this means we need to handle the case of running zipl from the target root. --- src/libostree/ostree-bootloader-zipl.c | 44 ++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/libostree/ostree-bootloader-zipl.c b/src/libostree/ostree-bootloader-zipl.c index 42cae8241d..f92cc61dcd 100644 --- a/src/libostree/ostree-bootloader-zipl.c +++ b/src/libostree/ostree-bootloader-zipl.c @@ -434,10 +434,19 @@ _ostree_bootloader_zipl_post_bls_sync (OstreeBootloader *bootloader, int bootver if (getuid () != 0) return TRUE; - /* Note that unlike the grub2-mkconfig backend, we make no attempt to - * chroot(). - */ - g_assert (self->sysroot->booted_deployment); + // If we're in a booted deployment, we don't need to spawn a container. + // Also avoid containerizing if there's no deployments to target, which shouldn't + // generally happen. + OstreeDeployment *target_deployment; + if (self->sysroot->booted_deployment || self->sysroot->deployments->len == 0) + { + target_deployment = NULL; + } + else + { + g_assert_cmpint (self->sysroot->deployments->len, >, 0); + target_deployment = self->sysroot->deployments->pdata[0]; + } if (!glnx_fstatat_allow_noent (self->sysroot->sysroot_fd, zipl_requires_execute_path, NULL, 0, error)) @@ -467,9 +476,30 @@ _ostree_bootloader_zipl_post_bls_sync (OstreeBootloader *bootloader, int bootver const char *const zipl_argv[] = { "zipl", "--secure", (sb_enabled == TRUE) ? "1" : "auto", "-V", NULL }; int estatus; - if (!g_spawn_sync (NULL, (char **)zipl_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, - &estatus, error)) - return FALSE; + if (target_deployment != NULL) + { + g_debug ("executing zipl in deployment root"); + g_autofree char *deployment_path + = ostree_sysroot_get_deployment_dirpath (self->sysroot, target_deployment); + glnx_autofd int deployment_dfd = -1; + if (!glnx_opendirat (self->sysroot->sysroot_fd, deployment_path, TRUE, &deployment_dfd, + error)) + return FALSE; + + g_autofree char *sysroot_boot + = g_build_filename (gs_file_get_path_cached (self->sysroot->path), "boot", NULL); + const char *bwrap_args[] = { "--bind", sysroot_boot, "/boot", NULL }; + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, bwrap_args, zipl_argv, &estatus, NULL, + error)) + return glnx_prefix_error (error, "Failed to invoke zipl"); + } + else + { + g_debug ("executing zipl from booted system"); + if (!g_spawn_sync (NULL, (char **)zipl_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, + NULL, &estatus, error)) + return FALSE; + } if (!g_spawn_check_exit_status (estatus, error)) return FALSE; if (!glnx_unlinkat (self->sysroot->sysroot_fd, zipl_requires_execute_path, 0, error))