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