[ostree/wip/selinux2] More SELinux rework
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree/wip/selinux2] More SELinux rework
- Date: Wed, 19 Feb 2014 03:41:39 +0000 (UTC)
commit 5f308f7b35dd3806134e318981f4b3904bc36870
Author: Colin Walters <walters verbum org>
Date: Fri Feb 14 12:39:39 2014 -0500
More SELinux rework
Right now, selinux/ just adds some overrides for the Fedora base. But
in the future we'll have a real ostree_t domain.
Also, add a public OstreeSePolicy API so that rpm-ostree can consume
the logic inside of here.
Makefile-libostree-defines.am | 1 +
Makefile-libostree.am | 1 +
Makefile.am | 4 +
configure.ac | 1 +
packaging/ostree.spec.in | 24 ++
selinux/.gitignore | 2 +
selinux/Makefile.am | 22 ++
selinux/ostree.fc | 9 +
selinux/ostree.if | 1 +
selinux/ostree.te | 33 +++
src/libostree/ostree-repo-commit.c | 121 +++++++--
src/libostree/ostree-repo.h | 4 +
src/libostree/ostree-sepolicy.c | 456 +++++++++++++++++++++++++++++++++
src/libostree/ostree-sepolicy.h | 66 +++++
src/libostree/ostree-sysroot-deploy.c | 363 +++++++--------------------
src/libostree/ostree-types.h | 1 +
16 files changed, 814 insertions(+), 295 deletions(-)
---
diff --git a/Makefile-libostree-defines.am b/Makefile-libostree-defines.am
index 6b07d0e..02037ed 100644
--- a/Makefile-libostree-defines.am
+++ b/Makefile-libostree-defines.am
@@ -27,6 +27,7 @@ libostree_public_headers = \
src/libostree/ostree-types.h \
src/libostree/ostree-repo-file.h \
src/libostree/ostree-diff.h \
+ src/libostree/ostree-sepolicy.h \
src/libostree/ostree-sysroot.h \
src/libostree/ostree-deployment.h \
src/libostree/ostree-bootconfig-parser.h \
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index 8e9aaca..04d03be 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -56,6 +56,7 @@ libostree_1_la_SOURCES = \
src/libostree/ostree-repo-file.c \
src/libostree/ostree-repo-file-enumerator.c \
src/libostree/ostree-repo-file-enumerator.h \
+ src/libostree/ostree-sepolicy.c \
src/libostree/ostree-sysroot-private.h \
src/libostree/ostree-sysroot.c \
src/libostree/ostree-sysroot-cleanup.c \
diff --git a/Makefile.am b/Makefile.am
index b20738a..803ce0a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,6 +31,10 @@ endif
SUBDIRS += .
+if USE_SELINUX
+SUBDIRS += selinux
+endif
+
if ENABLE_GTK_DOC
SUBDIRS += doc
endif
diff --git a/configure.ac b/configure.ac
index 542c9ff..d3c72d7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -203,6 +203,7 @@ AC_CONFIG_FILES([
Makefile
embedded-dependencies/Makefile
doc/Makefile
+selinux/Makefile
src/libostree/ostree-1.pc
])
AC_OUTPUT
diff --git a/packaging/ostree.spec.in b/packaging/ostree.spec.in
index c2596d2..105b0ae 100644
--- a/packaging/ostree.spec.in
+++ b/packaging/ostree.spec.in
@@ -44,6 +44,19 @@ Requires: %{name} = %{version}-%{release}
%description devel
The %{name}-devel package includes the header files for the %{name} library.
+%package selinux
+Summary: SELinux policy module for %{name}
+Group: System Environment/Base
+Requires: %{name} = %{version}-%{release}
+Requires: policycoreutils, libselinux-utils
+Requires(post): selinux-policy-base, policycoreutils
+Requires(postun): policycoreutils
+BuildRequires: selinux-policy-devel
+BuildArch: noarch
+
+%description selinux
+This package installs and sets up the SELinux policy security module for %{name}.
+
%prep
%setup -q -n ostree-%{version}
@@ -69,6 +82,14 @@ rm -rf $RPM_BUILD_ROOT
%preun
%systemd_preun ostree-remount.service
+%post selinux
+semodule -n -i %{_datadir}/selinux/packages/%{name}.pp
+
+%postun selinux
+if [ $1 -eq 0 ]; then
+ semodule -n -r %{name}
+fi
+
%files
%doc COPYING README.md
%{_bindir}/ostree
@@ -91,3 +112,6 @@ rm -rf $RPM_BUILD_ROOT
%dir %{_datadir}/gtk-doc/html/ostree
%{_datadir}/gtk-doc/html/ostree
%{_datadir}/gir-1.0/OSTree-1.0.gir
+
+%files selinux
+%attr(0600,root,root) %{_datadir}/selinux/packages/%{name}.pp
diff --git a/selinux/.gitignore b/selinux/.gitignore
new file mode 100644
index 0000000..cbefb9d
--- /dev/null
+++ b/selinux/.gitignore
@@ -0,0 +1,2 @@
+ostree.pp
+tmp
diff --git a/selinux/Makefile.am b/selinux/Makefile.am
new file mode 100644
index 0000000..1d69949
--- /dev/null
+++ b/selinux/Makefile.am
@@ -0,0 +1,22 @@
+# Copyright (C) 2014 Colin Walters <walters verbum org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+ostree.pp: ostree.fc ostree.if ostree.te
+ make -f /usr/share/selinux/devel/Makefile
+
+selinuxpkgdir = $(datadir)/selinux/packages
+selinuxpkg_DATA = ostree.pp
diff --git a/selinux/ostree.fc b/selinux/ostree.fc
new file mode 100644
index 0000000..56b9c4f
--- /dev/null
+++ b/selinux/ostree.fc
@@ -0,0 +1,9 @@
+# Core definitions
+
+/sysroot -d gen_context(system_u:object_r:usr_t,s0)
+/ostree -d gen_context(system_u:object_r:usr_t,s0)
+/ostree -l gen_context(system_u:object_r:usr_t,s0)
+/media -l gen_context(system_u:object_r:mnt_t,s0)
+/mnt -l gen_context(system_u:object_r:mnt_t,s0)
+/var/roothome -d gen_context(system_u:object_r:admin_home_t,s0)
+/var/home -d gen_context(system_u:object_r:home_root_t,s0)
diff --git a/selinux/ostree.if b/selinux/ostree.if
new file mode 100644
index 0000000..996cee9
--- /dev/null
+++ b/selinux/ostree.if
@@ -0,0 +1 @@
+# Empty.
diff --git a/selinux/ostree.te b/selinux/ostree.te
new file mode 100644
index 0000000..8d34940
--- /dev/null
+++ b/selinux/ostree.te
@@ -0,0 +1,33 @@
+policy_module(ostree, 1.3.0)
+
+require {
+ type init_t;
+ type root_t;
+ type var_log_t;
+ type games_data_t;
+ type var_yp_t;
+ type systemd_tmpfiles_t;
+ type local_login_t;
+ type admin_home_t;
+ type ldconfig_cache_t;
+ type var_t;
+ type var_run_t;
+ class lnk_file { relabelfrom relabelto read getattr };
+ class dir { relabelfrom relabelto create setattr write };
+}
+
+# init_t
+allow init_t admin_home_t:lnk_file { read getattr };
+allow init_t root_t:dir { write };
+
+#============= systemd_tmpfiles_t ==============
+allow systemd_tmpfiles_t games_data_t:dir relabelto;
+allow systemd_tmpfiles_t var_log_t:dir create;
+allow systemd_tmpfiles_t var_run_t:lnk_file { relabelfrom relabelto };
+allow systemd_tmpfiles_t var_t:dir { create relabelfrom relabelto setattr };
+allow systemd_tmpfiles_t var_yp_t:dir relabelto;
+allow systemd_tmpfiles_t ldconfig_cache_t:dir { relabelfrom relabelto setattr };
+allow systemd_tmpfiles_t var_t:dir { relabelfrom relabelto setattr };
+
+#============= local_login_t ==============
+allow local_login_t admin_home_t:lnk_file read;
diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c
index 10d3971..1b3136d 100644
--- a/src/libostree/ostree-repo-commit.c
+++ b/src/libostree/ostree-repo-commit.c
@@ -1618,6 +1618,8 @@ struct OstreeRepoCommitModifier {
OstreeRepoCommitModifierXattrCallback xattr_callback;
GDestroyNotify xattr_destroy;
gpointer xattr_user_data;
+
+ OstreeSePolicy *sepolicy;
};
OstreeRepoCommitFilterResult
@@ -1684,6 +1686,67 @@ apply_commit_filter (OstreeRepo *self,
}
static gboolean
+get_modified_xattrs (OstreeRepo *self,
+ OstreeRepoCommitModifier *modifier,
+ const char *relpath,
+ GFileInfo *file_info,
+ GFile *path,
+ GVariant **out_xattrs,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_variant GVariant *ret_xattrs = NULL;
+
+ if (modifier && modifier->xattr_callback)
+ {
+ ret_xattrs = modifier->xattr_callback (self, relpath, file_info,
+ modifier->xattr_user_data);
+ }
+ else if (!(modifier && (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS) > 0))
+ {
+ if (!gs_file_get_all_xattrs (path, &ret_xattrs, cancellable, error))
+ goto out;
+ }
+
+ if (modifier->sepolicy)
+ {
+ gs_free char *label = NULL;
+
+ if (!ostree_sepolicy_get_label (modifier->sepolicy, relpath,
+ g_file_info_get_attribute_uint32 (file_info, "unix::mode"),
+ &label, cancellable, error))
+ goto out;
+
+ if (label)
+ {
+ GVariantBuilder *builder;
+
+ if (ret_xattrs)
+ builder = ot_util_variant_builder_from_variant (ret_xattrs,
+ G_VARIANT_TYPE ("a(ayay)"));
+ else
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ayay)"));
+
+ g_variant_builder_add_value (builder,
+ g_variant_new ("(@ay ay)",
+ g_variant_new_bytestring ("security.selinux"),
+ g_variant_new_bytestring (label)));
+ if (ret_xattrs)
+ g_variant_unref (ret_xattrs);
+
+ ret_xattrs = g_variant_builder_end (builder);
+ g_variant_ref_sink (ret_xattrs);
+ }
+ }
+
+ ret = TRUE;
+ gs_transfer_out_value (out_xattrs, &ret_xattrs);
+ out:
+ return ret;
+}
+
+static gboolean
write_directory_to_mtree_internal (OstreeRepo *self,
GFile *dir,
OstreeMutableTree *mtree,
@@ -1751,16 +1814,10 @@ write_directory_to_mtree_internal (OstreeRepo *self,
if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW)
{
g_debug ("Adding: %s", gs_file_get_path_cached (dir));
- if (modifier && modifier->xattr_callback)
- {
- xattrs = modifier->xattr_callback (self, relpath, child_info,
- modifier->xattr_user_data);
- }
- else if (!(modifier && (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS) > 0))
- {
- if (!gs_file_get_all_xattrs (dir, &xattrs, cancellable, error))
- goto out;
- }
+ if (!get_modified_xattrs (self, modifier, relpath, child_info, dir,
+ &xattrs,
+ cancellable, error))
+ goto out;
if (!_ostree_repo_write_directory_meta (self, modified_info, xattrs, &child_file_csum,
cancellable, error))
@@ -1872,17 +1929,11 @@ write_directory_to_mtree_internal (OstreeRepo *self,
goto out;
}
- if (modifier && modifier->xattr_callback)
- {
- xattrs = modifier->xattr_callback (self, child_relpath, child_info,
- modifier->xattr_user_data);
- }
- else if (!(modifier && (modifier->flags &
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS) > 0))
- {
- g_clear_pointer (&xattrs, (GDestroyNotify) g_variant_unref);
- if (!gs_file_get_all_xattrs (child, &xattrs, cancellable, error))
- goto out;
- }
+ if (!get_modified_xattrs (self, modifier,
+ child_relpath, child_info, child,
+ &xattrs,
+ cancellable, error))
+ goto out;
if (!ostree_raw_file_to_content_stream (file_input,
modified_info, xattrs,
@@ -2082,6 +2133,8 @@ ostree_repo_commit_modifier_unref (OstreeRepoCommitModifier *modifier)
if (modifier->xattr_destroy)
modifier->xattr_destroy (modifier->xattr_user_data);
+ g_clear_object (&modifier->sepolicy);
+
g_free (modifier);
return;
}
@@ -2094,8 +2147,9 @@ ostree_repo_commit_modifier_unref (OstreeRepoCommitModifier *modifier)
* @user_data: Data for @callback:
*
* If set, this function should return extended attributes to use for
- * the given path. This is useful for things like SELinux, where a build
- * system can label the files as it's committing to the repository.
+ * the given path. This is useful for things like ACLs and SELinux,
+ * where a build system can label the files as it's committing to the
+ * repository.
*/
void
ostree_repo_commit_modifier_set_xattr_callback (OstreeRepoCommitModifier *modifier,
@@ -2108,6 +2162,27 @@ ostree_repo_commit_modifier_set_xattr_callback (OstreeRepoCommitModifier *modif
modifier->xattr_user_data = user_data;
}
+/**
+ * ostree_repo_commit_modifier_set_sepolicy:
+ * @modifier: An #OstreeRepoCommitModifier
+ * @sepolicy: (allow-none): Policy to use for labeling
+ *
+ * If @policy is non-%NULL, use it to look up labels to use for
+ * "security.selinux" extended attributes.
+ *
+ * Note that any policy specified this way operates in addition to any
+ * extended attributes provided via
+ * ostree_repo_commit_modifier_set_xattr_callback(). However if both
+ * specify a value for "security.selinux", then the one from the
+ * policy wins.
+ */
+void
+ostree_repo_commit_modifier_set_sepolicy (OstreeRepoCommitModifier *modifier,
+ OstreeSePolicy *sepolicy)
+{
+ g_clear_object (&modifier->sepolicy);
+ modifier->sepolicy = sepolicy ? g_object_ref (sepolicy) : NULL;
+}
G_DEFINE_BOXED_TYPE(OstreeRepoCommitModifier, ostree_repo_commit_modifier,
ostree_repo_commit_modifier_ref,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index df7f3e0..ad6533a 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -25,6 +25,7 @@
#include "ostree-core.h"
#include "ostree-types.h"
#include "ostree-async-progress.h"
+#include "ostree-sepolicy.h"
G_BEGIN_DECLS
@@ -313,6 +314,9 @@ void ostree_repo_commit_modifier_set_xattr_callback (OstreeRepoCommitModifier
GDestroyNotify destroy,
gpointer user_data);
+void ostree_repo_commit_modifier_set_sepolicy (OstreeRepoCommitModifier *modifier,
+ OstreeSePolicy *sepolicy);
+
OstreeRepoCommitModifier *ostree_repo_commit_modifier_ref (OstreeRepoCommitModifier *modifier);
void ostree_repo_commit_modifier_unref (OstreeRepoCommitModifier *modifier);
diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c
new file mode 100644
index 0000000..8a0457a
--- /dev/null
+++ b/src/libostree/ostree-sepolicy.c
@@ -0,0 +1,456 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters verbum org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#endif
+
+#include "otutil.h"
+#include "libgsystem.h"
+
+#include "ostree-sepolicy.h"
+#include "ostree-bootloader-uboot.h"
+#include "ostree-bootloader-syslinux.h"
+
+/**
+ * SECTION:libostree-sepolicy
+ * @title: SELinux policy management
+ * @short_description: Read SELinux policy and manage filesystem labels
+ *
+ * A #OstreeSePolicy object can load the SELinux policy from a given
+ * root and perform labeling.
+ */
+struct OstreeSePolicy {
+ GObject parent;
+
+ GFile *path;
+
+#ifdef HAVE_SELINUX
+ GFile *selinux_policy_root;
+ struct selabel_handle *selinux_hnd;
+ char *selinux_policy_name;
+#endif
+};
+
+typedef struct {
+ GObjectClass parent_class;
+} OstreeSePolicyClass;
+
+static void initable_iface_init (GInitableIface *initable_iface);
+
+enum {
+ PROP_0,
+
+ PROP_PATH
+};
+
+G_DEFINE_TYPE_WITH_CODE (OstreeSePolicy, ostree_sepolicy, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
+
+static void
+ostree_sepolicy_finalize (GObject *object)
+{
+ OstreeSePolicy *self = OSTREE_SEPOLICY (object);
+
+ g_clear_object (&self->path);
+ g_clear_object (&self->selinux_policy_root);
+ g_clear_pointer (&self->selinux_policy_name, g_free);
+#ifdef HAVE_SELINUX
+ if (self->selinux_hnd)
+ {
+ selabel_close (self->selinux_hnd);
+ self->selinux_hnd = NULL;
+ }
+#endif
+
+ G_OBJECT_CLASS (ostree_sepolicy_parent_class)->finalize (object);
+}
+
+static void
+ostree_sepolicy_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ OstreeSePolicy *self = OSTREE_SEPOLICY (object);
+
+ switch (prop_id)
+ {
+ case PROP_PATH:
+ /* Canonicalize */
+ self->path = g_file_new_for_path (gs_file_get_path_cached (g_value_get_object (value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ostree_sepolicy_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ OstreeSePolicy *self = OSTREE_SEPOLICY (object);
+
+ switch (prop_id)
+ {
+ case PROP_PATH:
+ g_value_set_object (value, self->path);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ostree_sepolicy_constructed (GObject *object)
+{
+ OstreeSePolicy *self = OSTREE_SEPOLICY (object);
+
+ g_assert (self->path != NULL);
+
+ G_OBJECT_CLASS (ostree_sepolicy_parent_class)->constructed (object);
+}
+
+static void
+ostree_sepolicy_class_init (OstreeSePolicyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = ostree_sepolicy_constructed;
+ object_class->get_property = ostree_sepolicy_get_property;
+ object_class->set_property = ostree_sepolicy_set_property;
+ object_class->finalize = ostree_sepolicy_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_PATH,
+ g_param_spec_object ("path",
+ "",
+ "",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static gboolean
+initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+#ifdef HAVE_SELINUX
+ gboolean ret = FALSE;
+ OstreeSePolicy *self = OSTREE_SEPOLICY (initable);
+ gs_unref_object GFile *etc_selinux_dir = NULL;
+ gs_unref_object GFile *policy_config_path = NULL;
+ gs_unref_object GFile *policy_root = NULL;
+ gs_unref_object GFileInputStream *filein = NULL;
+ gs_unref_object GDataInputStream *datain = NULL;
+ gboolean enabled = FALSE;
+ char *policytype = NULL;
+ const char *selinux_prefix = "SELINUX=";
+ const char *selinuxtype_prefix = "SELINUXTYPE=";
+
+ etc_selinux_dir = g_file_resolve_relative_path (self->path, "etc/selinux");
+ if (!g_file_query_exists (etc_selinux_dir, NULL))
+ {
+ g_object_unref (etc_selinux_dir);
+ etc_selinux_dir = g_file_resolve_relative_path (self->path, "usr/etc/selinux");
+ }
+ policy_config_path = g_file_get_child (etc_selinux_dir, "config");
+
+ if (g_file_query_exists (policy_config_path, NULL))
+ {
+ filein = g_file_read (policy_config_path, cancellable, error);
+ if (!filein)
+ goto out;
+
+ datain = g_data_input_stream_new ((GInputStream*)filein);
+
+ while (TRUE)
+ {
+ gsize len;
+ GError *temp_error = NULL;
+ gs_free char *line = g_data_input_stream_read_line_utf8 (datain, &len,
+ cancellable, &temp_error);
+
+ if (temp_error)
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+
+ if (!line)
+ break;
+
+ if (g_str_has_prefix (line, selinuxtype_prefix))
+ {
+ policytype = g_strstrip (g_strdup (line + strlen (selinuxtype_prefix)));
+ policy_root = g_file_get_child (etc_selinux_dir, policytype);
+ }
+ else if (g_str_has_prefix (line, selinux_prefix))
+ {
+ const char *enabled_str = line + strlen (selinux_prefix);
+ if (g_ascii_strncasecmp (enabled_str, "enforcing", strlen ("enforcing")) == 0 ||
+ g_ascii_strncasecmp (enabled_str, "permissive", strlen ("permissive")) == 0)
+ enabled = TRUE;
+ }
+ }
+ }
+
+ if (enabled)
+ {
+ g_setenv ("LIBSELINUX_DISABLE_PCRE_PRECOMPILED", "1", FALSE);
+ if (selinux_set_policy_root (gs_file_get_path_cached (policy_root)) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "selinux_set_policy_root(%s): %s",
+ gs_file_get_path_cached (etc_selinux_dir),
+ strerror (errno));
+ goto out;
+ }
+
+ self->selinux_hnd = selabel_open (SELABEL_CTX_FILE, NULL, 0);
+ if (!self->selinux_hnd)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "With policy root '%s': selabel_open(SELABEL_CTX_FILE): %s",
+ gs_file_get_path_cached (etc_selinux_dir),
+ strerror (errno));
+ goto out;
+ }
+
+ {
+ char *con = NULL;
+ if (selabel_lookup_raw (self->selinux_hnd, &con, "/", 0755) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "With policy root '%s': Failed to look up context of /: %s",
+ gs_file_get_path_cached (etc_selinux_dir),
+ strerror (errno));
+ goto out;
+ }
+ freecon (con);
+ }
+
+ self->selinux_policy_name = g_strdup (policytype);
+ self->selinux_policy_root = g_object_ref (etc_selinux_dir);
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+#else
+ return TRUE;
+#endif
+}
+
+static void
+ostree_sepolicy_init (OstreeSePolicy *self)
+{
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+ initable_iface->init = initable_init;
+}
+
+/**
+ * ostree_sepolicy_new:
+ * @path: Path to a root directory
+ *
+ * Returns: (transfer full): An accessor object for SELinux policy in root located at @path
+ */
+OstreeSePolicy*
+ostree_sepolicy_new (GFile *path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_initable_new (OSTREE_TYPE_SEPOLICY, cancellable, error, "path", path, NULL);
+}
+
+/**
+ * ostree_sepolicy_get_path:
+ * @self:
+ *
+ * Returns: (transfer none): Path to rootfs
+ */
+GFile *
+ostree_sepolicy_get_path (OstreeSePolicy *self)
+{
+ return self->path;
+}
+
+const char *
+ostree_sepolicy_get_name (OstreeSePolicy *self)
+{
+#ifdef HAVE_SELINUX
+ return self->selinux_policy_name;
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * ostree_sepolicy_get_label:
+ * @self: Self
+ * @relpath: Path
+ * @unix_mode: Unix mode
+ * @out_label: (allow-none) (out) (transfer full): Return location for security context
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Store in @out_label the security context for the given @relpath and
+ * mode @unix_mode. If the policy does not specify a label, %NULL
+ * will be returned.
+ */
+gboolean
+ostree_sepolicy_get_label (OstreeSePolicy *self,
+ const char *relpath,
+ guint32 unix_mode,
+ char **out_label,
+ GCancellable *cancellable,
+ GError **error)
+{
+#ifdef HAVE_SELINUX
+ gboolean ret = FALSE;
+ int res;
+ char *con = NULL;
+
+ if (self->selinux_hnd)
+ {
+ res = selabel_lookup_raw (self->selinux_hnd, &con, relpath, unix_mode);
+ if (res != 0)
+ {
+ int errsv = errno;
+ if (errsv != ENOENT)
+ {
+ ot_util_set_error_from_errno (error, errsv);
+ goto out;
+ }
+ }
+ else
+ {
+ /* Ensure we consistently allocate with g_malloc */
+ *out_label = g_strdup (con);
+ freecon (con);
+ }
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+#else
+ return TRUE;
+#endif
+}
+
+/**
+ * ostree_sepolicy_restorecon:
+ * @self: Self
+ * @path: Path string to use for policy lookup
+ * @info: (allow-none): File attributes
+ * @target: Physical path to target file
+ * @flags: Flags controlling behavior
+ * @out_new_label: (allow-none) (out): New label, or %NULL if unchanged
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Reset the security context of @target based on the SELinux policy.
+ */
+gboolean
+ostree_sepolicy_restorecon (OstreeSePolicy *self,
+ const char *path,
+ GFileInfo *info,
+ GFile *target,
+ OstreeSePolicyRestoreconFlags flags,
+ char **out_new_label,
+ GCancellable *cancellable,
+ GError **error)
+{
+#ifdef HAVE_SELINUX
+ gboolean ret = FALSE;
+ gs_unref_object GFileInfo *src_info = NULL;
+ gs_free char *label = NULL;
+ gboolean do_relabel = TRUE;
+
+ if (info != NULL)
+ src_info = g_object_ref (info);
+ else
+ {
+ src_info = g_file_query_info (target, "unix::mode",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!src_info)
+ goto out;
+ }
+
+ if (flags & OSTREE_SEPOLICY_RESTORECON_FLAGS_KEEP_EXISTING)
+ {
+ char *existing_con = NULL;
+ if (lgetfilecon_raw (gs_file_get_path_cached (target), &existing_con) > 0
+ && existing_con)
+ {
+ do_relabel = FALSE;
+ freecon (existing_con);
+ }
+ }
+
+ if (do_relabel)
+ {
+ if (!ostree_sepolicy_get_label (self, path,
+ g_file_info_get_attribute_uint32 (src_info, "unix::mode"),
+ &label,
+ cancellable, error))
+ goto out;
+
+ if (!label)
+ {
+ if (!(flags & OSTREE_SEPOLICY_RESTORECON_FLAGS_ALLOW_NOLABEL))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No label found for '%s'", path);
+ goto out;
+ }
+ }
+ else
+ {
+ int res = lsetfilecon (gs_file_get_path_cached (target), label);
+ if (res != 0)
+ {
+ ot_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+ }
+ }
+
+ ret = TRUE;
+ gs_transfer_out_value (out_new_label, &label);
+ out:
+ return ret;
+#else
+ return TRUE;
+#endif
+}
diff --git a/src/libostree/ostree-sepolicy.h b/src/libostree/ostree-sepolicy.h
new file mode 100644
index 0000000..19a067e
--- /dev/null
+++ b/src/libostree/ostree-sepolicy.h
@@ -0,0 +1,66 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters verbum org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include "ostree-types.h"
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_SEPOLICY ostree_sepolicy_get_type()
+#define OSTREE_SEPOLICY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSTREE_TYPE_SEPOLICY, OstreeSePolicy))
+#define OSTREE_IS_SEPOLICY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSTREE_TYPE_SEPOLICY))
+
+GType ostree_sepolicy_get_type (void);
+
+OstreeSePolicy* ostree_sepolicy_new (GFile *path,
+ GCancellable *cancellable,
+ GError **error);
+
+GFile * ostree_sepolicy_get_path (OstreeSePolicy *self);
+
+const char *ostree_sepolicy_get_name (OstreeSePolicy *self);
+
+gboolean ostree_sepolicy_get_label (OstreeSePolicy *self,
+ const char *relpath,
+ guint32 unix_mode,
+ char **out_label,
+ GCancellable *cancellable,
+ GError **error);
+
+typedef enum {
+ OSTREE_SEPOLICY_RESTORECON_FLAGS_NONE,
+ OSTREE_SEPOLICY_RESTORECON_FLAGS_ALLOW_NOLABEL = (1 << 0),
+ OSTREE_SEPOLICY_RESTORECON_FLAGS_KEEP_EXISTING = (1 << 1)
+} OstreeSePolicyRestoreconFlags;
+
+gboolean ostree_sepolicy_restorecon (OstreeSePolicy *self,
+ const char *path,
+ GFileInfo *info,
+ GFile *target,
+ OstreeSePolicyRestoreconFlags flags,
+ char **out_new_label,
+ GCancellable *cancellable,
+ GError **error);
+
+G_END_DECLS
+
diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c
index aa55db2..f5ee56f 100644
--- a/src/libostree/ostree-sysroot-deploy.c
+++ b/src/libostree/ostree-sysroot-deploy.c
@@ -1,6 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
- * Copyright (C) 2012 Colin Walters <walters verbum org>
+ * Copyright (C) 2012,2014 Colin Walters <walters verbum org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,17 +16,10 @@
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
- *
- * Author: Colin Walters <walters verbum org>
*/
#include "config.h"
-#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-#endif
-
#include "ostree-sysroot-private.h"
#include "ostree-core-private.h"
#include "otutil.h"
@@ -243,74 +236,6 @@ checkout_deployment_tree (OstreeSysroot *sysroot,
return ret;
}
-#ifdef HAVE_SELINUX
-static gboolean
-get_selinux_policy_root (GFile *deployment_etc,
- GFile **out_policy_root,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFile *etc_selinux_dir = NULL;
- gs_unref_object GFile *policy_config_path = NULL;
- gs_unref_object GFile *ret_policy_root = NULL;
- gs_unref_object GFileInputStream *filein = NULL;
- gs_unref_object GDataInputStream *datain = NULL;
- gboolean enabled = FALSE;
- char *policytype = NULL;
- const char *selinux_prefix = "SELINUX=";
- const char *selinuxtype_prefix = "SELINUXTYPE=";
-
- etc_selinux_dir = g_file_get_child (deployment_etc, "selinux");
- policy_config_path = g_file_get_child (etc_selinux_dir, "config");
-
- if (g_file_query_exists (policy_config_path, NULL))
- {
- filein = g_file_read (policy_config_path, cancellable, error);
- if (!filein)
- goto out;
-
- datain = g_data_input_stream_new ((GInputStream*)filein);
-
- while (TRUE)
- {
- gsize len;
- GError *temp_error = NULL;
- gs_free char *line = g_data_input_stream_read_line_utf8 (datain, &len,
- cancellable, &temp_error);
-
- if (temp_error)
- {
- g_propagate_error (error, temp_error);
- goto out;
- }
-
- if (!line)
- break;
-
- if (g_str_has_prefix (line, selinuxtype_prefix))
- {
- policytype = g_strstrip (g_strdup (line + strlen (selinuxtype_prefix)));
- }
- else if (g_str_has_prefix (line, selinux_prefix))
- {
- const char *enabled_str = line + strlen (selinux_prefix);
- if (g_ascii_strncasecmp (enabled_str, "enforcing", strlen ("enforcing")) == 0 ||
- g_ascii_strncasecmp (enabled_str, "permissive", strlen ("permissive")) == 0)
- enabled = TRUE;
- }
- }
- }
-
- if (enabled)
- ret_policy_root = g_file_get_child (etc_selinux_dir, policytype);
-
- ret = TRUE;
- gs_transfer_out_value (out_policy_root, &ret_policy_root);
- out:
- return ret;
-}
-
static char *
ptrarray_path_join (GPtrArray *path)
{
@@ -336,69 +261,43 @@ ptrarray_path_join (GPtrArray *path)
}
static gboolean
-relabel_one_path (GFile *path,
+relabel_one_path (OstreeSysroot *sysroot,
+ OstreeSePolicy *sepolicy,
+ GFile *path,
GFileInfo *info,
GPtrArray *path_parts,
- struct selabel_handle *hnd,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
- guint32 mode;
gs_free char *relpath = NULL;
- char *con = NULL;
-
- mode = g_file_info_get_attribute_uint32 (info, "unix::mode");
relpath = ptrarray_path_join (path_parts);
-
- if (selabel_lookup_raw (hnd, &con, relpath, mode) != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "selabel_lookup_raw(%s, %u): %s",
- relpath, mode, strerror (errno));
- goto out;
- }
-
- if (S_ISLNK (mode))
- {
- if (lsetfilecon (gs_file_get_path_cached (path), con) != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "lsetfilecon(%s): %s",
- gs_file_get_path_cached (path), strerror (errno));
- goto out;
- }
- }
- else
- {
- if (setfilecon (gs_file_get_path_cached (path), con) != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "setfilecon(%s): %s",
- gs_file_get_path_cached (path), strerror (errno));
- goto out;
- }
- }
+ if (!ostree_sepolicy_restorecon (sepolicy, relpath,
+ info, path,
+ OSTREE_SEPOLICY_RESTORECON_FLAGS_ALLOW_NOLABEL,
+ NULL,
+ cancellable, error))
+ goto out;
ret = TRUE;
out:
- if (con) freecon (con);
return ret;
}
static gboolean
-relabel_recursively (GFile *dir,
+relabel_recursively (OstreeSysroot *sysroot,
+ OstreeSePolicy *sepolicy,
+ GFile *dir,
GFileInfo *dir_info,
GPtrArray *path_parts,
- struct selabel_handle *hnd,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object GFileEnumerator *direnum = NULL;
- if (!relabel_one_path (dir, dir_info, path_parts, hnd,
+ if (!relabel_one_path (sysroot, sepolicy, dir, dir_info, path_parts,
cancellable, error))
goto out;
@@ -425,13 +324,13 @@ relabel_recursively (GFile *dir,
ftype = g_file_info_get_file_type (file_info);
if (ftype == G_FILE_TYPE_DIRECTORY)
{
- if (!relabel_recursively (child, file_info, path_parts, hnd,
+ if (!relabel_recursively (sysroot, sepolicy, child, file_info, path_parts,
cancellable, error))
goto out;
}
else
{
- if (!relabel_one_path (child, file_info, path_parts, hnd,
+ if (!relabel_one_path (sysroot, sepolicy, child, file_info, path_parts,
cancellable, error))
goto out;
}
@@ -444,202 +343,116 @@ relabel_recursively (GFile *dir,
return ret;
}
-#endif
-
-typedef struct {
- gboolean have_policy;
-#ifdef HAVE_SELINUX
- struct selabel_handle *hnd;
-#endif
-} OstreeLabelingContext;
-
-static gboolean
-init_labeling_context (GFile *deployment_etc,
- OstreeLabelingContext *secontext,
- GCancellable *cancellable,
- GError **error)
-{
-#ifdef HAVE_SELINUX
- gboolean ret = FALSE;
- gs_unref_object GFile *policy_root = NULL;
-
- if (!get_selinux_policy_root (deployment_etc, &policy_root,
- cancellable, error))
- goto out;
-
- if (policy_root)
- {
- secontext->have_policy = TRUE;
-
- g_print ("ostadmin: Using SELinux policy '%s'\n", gs_file_get_basename_cached (policy_root));
-
- if (selinux_set_policy_root (gs_file_get_path_cached (policy_root)) != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "selinux_set_policy_root(%s): %s",
- gs_file_get_path_cached (policy_root),
- strerror (errno));
- goto out;
- }
- secontext->hnd = selabel_open (SELABEL_CTX_FILE, NULL, 0);
- if (!secontext->hnd)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "selabel_open(SELABEL_CTX_FILE): %s",
- strerror (errno));
- goto out;
- }
- }
- else
- secontext->have_policy = FALSE;
-
- ret = TRUE;
- out:
- return ret;
-#else
- secontext->have_policy = FALSE;
- return TRUE;
-#endif
-}
-
-static void
-ostree_labeling_context_cleanup (OstreeLabelingContext *secontext)
-{
-#ifdef HAVE_SELINUX
- if (secontext->hnd)
- selabel_close (secontext->hnd);
-#endif
-}
-
static gboolean
selinux_relabel_dir (OstreeSysroot *sysroot,
- OstreeLabelingContext *secontext,
+ OstreeSePolicy *sepolicy,
GFile *dir,
const char *prefix,
GCancellable *cancellable,
GError **error)
{
-#ifdef HAVE_SELINUX
gboolean ret = FALSE;
gs_unref_ptrarray GPtrArray *path_parts = g_ptr_array_new ();
gs_unref_object GFileInfo *root_info = NULL;
- if (secontext->have_policy)
+ root_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!root_info)
+ goto out;
+
+ g_ptr_array_add (path_parts, (char*)prefix);
+ if (!relabel_recursively (sysroot, sepolicy, dir, root_info, path_parts,
+ cancellable, error))
{
- root_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, error);
- if (!root_info)
- goto out;
-
- g_ptr_array_add (path_parts, (char*)prefix);
- if (!relabel_recursively (dir, root_info, path_parts, secontext->hnd,
- cancellable, error))
- {
- g_prefix_error (error, "Relabeling /%s: ", prefix);
- goto out;
- }
+ g_prefix_error (error, "Relabeling /%s: ", prefix);
+ goto out;
}
ret = TRUE;
out:
return ret;
-#else
- return TRUE;
-#endif
}
-#ifdef HAVE_SELINUX
static gboolean
-selinux_relabel_file (OstreeLabelingContext *secontext,
+selinux_relabel_file (OstreeSysroot *sysroot,
+ OstreeSePolicy *sepolicy,
GFile *path,
const char *prefix,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
+ gs_unref_ptrarray GPtrArray *path_parts = g_ptr_array_new ();
+ gs_unref_object GFileInfo *file_info = g_file_query_info (path, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!file_info)
+ goto out;
- if (secontext->have_policy)
+ g_ptr_array_add (path_parts, (char*)prefix);
+ g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (path));
+ if (!relabel_one_path (sysroot, sepolicy, path, file_info, path_parts,
+ cancellable, error))
{
- gs_unref_ptrarray GPtrArray *path_parts = g_ptr_array_new ();
- gs_unref_object GFileInfo *file_info = g_file_query_info (path, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, error);
- if (!file_info)
- goto out;
-
- g_ptr_array_add (path_parts, (char*)prefix);
- g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (path));
- if (!relabel_one_path (path, file_info, path_parts, secontext->hnd,
- cancellable, error))
- {
- g_prefix_error (error, "Relabeling /%s/%s: ", prefix,
- gs_file_get_basename_cached (path));
- goto out;
- }
+ g_prefix_error (error, "Relabeling /%s/%s: ", prefix,
+ gs_file_get_basename_cached (path));
+ goto out;
}
ret = TRUE;
out:
return ret;
}
-#endif
static gboolean
selinux_relabel_var_if_needed (OstreeSysroot *sysroot,
- OstreeLabelingContext *secontext,
+ OstreeSePolicy *sepolicy,
GFile *deployment_var_path,
GCancellable *cancellable,
GError **error)
{
-#ifdef HAVE_SELINUX
gboolean ret = FALSE;
-
- if (secontext->have_policy)
- {
- /* This is a bit of a hack; we should change the code at some
- * point in the distant future to only create (and label) /var
- * when doing a deployment.
- */
- gs_unref_object GFile *deployment_var_labeled =
- g_file_get_child (deployment_var_path, ".ostree-selabeled");
- gs_unref_object GFile *deployment_var_labeled_tmp =
- g_file_get_child (deployment_var_path, ".ostree-selabeled.tmp");
+ /* This is a bit of a hack; we should change the code at some
+ * point in the distant future to only create (and label) /var
+ * when doing a deployment.
+ */
+ gs_unref_object GFile *deployment_var_labeled =
+ g_file_get_child (deployment_var_path, ".ostree-selabeled");
+ gs_unref_object GFile *deployment_var_labeled_tmp =
+ g_file_get_child (deployment_var_path, ".ostree-selabeled.tmp");
- if (!g_file_query_exists (deployment_var_labeled, NULL))
+ if (!g_file_query_exists (deployment_var_labeled, NULL))
+ {
+ g_print ("ostadmin: Didn't find '%s', relabeling /var\n",
+ gs_file_get_path_cached (deployment_var_labeled));
+
+ if (!selinux_relabel_dir (sysroot, sepolicy,
+ deployment_var_path, "var",
+ cancellable, error))
{
- g_print ("ostadmin: Didn't find '%s', relabeling /var\n",
- gs_file_get_path_cached (deployment_var_labeled));
+ g_prefix_error (error, "Relabeling /var: ");
+ goto out;
+ }
- if (!selinux_relabel_dir (sysroot, secontext,
- deployment_var_path, "var",
+ if (!g_file_replace_contents (deployment_var_labeled_tmp, "", 0, NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION, NULL,
cancellable, error))
- {
- g_prefix_error (error, "Relabeling /var: ");
- goto out;
- }
-
- if (!g_file_replace_contents (deployment_var_labeled_tmp, "", 0, NULL, FALSE,
- G_FILE_CREATE_REPLACE_DESTINATION, NULL,
- cancellable, error))
- goto out;
+ goto out;
- if (!selinux_relabel_file (secontext, deployment_var_labeled_tmp, "var",
- cancellable, error))
- goto out;
+ if (!selinux_relabel_file (sysroot, sepolicy,
+ deployment_var_labeled_tmp, "var",
+ cancellable, error))
+ goto out;
- if (!gs_file_rename (deployment_var_labeled_tmp, deployment_var_labeled,
- cancellable, error))
- goto out;
- }
+ if (!gs_file_rename (deployment_var_labeled_tmp, deployment_var_labeled,
+ cancellable, error))
+ goto out;
}
ret = TRUE;
out:
return ret;
-#else
- return TRUE;
-#endif
}
static gboolean
@@ -647,6 +460,7 @@ merge_configuration (OstreeSysroot *sysroot,
OstreeDeployment *previous_deployment,
OstreeDeployment *deployment,
GFile *deployment_path,
+ OstreeSePolicy **out_sepolicy,
GCancellable *cancellable,
GError **error)
{
@@ -655,6 +469,7 @@ merge_configuration (OstreeSysroot *sysroot,
gs_unref_object GFile *source_etc_pristine_path = NULL;
gs_unref_object GFile *deployment_usretc_path = NULL;
gs_unref_object GFile *deployment_etc_path = NULL;
+ gs_unref_object OstreeSePolicy *sepolicy = NULL;
gboolean etc_exists;
gboolean usretc_exists;
@@ -703,21 +518,26 @@ merge_configuration (OstreeSysroot *sysroot,
if (usretc_exists)
{
- __attribute__((cleanup(ostree_labeling_context_cleanup))) OstreeLabelingContext new_default_secontext
= { 0, };
-
/* TODO - set out labels as we copy files */
g_assert (!etc_exists);
if (!gs_shutil_cp_a (deployment_usretc_path, deployment_etc_path,
cancellable, error))
goto out;
- if (!init_labeling_context (deployment_etc_path, &new_default_secontext,
- cancellable, error))
+ /* Here, we initialize SELinux policy from the /usr/etc inside
+ * the root - this is before we've finalized the configuration
+ * merge into /etc. */
+ sepolicy = ostree_sepolicy_new (deployment_path, cancellable, error);
+ if (!sepolicy)
goto out;
- if (!selinux_relabel_dir (sysroot, &new_default_secontext, deployment_etc_path, "etc",
- cancellable, error))
- goto out;
+ if (ostree_sepolicy_get_name (sepolicy) != NULL)
+ {
+ g_print ("ostadmin: Using SELinux policy '%s'\n", ostree_sepolicy_get_name (sepolicy));
+ if (!selinux_relabel_dir (sysroot, sepolicy, deployment_etc_path, "etc",
+ cancellable, error))
+ goto out;
+ }
g_print ("ostadmin: Created %s\n", gs_file_get_path_cached (deployment_etc_path));
}
@@ -733,6 +553,7 @@ merge_configuration (OstreeSysroot *sysroot,
}
ret = TRUE;
+ gs_transfer_out_value (out_sepolicy, &sepolicy);
out:
return ret;
}
@@ -1507,7 +1328,6 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
{
gboolean ret = FALSE;
gint new_deployserial;
- __attribute__((cleanup(ostree_labeling_context_cleanup))) OstreeLabelingContext secontext = { 0, };
gs_unref_object OstreeDeployment *new_deployment = NULL;
gs_unref_object OstreeDeployment *merge_deployment = NULL;
gs_unref_object OstreeRepo *repo = NULL;
@@ -1518,6 +1338,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
gs_unref_object GFile *tree_kernel_path = NULL;
gs_unref_object GFile *tree_initramfs_path = NULL;
gs_unref_object GFile *new_deployment_path = NULL;
+ gs_unref_object OstreeSePolicy *sepolicy = NULL;
gs_free char *new_bootcsum = NULL;
gs_unref_object OstreeBootconfigParser *bootconfig = NULL;
@@ -1590,6 +1411,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
if (!merge_configuration (self, merge_deployment, new_deployment,
new_deployment_path,
+ &sepolicy,
cancellable, error))
{
g_prefix_error (error, "During /etc merge: ");
@@ -1598,10 +1420,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
deployment_etc = g_file_get_child (new_deployment_path, "etc");
- if (!init_labeling_context (deployment_etc, &secontext, cancellable, error))
- goto out;
-
- if (!selinux_relabel_var_if_needed (self, &secontext, deployment_var,
+ if (!selinux_relabel_var_if_needed (self, sepolicy, deployment_var,
cancellable, error))
goto out;
diff --git a/src/libostree/ostree-types.h b/src/libostree/ostree-types.h
index b15cbbc..8be1258 100644
--- a/src/libostree/ostree-types.h
+++ b/src/libostree/ostree-types.h
@@ -27,6 +27,7 @@
G_BEGIN_DECLS
typedef struct OstreeRepo OstreeRepo;
+typedef struct OstreeSePolicy OstreeSePolicy;
typedef struct OstreeSysroot OstreeSysroot;
typedef struct OstreeMutableTree OstreeMutableTree;
typedef struct OstreeRepoFile OstreeRepoFile;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]