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 --
pgpivPsIy7KuH.pgp
Description: PGP signature