initd/init: add minimal SELinux policy loading support
authorThomas Petazzoni <thomas.petazzoni at bootlin.com>
Mon, 10 Aug 2020 01:15:20 +0000 (15:15 -1000)
committerDaniel Golle <daniel@makrotopia.org>
Mon, 10 Aug 2020 08:35:03 +0000 (09:35 +0100)
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>
CMakeLists.txt
initd/init.c

index c7adfa363b770e993d0a98c28ec17e9f5fa528db..d20e57b4e6a5b908cdb1bc1d7a896c0761159f2a 100644 (file)
@@ -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}
 )
index 9b4782608e1a7a9f411eaacfa9b97b2d6b3fe89c..2eb6ead2c0f466a7d91eb813f7de0cbdaedba42d 100644 (file)
 #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);