From 81c08746c6ae3c83fc7903155546ed9851c2acce Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 2 Oct 2023 11:05:31 -0400 Subject: [PATCH] repo: Add an option to label /usr/etc as /etc This will be very useful for enabling a "transient /etc" option because we won't have to do hacks relabling in the initramfs, or forcing it on just for composefs. --- man/ostree-commit.xml | 8 ++++++++ src/libostree/ostree-repo-commit.c | 9 ++++++++- src/libostree/ostree-repo.h | 3 +++ src/ostree/ot-builtin-commit.c | 18 ++++++++++++++++++ .../destructive/itest-label-selinux.sh | 15 +++++++++++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/man/ostree-commit.xml b/man/ostree-commit.xml index 3e22b1723f..12f4fd10fa 100644 --- a/man/ostree-commit.xml +++ b/man/ostree-commit.xml @@ -184,6 +184,14 @@ License along with this library. If not, see . + + 0 | 1 + + + When SELinux labeling is enabled, epoch 1 ensures that /usr/etc is labeled as if it was /etc. + + + diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index c269142e72..d9fbb25104 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -3272,8 +3273,14 @@ get_final_xattrs (OstreeRepo *self, OstreeRepoCommitModifier *modifier, const ch if (modifier && modifier->sepolicy) { g_autofree char *label = NULL; + const char *path_for_labeling = relpath; - if (!ostree_sepolicy_get_label (modifier->sepolicy, relpath, + bool using_v1 = (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SELINUX_LABEL_V1) > 0; + bool is_usretc = g_str_equal (relpath, "/usr/etc") || g_str_has_prefix (relpath, "/usr/etc/"); + if (using_v1 && is_usretc) + path_for_labeling += strlen ("/usr"); + + if (!ostree_sepolicy_get_label (modifier->sepolicy, path_for_labeling, g_file_info_get_attribute_uint32 (file_info, "unix::mode"), &label, cancellable, error)) return FALSE; diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 2dea909223..73e62f5cd7 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -517,6 +517,8 @@ typedef OstreeRepoCommitFilterResult (*OstreeRepoCommitFilter) (OstreeRepo *repo * 2017.13 * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_DEVINO_CANONICAL: If a devino cache hit is found, skip * modifier filters (non-directories only); Since: 2017.14 + * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SELINUX_LABEL_V1: For SELinux and other systems, label + * /usr/etc as if it was /etc. * * Flags modifying commit behavior. In bare-user-only mode, * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS and @@ -532,6 +534,7 @@ typedef enum OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED = (1 << 3), OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CONSUME = (1 << 4), OSTREE_REPO_COMMIT_MODIFIER_FLAGS_DEVINO_CANONICAL = (1 << 5), + OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SELINUX_LABEL_V1 = (1 << 6), } OstreeRepoCommitModifierFlags; /** diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 98aa5f952a..0309e73f2a 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -54,6 +54,7 @@ static char *opt_tar_pathname_filter; static gboolean opt_no_xattrs; static char *opt_selinux_policy; static gboolean opt_selinux_policy_from_base; +static int opt_selinux_labeling_epoch; static gboolean opt_canonical_permissions; static gboolean opt_ro_executables; static gboolean opt_consume; @@ -134,6 +135,10 @@ static GOptionEntry options[] = { "Set SELinux labels based on policy in root filesystem PATH (may be /)", "PATH" }, { "selinux-policy-from-base", 'P', 0, G_OPTION_ARG_NONE, &opt_selinux_policy_from_base, "Set SELinux labels based on first --tree argument", NULL }, + { "selinux-labeling-epoch", 0, 0, G_OPTION_ARG_INT, &opt_selinux_labeling_epoch, + "Configure the default SELinux labeling rules; 0 is the default, 1 enables labeling /usr/etc " + "as /etc", + NULL }, { "link-checkout-speedup", 0, 0, G_OPTION_ARG_NONE, &opt_link_checkout_speedup, "Optimize for commits of trees composed of hardlinks into the repository", NULL }, { "devino-canonical", 'I', 0, G_OPTION_ARG_NONE, &opt_devino_canonical, @@ -597,6 +602,19 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS; if (opt_consume) flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CONSUME; + switch (opt_selinux_labeling_epoch) + { + case 0: + break; + case 1: + flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SELINUX_LABEL_V1; + break; + default: + { + glnx_throw (error, "Unknown SELinux labeling epoch: %d", opt_selinux_labeling_epoch); + goto out; + } + } if (opt_devino_canonical) { opt_link_checkout_speedup = TRUE; /* Imply this */ diff --git a/tests/kolainst/destructive/itest-label-selinux.sh b/tests/kolainst/destructive/itest-label-selinux.sh index 97b5cc5426..29444fbc8d 100755 --- a/tests/kolainst/destructive/itest-label-selinux.sh +++ b/tests/kolainst/destructive/itest-label-selinux.sh @@ -32,6 +32,21 @@ ostree refs --delete testbranch rm co -rf echo "ok commit with sepolicy" +ostree ls -X ${host_refspec} /usr/etc/sysctl.conf > ls.txt +if grep -qF ':etc_t:' ls.txt; then + ostree checkout -H ${host_refspec} co + ostree commit -b testbranch --link-checkout-speedup \ + --selinux-policy co --tree=dir=co --selinux-labeling-epoch=1 + ostree ls -X testbranch /usr/etc/sysctl.conf > ls.txt + assert_file_has_content ls.txt ':system_conf_t:' + rm co ls.txt -rf + ostree refs --delete testbranch +else + echo 'Already using --selinux-labeling-epoch > 0 on host, hopefully!' +fi + +echo "ok --selinux-labeling-epoch=1" + # Now let's check that selinux policy labels can be applied on checkout rm rootfs -rf