[RFC] change policy loading to initramfs

Bill Nottingham notting at redhat.com
Wed Jan 23 22:29:55 UTC 2008


We're looking to move to a different init system in Fedora - the
current work is going to be around upstart, most likely. upstart
does not have native code for loading the SELinux policy.

We could modify every possible init to load the policy... but
that would be painful. So we might as well move to having the
policy loaded from the initramfs. The attached patches are the
first quick cut at doing that.

The main patch is for mkinitrd/nash; there's a short patch for the
current init, as it will abort if policy is already loaded. We
can't actually remove the code from init to load the policy, as
there will always be older initramfses.

Comments? Ideas for different ways to do this? It's sort of ugly
with fork and chroot(), but to avoid that we'd have to reimplement
most, if not all, of libselinux's policy loading code directly.

Bill
-------------- next part --------------
diff -up mkinitrd-6.0.28/nash/nash.c.foo mkinitrd-6.0.28/nash/nash.c
--- mkinitrd-6.0.28/nash/nash.c.foo	2008-01-09 12:12:28.000000000 -0500
+++ mkinitrd-6.0.28/nash/nash.c	2008-01-23 16:59:15.000000000 -0500
@@ -60,6 +60,8 @@
 
 #include <libdevmapper.h>
 
+#include <selinux/selinux.h>
+
 #include <bdevid.h>
 
 #include <nash.h>
@@ -1719,6 +1721,34 @@ mkdirCommand(char * cmd, char * end)
 }
 
 static int
+loadPolicyCommand(char * cmd, char *end)
+{
+    int enforce = 0;
+    int pid, status;
+    
+    pid = fork();
+    
+    if (pid == 0) {
+        if (chroot("/sysroot") != 0) {
+            eprintf("load_policy: chroot failed: %m\n");
+            exit(0);
+        }
+
+        if (selinux_init_load_policy(&enforce) != 0) {
+            if (enforce > 0) {
+                eprintf("Unable to load SELinux policy (%m). Halting now.\n");
+                exit(1);
+            }
+            exit(0);
+        }
+        exit(0);
+    }
+    waitpid(pid, &status, 0);
+    if (!WIFEXITED(status) || WEXITSTATUS(status)) exit(1);
+    return 0;
+}
+
+static int
 accessCommand(char * cmd, char * end)
 {
     char * permStr;
@@ -2728,6 +2758,7 @@ static const struct commandHandler handl
     { "find", findCommand },
     { "kernelopt", printKernelOpt },
     { "loadDrivers", loadDriversCommand },
+    { "loadpolicy", loadPolicyCommand },
     { "mkblktab", mkblktabCommand },
     { "mkblkdevs", mkblkdevsCommand },
     { "mkdir", mkdirCommand },
diff -up mkinitrd-6.0.28/mkinitrd.foo mkinitrd-6.0.28/mkinitrd
--- mkinitrd-6.0.28/mkinitrd.foo	2008-01-23 17:09:26.000000000 -0500
+++ mkinitrd-6.0.28/mkinitrd	2008-01-23 17:10:23.000000000 -0500
@@ -1692,6 +1692,13 @@ if [ -n "$dhclient_leases_cmd" ]; then
     emit "$dhclient_leases_cmd"
 fi
 
+SELINUX=
+[ -f /etc/selinux/config ] && . /etc/selinux/config
+if [ -n "$SELINUX" -a "$SELINUX" != "disabled" ]; then
+    emit "echo Loading SELinux policy."
+    emit "loadpolicy"
+fi
+
 emit "echo Switching to new root and running init."
 emit "switchroot"
 emit "echo Booting has failed."
-------------- next part --------------
diff -ru sysvinit-2.86/src/init.c sysvinit-2.86/src/init.c
--- sysvinit-2.86/src/init.c	2008-01-23 17:10:45.000000000 -0500
+++ sysvinit-2.86/src/init.c	2008-01-23 16:26:07.000000000 -0500
@@ -2671,7 +2671,7 @@
 		maxproclen += strlen(argv[f]) + 1;
 	}
 
-  	if (getenv("SELINUX_INIT") == NULL) {
+  	if (getenv("SELINUX_INIT") == NULL && !is_selinux_enabled()) {
 	  putenv("SELINUX_INIT=YES");
 	  if (selinux_init_load_policy(&enforce) == 0 ) {
 	    execv(myname, argv);


More information about the fedora-selinux-list mailing list