Currently on at least Fedora, SELinux policy does not come in
the initramfs. systemd will attempt to load *both* in the
initramfs and in the real root.

Now, the selinux_init_load_policy() API has a regular error return
value, as well as an "enforcing" boolean. To determine enforcing
state, it looks for /etc/selinux/config as well as the presence
of "enforcing=" on the kernel command line.

Ordinarily, neither of those exist in the initramfs, so it will return
"unknown" for enforcing, and systemd will simply ignore the failure to
load policy.

Then later after we switch to the real root, we have the config file,
and all will work properly.

Except...this all blows up if someone explicitly specifies enforcing=1
on the kernel command line. Then systemd will fail to load the
nonexistent policy in the initramfs and freeze.

What this patch does is quite simple - we add an internal API that
says where we expect to find policy, and attempt to load it exactly
from there. Right now since I'm not aware of anyone who does
policy-in-initramfs, this function is hardcoded to return false.

Lots-of-very-painful-debugging-by: Colin Walters <walt...@verbum.org>
---
src/core/main.c | 6 ++++--
src/core/selinux-setup.c | 10 ++++++++++
src/core/selinux-setup.h | 2 ++
3 files changed, 16 insertions(+), 2 deletions(-)



>From b109b6e0c1ea7509f08a09d66072c86bea279a06 Mon Sep 17 00:00:00 2001
From: Colin Walters <walt...@verbum.org>
Date: Thu, 20 Feb 2014 10:15:10 -0500
Subject: [PATCH] selinux: Only attempt to load policy exactly once, in the
 real root

Currently on at least Fedora, SELinux policy does not come in
the initramfs.  systemd will attempt to load *both* in the
initramfs and in the real root.

Now, the selinux_init_load_policy() API has a regular error return
value, as well as an "enforcing" boolean.  To determine enforcing
state, it looks for /etc/selinux/config as well as the presence
of "enforcing=" on the kernel command line.

Ordinarily, neither of those exist in the initramfs, so it will return
"unknown" for enforcing, and systemd will simply ignore the failure to
load policy.

Then later after we switch to the real root, we have the config file,
and all will work properly.

Except...this all blows up if someone explicitly specifies enforcing=1
on the kernel command line.  Then systemd will fail to load the
nonexistent policy in the initramfs and freeze.

What this patch does is quite simple - we add an internal API that
says where we expect to find policy, and attempt to load it exactly
from there.  Right now since I'm not aware of anyone who does
policy-in-initramfs, this function is hardcoded to return false.

Lots-of-very-painful-debugging-by: Colin Walters <walt...@verbum.org>
---
 src/core/main.c          |  6 ++++--
 src/core/selinux-setup.c | 10 ++++++++++
 src/core/selinux-setup.h |  2 ++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/core/main.c b/src/core/main.c
index 58c3a9e..8a13b54 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1296,8 +1296,10 @@ int main(int argc, char *argv[]) {
 
                 if (!skip_setup) {
                         mount_setup_early();
-                        if (selinux_setup(&loaded_policy) < 0)
-                                goto finish;
+                        if (in_initrd() == selinux_load_policy_in_initramfs()) {
+                                if (selinux_setup(&loaded_policy) < 0)
+                                        goto finish;
+                        }
                         if (ima_setup() < 0)
                                 goto finish;
                         if (smack_setup() < 0)
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index 7a32ed5..f689149 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -37,6 +37,16 @@
 #include "util.h"
 #include "log.h"
 
+/**
+ * At present, I'm not aware of a SELinux user who loads the policy
+ * from the initramfs.  If you are such a user, you can flip this
+ * define with a patch.  Alternatively in the future, this information
+ * could come from the kernel command line.
+ */
+bool selinux_load_policy_in_initramfs(void) {
+        return false;
+}
+
 #ifdef HAVE_SELINUX
 static int null_log(int type, const char *fmt, ...) {
         return 0;
diff --git a/src/core/selinux-setup.h b/src/core/selinux-setup.h
index 39e2bc2..d3f3bbc 100644
--- a/src/core/selinux-setup.h
+++ b/src/core/selinux-setup.h
@@ -23,4 +23,6 @@
 
 #include <stdbool.h>
 
+bool selinux_load_policy_in_initramfs(void);
+
 int selinux_setup(bool *loaded_policy);
-- 
1.8.3.1

_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to