Browse Source

initd/init: add minimal SELinux policy loading support

In order to support SELinux in OpenWrt, this commit introduces minimal
support for loading the SELinux policy in the init code. The logic is
very much inspired from what Busybox is doing: call
selinux_init_load_policy() from libselinux, and then re-execute init
so that it runs with the SELinux policy in place and enforced.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni at bootlin.com>
[fix spelling of OpenWrt]
Signed-off-by: Paul Spooren <mail@aparcar.org>
Thomas Petazzoni 3 years ago
parent
commit
fad899769e
2 changed files with 46 additions and 1 deletions
  1. 8 1
      CMakeLists.txt
  2. 38 0
      initd/init.c

+ 8 - 1
CMakeLists.txt

@@ -46,6 +46,12 @@ IF(ZRAM_TMPFS)
   SET(SOURCES_ZRAM initd/zram.c)
 ENDIF()
 
+IF(SELINUX)
+  include(FindPkgConfig)
+  pkg_search_module(SELINUX REQUIRED libselinux)
+  add_compile_definitions(WITH_SELINUX)
+ENDIF()
+
 add_subdirectory(upgraded)
 
 ADD_EXECUTABLE(procd ${SOURCES})
@@ -62,7 +68,8 @@ ADD_DEFINITIONS(-DDISABLE_INIT)
 ELSE()
 ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c sysupgrade.c watchdog.c
 	utils/utils.c ${SOURCES_ZRAM})
-TARGET_LINK_LIBRARIES(init ${LIBS})
+TARGET_INCLUDE_DIRECTORIES(init PUBLIC ${SELINUX_INCLUDE_DIRS})
+TARGET_LINK_LIBRARIES(init ${LIBS} ${SELINUX_LIBRARIES})
 INSTALL(TARGETS init
 	RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
 )

+ 38 - 0
initd/init.c

@@ -29,6 +29,10 @@
 #include <unistd.h>
 #include <stdio.h>
 
+#if defined(WITH_SELINUX)
+#include <selinux/selinux.h>
+#endif
+
 #include "../utils/utils.h"
 #include "init.h"
 #include "../watchdog.h"
@@ -67,6 +71,38 @@ cmdline(void)
 	}
 }
 
+#if defined(WITH_SELINUX)
+static int
+selinux(char **argv)
+{
+	int enforce = 0;
+	int ret;
+
+	/* SELinux already initialized */
+	if (getenv("SELINUX_INIT"))
+		return 0;
+
+	putenv("SELINUX_INIT=1");
+
+	ret = selinux_init_load_policy(&enforce);
+	if (ret == 0)
+		execv(argv[0], argv);
+
+	if (enforce > 0) {
+		fprintf(stderr, "Cannot load SELinux policy, but system in enforcing mode. Halting.\n");
+		return 1;
+	}
+
+	return 0;
+}
+#else
+static int
+selinux(char **argv)
+{
+	return 0;
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
@@ -79,6 +115,8 @@ main(int argc, char **argv)
 	sigaction(SIGUSR2, &sa_shutdown, NULL);
 	sigaction(SIGPWR, &sa_shutdown, NULL);
 
+	if (selinux(argv))
+		exit(-1);
 	early();
 	cmdline();
 	watchdog_init(1);