Package: sysvinit
Severity: wishlist
Tags: patch

From 7f6242e5f3d893e90b3ed44fb09abe5983c2d49a Mon Sep 17 00:00:00 2001
From: Dmitry Bogatov <kact...@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
                                                                             --

Attachment: pgpivPsIy7KuH.pgp
Description: PGP signature

Reply via email to