Bug#929063: init: delegate selinux operation to separate binary

Dmitry Bogatov KAction at debian.org
Thu May 16 09:54:43 BST 2019


Package: sysvinit
Severity: wishlist
Tags: patch

From 7f6242e5f3d893e90b3ed44fb09abe5983c2d49a Mon Sep 17 00:00:00 2001
From: Dmitry Bogatov <KAction at debian.org>
Date: Wed, 15 May 2019 12:10:13 +0000
Subject: [PATCH] init: delegate selinux operation to separate binary

Move selinux-related logic from /sbin/init into separate binary
(/sbin/selinux-check) by default. This way, /sbin/init is no longer
linked aganist libselinux (and its transitive dependencies).

If user need selinux initialization, she can install /sbin/selinux-check
separately.
---
 src/Makefile        |  8 +++----
 src/init.c          | 51 +++++++++++++++++++++++++++------------------
 src/init.h          |  4 ++++
 src/paths.h         |  1 +
 src/selinux-check.c | 21 +++++++++++++++++++
 5 files changed, 61 insertions(+), 24 deletions(-)
 create mode 100644 src/selinux-check.c

diff --git a/src/Makefile b/src/Makefile
index e54c051c..a23fbe38 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -23,7 +23,7 @@ MNTPOINT=
 
 # For some known distributions we do not build all programs, otherwise we do.
 BIN	=
-SBIN	= init halt shutdown runlevel killall5 fstab-decode logsave
+SBIN	= init halt shutdown runlevel killall5 fstab-decode logsave selinux-check
 USRBIN	= last mesg readbootlog
 
 MAN1	= last.1 lastb.1 mesg.1 readbootlog.1
@@ -81,11 +81,9 @@ MANDIR		= /usr/share/man
 
 ifeq ($(WITH_SELINUX),yes)
   SELINUX_DEF	=  -DWITH_SELINUX
-  INITLIBS	+= -lsepol -lselinux
   SULOGINLIBS	= -lselinux	
 else
   SELINUX_DEF	=
-  INITLIBS	=
   SULOGINLIBS	=
 endif
 
@@ -105,8 +103,10 @@ all:		$(BIN) $(SBIN) $(USRBIN)
 #	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 #%.o: %.c
 #	$(CC) $(CFLAGS) $(CPPFLAGS) -c $^ -o $@
+#
+selinux-check: -lsepol -lselinux
 
-init:		LDLIBS += $(INITLIBS) $(STATIC)
+init:		LDLIBS += $(STATIC)
 init:		init.o init_utmp.o runlevellog.o
 
 halt:		LDLIBS += $(STATIC)
diff --git a/src/init.c b/src/init.c
index 4369beb9..58e098fa 100644
--- a/src/init.c
+++ b/src/init.c
@@ -64,9 +64,6 @@ Version information is not placed in the top-level Makefile by default
 #include <sys/syslog.h>
 #include <sys/time.h>
 
-#ifdef WITH_SELINUX
-#  include <selinux/selinux.h>
-#endif
 #ifdef __FreeBSD__
 extern char **environ;
 #endif
@@ -3012,6 +3009,35 @@ int telinit(char *progname, int argc, char **argv)
 	return 1;
 }
 
+static
+void maybe_init_selinux(char **argv)
+{
+	int wstatus, ret;
+
+	if (getenv("SELINUX_INIT")) return;           /* We were re-execed. */
+	if (access(SELINUX_CHECK, X_OK) != 0) return; /* Helper not installed */
+
+	if (fork() == 0) { /* child */
+		execl(SELINUX_CHECK, SELINUX_CHECK, NULL);
+		fprintf(stderr, "Failed to execute helper to init SELinux\n");
+		exit(SELINUX_CHECK_HALT);
+	}
+
+	/* parent */
+	wait(&wstatus);
+	ret = WIFEXITED(wstatus) ? WEXITSTATUS(wstatus) : SELINUX_CHECK_HALT;
+	switch (ret) {
+		case SELINUX_CHECK_CONTINUE: return;
+		case SELINUX_CHECK_REEXEC:
+			putenv("SELINUX_INIT=YES");
+			execv(myname, argv);
+			fprintf(stderr, "Failed to re-exec init\n");
+			/* fall through */
+		case SELINUX_CHECK_HALT:
+		default: exit(1);
+	}
+}
+
 /*
  * Main entry for init and telinit.
  */
@@ -3095,23 +3121,8 @@ int main(int argc, char **argv)
 		maxproclen += strlen(argv[f]) + 1;
 	}
 
-#ifdef WITH_SELINUX
-	if (getenv("SELINUX_INIT") == NULL) {
-         if (is_selinux_enabled() != 1) {
-	    if (selinux_init_load_policy(&enforce) == 0) {
-             putenv("SELINUX_INIT=YES");
-	      execv(myname, argv);
-	    } else {
-	      if (enforce > 0) {
-		/* SELinux in enforcing mode but load_policy failed */
-		/* At this point, we probably can't open /dev/console, so log() won't work */
-		fprintf(stderr,"Unable to load SELinux Policy. Machine is in enforcing mode. Halting now.\n");
-		exit(1);
-	      }
-	    }
-	  }
-	}
-#endif  
+	maybe_init_selinux(argv);
+
 	/* Start booting. */
 	argv0 = argv[0];
 	argv[1] = NULL;
diff --git a/src/init.h b/src/init.h
index 1b70d6d1..b9440e93 100644
--- a/src/init.h
+++ b/src/init.h
@@ -50,6 +50,10 @@
 /* Default path inherited by every child. */
 #define PATH_DEFAULT   "/sbin:/usr/sbin:/bin:/usr/bin"
 
+/* Interface with SELINUX_CHECK */
+#define SELINUX_CHECK_CONTINUE 0
+#define SELINUX_CHECK_REEXEC   1
+#define SELINUX_CHECK_HALT     2
 
 /* Prototypes. */
 void write_utmp_wtmp(char *user, char *id, int pid, int type, char *line);
diff --git a/src/paths.h b/src/paths.h
index c9b82c1a..8230c8a9 100644
--- a/src/paths.h
+++ b/src/paths.h
@@ -38,6 +38,7 @@
 #define PWRSTAT_OLD	"/etc/powerstatus"	/* COMPAT: SIGPWR reason (OK/BAD) */
 #define PWRSTAT		"/var/run/powerstatus"	/* COMPAT: SIGPWR reason (OK/BAD) */
 #define RUNLEVEL_LOG    "/var/run/runlevel"     /* neutral place to store run level */
+#define SELINUX_CHECK   "/sbin/selinux-check"   /* optional selinux initialization */
 
 #if 0
 #define INITLVL		"/etc/initrunlvl"	/* COMPAT: New runlevel */
diff --git a/src/selinux-check.c b/src/selinux-check.c
new file mode 100644
index 00000000..f530b92c
--- /dev/null
+++ b/src/selinux-check.c
@@ -0,0 +1,21 @@
+#include <selinux/selinux.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "init.h"
+
+int main(void)
+{
+	int enforce;
+
+	if (is_selinux_enabled() != 1) {
+		if (selinux_init_load_policy(&enforce) == 0) {
+			return SELINUX_CHECK_REEXEC;
+		} else if (enforce > 0) {
+			fprintf(stderr,"Unable to load SELinux Policy. Machine is in enforcing mode. Halting now.\n");
+			return SELINUX_CHECK_HALT;
+		}
+	}
+
+	return SELINUX_CHECK_CONTINUE;
+}
-- 
        Note, that I send and fetch email in batch, once every 24 hours.
                 If matter is urgent, try https://t.me/kaction
                                                                             --
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://www.chiark.greenend.org.uk/pipermail/debian-init-diversity/attachments/20190516/bb2f9a44/attachment.sig>


More information about the Debian-init-diversity mailing list