From 0340702b658f402fc070e55588c700c74e3fbaa5 Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Wed, 9 Mar 2022 15:27:11 +0100 Subject: [PATCH] deploy: try to rebuild policy in new deployment if needed Whenever the user has SELinux enabled and has any local modules/modifications installed, it is necessary to rebuild the policy in the final deployment, otherwise ostree will leave the binary policy files uchanged from last deployment as it detects difference against the base content (in rpm-ostree case this is the RPM content). To avoid the situation where the policy binaries go stale once any local customization of the policy is made, try to rebuild the policy as part of sysroot_finalize_deployment(). Use the special --rebuild-if-modules-changed switch, which detects if the input module files have changed relative to last time the policy was built and skips the most time-consuming part of the rebuild process if modules are unchanged (thus making this a relatively cheap operation if the user hasn't made any modifications to the shipped policy). Partially addresses: https://github.com/coreos/fedora-coreos-tracker/issues/701 Signed-off-by: Ondrej Mosnacek --- src/libostree/ostree-sysroot-deploy.c | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index b7cc232f46..fa391721ad 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2830,6 +2830,59 @@ get_var_dfd (OstreeSysroot *self, return glnx_opendirat (base_dfd, base_path, TRUE, ret_fd, error); } +/* + * Derived from rpm-ostree's rust/src/bwrap.rs + */ +static gboolean +run_in_deployment (const gchar *deployment_path, + const gchar * const *child_argv, + gsize child_argc, + gint *exit_status, + GError **error) +{ + static const gchar * const COMMON_ARGV[] = { + "/usr/bin/bwrap", + "--dev", "/dev", "--proc", "/proc", "--dir", "/run", "--dir", "/tmp", + "--chdir", "/", + "--die-with-parent", + "--unshare-pid", + "--unshare-uts", + "--unshare-ipc", + "--unshare-cgroup-try", + "--ro-bind", "/sys/block", "/sys/block", + "--ro-bind", "/sys/bus", "/sys/bus", + "--ro-bind", "/sys/class", "/sys/class", + "--ro-bind", "/sys/dev", "/sys/dev", + "--ro-bind", "/sys/devices", "/sys/devices", + "--bind", "usr", "/usr", + "--bind", "etc", "/etc", + "--bind", "var", "/var", + "--symlink", "/usr/lib", "/lib", + "--symlink", "/usr/lib32", "/lib32", + "--symlink", "/usr/lib64", "/lib64", + "--symlink", "/usr/bin", "/bin", + "--symlink", "/usr/sbin", "/sbin", + }; + static const gsize COMMON_ARGC = sizeof(COMMON_ARGV) / sizeof(*COMMON_ARGV); + + gsize i; + GPtrArray *args = g_ptr_array_sized_new(COMMON_ARGC + child_argc + 1); + g_autofree gchar **args_raw = NULL; + + for (i = 0; i < COMMON_ARGC; i++) + g_ptr_array_add(args, (gchar *)COMMON_ARGV[i]); + + for (i = 0; i < child_argc; i++) + g_ptr_array_add(args, (gchar *)child_argv[i]); + + g_ptr_array_add(args, NULL); + + args_raw = (gchar **)g_ptr_array_free(args, FALSE); + + return g_spawn_sync(deployment_path, args_raw, NULL, 0, NULL, NULL, + NULL, NULL, exit_status, error); +} + static gboolean sysroot_finalize_deployment (OstreeSysroot *self, OstreeDeployment *deployment, @@ -2866,6 +2919,17 @@ sysroot_finalize_deployment (OstreeSysroot *self, return FALSE; } + static const gchar * const SEMODULE_CMD[] = { + "semodule", "-N", "--rebuild-if-modules-changed" + }; + gint exit_status; + if (!run_in_deployment(deployment_path, SEMODULE_CMD, + sizeof(SEMODULE_CMD) / sizeof(*SEMODULE_CMD), + &exit_status, error)) + return FALSE; + if (exit_status != 0) + g_warning ("Failed to refresh SELinux policy - the policy contents may be inconsistent"); + const char *osdeploypath = glnx_strjoina ("ostree/deploy/", ostree_deployment_get_osname (deployment)); glnx_autofd int os_deploy_dfd = -1; if (!glnx_opendirat (self->sysroot_fd, osdeploypath, TRUE, &os_deploy_dfd, error))