diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 797debea..b47b3be2 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -16,3 +16,4 @@ The following people (in alphabetical order) have contributed: * Oliver Amann - Code, testing, documentation * Locria Cyber - Code, documentation * q66 - Code, testing, documentation. + * Rahul Sandhu - Code diff --git a/build/Makefile b/build/Makefile index a8b51a78..1eda7d86 100644 --- a/build/Makefile +++ b/build/Makefile @@ -16,7 +16,8 @@ includes/mconfig.h: ../mconfig tools/mconfig-gen.cc version.conf DEFAULT_STOP_TIMEOUT=$(DEFAULT_STOP_TIMEOUT) \ $(if $(SUPPORT_CGROUPS),SUPPORT_CGROUPS=$(SUPPORT_CGROUPS),) \ $(if $(USE_UTMPX),USE_UTMPX=$(USE_UTMPX),) \ - $(if $(USE_INITGROUPS),USE_INITGROUPS=$(USE_INITGROUPS),) > includes/mconfig.h + $(if $(USE_INITGROUPS),USE_INITGROUPS=$(USE_INITGROUPS),) \ + $(if $(SUPPORT_SELINUX),SUPPORT_SELINUX=$(SUPPORT_SELINUX),) > includes/mconfig.h clean: rm -f includes/mconfig.h diff --git a/build/mconfig.mesontemplate b/build/mconfig.mesontemplate index a7a6d1fb..435fc60b 100644 --- a/build/mconfig.mesontemplate +++ b/build/mconfig.mesontemplate @@ -8,6 +8,7 @@ #mesondefine USE_UTMPX #mesondefine USE_INITGROUPS #mesondefine SUPPORT_CGROUPS +#mesondefine SUPPORT_SELINUX #mesondefine DEFAULT_AUTO_RESTART #mesondefine DEFAULT_START_TIMEOUT #mesondefine DEFAULT_STOP_TIMEOUT diff --git a/build/tools/mconfig-gen.cc b/build/tools/mconfig-gen.cc index d20ea117..324d0d07 100644 --- a/build/tools/mconfig-gen.cc +++ b/build/tools/mconfig-gen.cc @@ -80,6 +80,9 @@ int main(int argc, char **argv) if (vars.find("DEFAULT_AUTO_RESTART") != vars.end()) { cout << "#define DEFAULT_AUTO_RESTART " << vars["DEFAULT_AUTO_RESTART"] << "\n"; } + if (vars.find("SUPPORT_SELINUX") != vars.end()) { + cout << "#define SUPPORT_SELINUX " << vars["SUPPORT_SELINUX"] << "\n"; + } cout << "\n// Constants\n"; cout << "\nconstexpr static char DINIT_VERSION[] = " << stringify(vars["VERSION"]) << ";\n"; diff --git a/configure b/configure index 365c32a8..b58b2484 100755 --- a/configure +++ b/configure @@ -152,6 +152,7 @@ Optional options: --disable-utmpx Disable manipulating the utmp/utmpx database via the related POSIX functions --enable-initgroups Enable initialization of supplementary groups for run-as [Enabled] --disable-initgroups Disable initialization of supplementary groups for run-as + --enable-selinux Enable SELinux support [Enabled only on Linux based systems] --enable-auto-restart Enable auto-restart for services by default [Deprecated] --disable-auto-restart Disable auto-restart for services by default [Deprecated] --default-start-timeout=sec Default start-timeout for services [60] @@ -210,6 +211,7 @@ for var in PREFIX \ SUPPORT_CGROUPS \ USE_UTMPX \ USE_INITGROUPS \ + SUPPORT_SELINUX \ SYSCONTROLSOCKET \ STRIPOPTS do @@ -243,6 +245,8 @@ for arg in "$@"; do --disable-utmpx|--enable-utmpx=no) USE_UTMPX=0 ;; --enable-initgroups|--enable-initgroups=yes) USE_INITGROUPS=1 ;; --disable-initgroups|--enable-initgroups=no) USE_INITGROUPS=0 ;; + --enable-selinux|--enable-selinux=yes) SUPPORT_SELINUX=1 ;; + --disable-selinux|--enable-selinux=no) SUPPORT_SELINUX=0 ;; --enable-auto-restart|--enable-auto-restart=yes) DEFAULT_AUTO_RESTART=ALWAYS ;; # Deprecated --disable-auto-restart|--enable-auto-restart=no) DEFAULT_AUTO_RESTART=NEVER ;; # Deprecated --enable-strip|--enable-strip=yes) STRIPOPTS="-s" ;; @@ -275,6 +279,7 @@ done : "${DEFAULT_START_TIMEOUT:="60"}" : "${DEFAULT_STOP_TIMEOUT:="10"}" : "${USE_INITGROUPS:="1"}" +: "${SUPPORT_SELINUX:="0"}" if [ "$PLATFORM" = "Linux" ]; then : "${BUILD_SHUTDOWN:="yes"}" : "${SUPPORT_CGROUPS:="1"}" @@ -380,6 +385,9 @@ fi if [ "$AUTO_LDFLAGS_BASE" = true ] && [ "$PLATFORM" = FreeBSD ]; then try_ld_argument LDFLAGS_BASE -lrt fi +if [ "$AUTO_LDFLAGS_BASE" = true ] && [ "$SUPPORT_SELINUX" = "1" ]; then + try_ld_argument LDFLAGS_BASE -lselinux +fi if [ "$AUTO_TEST_LDFLAGS_BASE" = true ]; then TEST_LDFLAGS_BASE="\$(LDFLAGS_BASE)" established_TEST_LDFLAGS="$LDFLAGS_BASE" @@ -467,6 +475,7 @@ STRIPOPTS=$STRIPOPTS # Feature settings SUPPORT_CGROUPS=$SUPPORT_CGROUPS USE_INITGROUPS=$USE_INITGROUPS +SUPPORT_SELINUX=$SUPPORT_SELINUX # Optional settings SHUTDOWN_PREFIX=${SHUTDOWN_PREFIX:-} diff --git a/meson.build b/meson.build index 96e1a0f9..2cbef24f 100644 --- a/meson.build +++ b/meson.build @@ -33,6 +33,7 @@ man_pages = get_option('man-pages') support_cgroups = get_option('support-cgroups') use_utmpx = get_option('use-utmpx') use_initgroups = get_option('use-initgroups') +libselinux = dependency('libselinux', version : '>= 2.1.9', required : get_option('selinux')) default_auto_restart = get_option('default-auto-restart') default_start_timeout = get_option('default-start-timeout').to_string() default_stop_timeout = get_option('default-stop-timeout').to_string() @@ -65,6 +66,7 @@ mconfig_data.set('DEFAULT_AUTO_RESTART', default_auto_restart) mconfig_data.set('DEFAULT_START_TIMEOUT', default_start_timeout) mconfig_data.set('DEFAULT_STOP_TIMEOUT', default_stop_timeout) mconfig_data.set10('USE_INITGROUPS', use_initgroups) +mconfig_data.set10('SUPPORT_SELINUX', libselinux.found()) if support_cgroups.auto() and platform == 'linux' or support_cgroups.enabled() mconfig_data.set('SUPPORT_CGROUPS', '1') endif diff --git a/meson_options.txt b/meson_options.txt index 617669ec..1cc8179d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -91,3 +91,9 @@ option( value : 'auto', description : 'Building shutdown/reboot/soft-reboot/halt or not.' ) +option( + 'selinux', + type : 'feature', + value : 'auto', + description : 'SELinux support' +) diff --git a/src/dinit.cc b/src/dinit.cc index d2d0510d..b6473a93 100644 --- a/src/dinit.cc +++ b/src/dinit.cc @@ -37,6 +37,12 @@ #include "mconfig.h" +#if SUPPORT_SELINUX +#include +#include +#include +#endif + /* * When running as the system init process, Dinit processes the following signals: * @@ -453,6 +459,71 @@ static int process_commandline_arg(char **argv, int argc, int &i, options &opts) return 0; } +bool selinux_transition(const char *exe) { +#if SUPPORT_SELINUX + using std::cerr; + using std::endl; + + char *current_context = nullptr; + char *file_context = nullptr; + security_class_t security_class; + char *new_context = nullptr; + + if (is_selinux_enabled() == 1) { + return 0; + } + + int enforce = 0; + if (selinux_init_load_policy(&enforce) != 0) { + if (enforce > 0) { + cerr << "Failed to load SELinux policy." << endl; + return 1; + } + } + + bool ret = true; + if (getcon_raw(¤t_context) < 0) { + ret = false; + cerr << "Failed to get current context: " << strerror(errno) << endl; + goto cleanup; + } + + if (getfilecon_raw(exe, &file_context) < 0) { + ret = false; + cerr << "Failed to get file context for " << exe << ": " << strerror(errno) << endl; + goto cleanup; + } + + security_class = string_to_security_class("process"); + if (security_class == 0) { + ret = false; + cerr << "Failed to get security class for process" << endl; + goto cleanup; + } + + if (security_compute_create_raw(current_context, file_context, security_class, &new_context) < 0) { + ret = false; + cerr << "Failed to compute create context: " << strerror(errno) << endl; + goto cleanup; + } + + if (setcon_raw(new_context) < 0) { + ret = false; + cerr << "Failed to set exec context to " << new_context << ": " << strerror(errno) << endl; + goto cleanup; + } + +cleanup: + if (current_context) freecon(current_context); + if (file_context) freecon(file_context); + if (new_context) freecon(new_context); + selinux_status_close(); + return ret; +#else + return true; +#endif +} + // Main entry point int dinit_main(int argc, char **argv) { @@ -461,6 +532,8 @@ int dinit_main(int argc, char **argv) am_system_mgr = (getpid() == 1); am_system_init = (getuid() == 0); + if (am_system_mgr && am_system_init && !selinux_transition(argv[0])) return 1; + struct options opts; // if we are PID 1 and user id 0, we are *most probably* the system init. (Or on linux at least, we diff --git a/src/meson.build b/src/meson.build index 75b3aced..e0154f5f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -21,6 +21,12 @@ dinit_source_files = [ 'dinit-env.cc', 'settings.cc' ] +dinit_dependencies = [] + +if libselinux.found() + dinit_dependencies += libselinux +endif + ## src/'s Defines shutdown_built = false @@ -40,7 +46,8 @@ endif executable( 'dinit', dinit_source_files, - kwargs: misc_args + kwargs: misc_args, + dependencies: dinit_dependencies ) executable( 'dinitctl',