Lower initial SELinux policy load from compose to core

Add a `selinux` verb to treespec, and bind it from treefile.  If
set, use it in the core to load an initial policy before import,
if we didn't already set a policy.

In practice right now this is only used from the compose path
since the SysrootUpgrader uses the policy from the merge deployment.

Unset the policy if rojig mode is enabled.

Now, non-SELinux use cases are required to set `selinux: false`
in the treespec. For `ex container` I just set it in our example
specs.  Probably that should forcibly disable it in the
treespec but eh, it's experimental.

The other case I can think of is client-side layering; before
we would create a policy using the target root, but it
wasn't a *hard* requirement, i.e. we didn't error out if
`policy_get_name() == NULL`.  Let's preserve that semantic by
hooking off of whether `_new_system()` was used.

Prep for sharing code with `compose rojig`.

Closes: #1630
Approved by: jlebon
This commit is contained in:
Colin Walters 2018-10-15 12:10:16 -04:00 committed by Atomic Bot
parent 95c1ed3695
commit fca01e70b5
6 changed files with 40 additions and 15 deletions

View File

@ -245,7 +245,6 @@ install_packages (RpmOstreeTreeComposeContext *self,
/* For unified core, we have a pkgcache repo. This may be auto-created under
* the workdir, or live explicitly in the dir for --cache.
*/
glnx_autofd int host_rootfs_dfd = -1;
if (opt_unified_core)
{
self->pkgcache_repo = ostree_repo_create_at (cachedir_dfd (self), "pkgcache-repo",
@ -284,19 +283,6 @@ install_packages (RpmOstreeTreeComposeContext *self,
}
rpmostree_context_set_repos (self->corectx, self->repo, self->pkgcache_repo);
/* Ensure that the imported packages are labeled with *a* policy if
* possible, even if it's not the final one. This helps avoid duplicating
* all of the content.
*/
if (!glnx_opendirat (AT_FDCWD, "/", TRUE, &host_rootfs_dfd, error))
return FALSE;
g_autoptr(OstreeSePolicy) sepolicy = ostree_sepolicy_new_at (host_rootfs_dfd, cancellable, error);
if (!sepolicy)
return FALSE;
if (ostree_sepolicy_get_name (sepolicy) == NULL)
return glnx_throw (error, "Unable to load SELinux policy from /");
rpmostree_context_set_sepolicy (self->corectx, sepolicy);
}
if (!rpmostree_context_prepare (self->corectx, cancellable, error))

View File

@ -255,6 +255,8 @@ rpmostree_composeutil_get_treespec (RpmOstreeContext *ctx,
return FALSE;
if (!treespec_bind_bool (treedata, treespec, "recommends", TRUE, error))
return FALSE;
if (!treespec_bind_bool (treedata, treespec, "selinux", TRUE, error))
return FALSE;
if (!treespec_bind_array (treedata, treespec, "install-langs", "instlangs", FALSE, error))
return FALSE;
{ const char *releasever;

View File

@ -27,6 +27,8 @@
struct _RpmOstreeContext {
GObject parent;
/* Whether we were created with new_system() */
gboolean is_system;
RpmOstreeTreespec *spec;
gboolean empty;

View File

@ -289,6 +289,7 @@ rpmostree_treespec_new_from_keyfile (GKeyFile *keyfile,
tf_bind_boolean (keyfile, &builder, "documentation", TRUE);
tf_bind_boolean (keyfile, &builder, "recommends", TRUE);
tf_bind_boolean (keyfile, &builder, "selinux", TRUE);
ret->spec = g_variant_builder_end (&builder);
ret->dict = g_variant_dict_new (ret->spec);
@ -403,6 +404,7 @@ rpmostree_context_new_system (OstreeRepo *repo,
g_return_val_if_fail (repo != NULL, FALSE);
RpmOstreeContext *self = g_object_new (RPMOSTREE_TYPE_CONTEXT, NULL);
self->is_system = TRUE;
self->ostreerepo = g_object_ref (repo);
/* We can always be control-c'd at any time; this is new API,
@ -789,6 +791,33 @@ rpmostree_context_setup (RpmOstreeContext *self,
if (g_variant_dict_contains (self->spec->dict, "ignore-scripts"))
sd_journal_print (LOG_INFO, "ignore-scripts is no longer supported");
gboolean selinux;
g_assert (g_variant_dict_lookup (self->spec->dict, "selinux", "b", &selinux));
/* Load policy from / if SELinux is enabled, and we haven't already loaded
* a policy. This is mostly for the "compose tree" case.
*/
if (selinux && !self->sepolicy)
{
glnx_autofd int host_rootfs_dfd = -1;
/* Ensure that the imported packages are labeled with *a* policy if
* possible, even if it's not the final one. This helps avoid duplicating
* all of the content.
*/
if (!glnx_opendirat (AT_FDCWD, "/", TRUE, &host_rootfs_dfd, error))
return FALSE;
g_autoptr(OstreeSePolicy) sepolicy = ostree_sepolicy_new_at (host_rootfs_dfd, cancellable, error);
if (!sepolicy)
return FALSE;
/* For system contexts, whether SELinux required is dynamic based on the
* filesystem state. If the base compose doesn't have a policy package,
* then that's OK. It'd be cleaner if we loaded the no-SELinux state from
* the origin, but that'd be a backwards-incompatible change.
*/
if (!self->is_system && ostree_sepolicy_get_name (sepolicy) == NULL)
return glnx_throw (error, "Unable to load SELinux policy from /");
rpmostree_context_set_sepolicy (self, sepolicy);
}
return TRUE;
}
@ -1931,6 +1960,10 @@ rpmostree_context_prepare_rojig (RpmOstreeContext *self,
GError **error)
{
self->rojig_pure = TRUE;
/* Override the default policy load; rojig handles xattrs
* internally.
*/
rpmostree_context_set_sepolicy (self, NULL);
return rpmostree_context_prepare (self, cancellable, error);
}
@ -2295,7 +2328,6 @@ rpmostree_context_import_rojig (RpmOstreeContext *self,
OstreeRepo *repo = get_pkgcache_repo (self);
g_return_val_if_fail (repo != NULL, FALSE);
g_return_val_if_fail (rojig_pkg_to_xattrs == NULL || self->sepolicy == NULL, FALSE);
if (!dnf_transaction_import_keys (dnf_context_get_transaction (dnfctx), error))
return FALSE;

View File

@ -10,6 +10,7 @@ cat >bash.conf <<EOF
[tree]
ref=bash
packages=coreutils;bash;
selinux=false
repos=fedora;
releasever=28
EOF
@ -24,6 +25,7 @@ cat >bash-nodocs.conf <<EOF
[tree]
ref=bash-nodocs
packages=coreutils;bash;
selinux=false
repos=fedora;
releasever=28
documentation=false;

View File

@ -10,6 +10,7 @@ cat >httpd.conf <<EOF
[tree]
ref=httpd
packages=httpd;
selinux=false
repos=fedora;
releasever=28
EOF