chiark / gitweb /
core: Refuse to run a user instance when the system hasn't been booted with systemd.
[elogind.git] / src / core / main.c
index 44c010cfbf817bc7485a414e40dbde7844507270..e094efeb3c5efb4f9a74587b75cb199a3c75061b 100644 (file)
@@ -62,6 +62,7 @@
 #include "hwclock.h"
 #include "selinux-setup.h"
 #include "ima-setup.h"
+#include "sd-daemon.h"
 
 static enum {
         ACTION_RUN,
@@ -73,7 +74,7 @@ static enum {
 } arg_action = ACTION_RUN;
 
 static char *arg_default_unit = NULL;
-static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
+static SystemdRunningAs arg_running_as = _SYSTEMD_RUNNING_AS_INVALID;
 
 static bool arg_dump_core = true;
 static bool arg_crash_shell = false;
@@ -684,7 +685,7 @@ static int parse_config_file(void) {
         const char *fn;
         int r;
 
-        fn = arg_running_as == MANAGER_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
+        fn = arg_running_as == SYSTEMD_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
         f = fopen(fn, "re");
         if (!f) {
                 if (errno == ENOENT)
@@ -872,11 +873,11 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_SYSTEM:
-                        arg_running_as = MANAGER_SYSTEM;
+                        arg_running_as = SYSTEMD_SYSTEM;
                         break;
 
                 case ARG_USER:
-                        arg_running_as = MANAGER_USER;
+                        arg_running_as = SYSTEMD_USER;
                         break;
 
                 case ARG_TEST:
@@ -1227,6 +1228,28 @@ static void test_cgroups(void) {
         sleep(10);
 }
 
+static int initialize_join_controllers(void) {
+        /* By default, mount "cpu" + "cpuacct" together, and "net_cls"
+         * + "net_prio". We'd like to add "cpuset" to the mix, but
+         * "cpuset" does't really work for groups with no initialized
+         * attributes. */
+
+        arg_join_controllers = new(char**, 3);
+        if (!arg_join_controllers)
+                return -ENOMEM;
+
+        arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
+        if (!arg_join_controllers[0])
+                return -ENOMEM;
+
+        arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL);
+        if (!arg_join_controllers[1])
+                return -ENOMEM;
+
+        arg_join_controllers[2] = NULL;
+        return 0;
+}
+
 int main(int argc, char *argv[]) {
         Manager *m = NULL;
         int r, retval = EXIT_FAILURE;
@@ -1285,10 +1308,15 @@ int main(int argc, char *argv[]) {
         saved_argc = argc;
 
         log_show_color(isatty(STDERR_FILENO) > 0);
-        log_show_location(false);
-        log_set_max_level(LOG_INFO);
 
-        if (getpid() == 1) {
+        if (getpid() == 1 && detect_container(NULL) <= 0) {
+
+                /* Running outside of a container as PID 1 */
+                arg_running_as = SYSTEMD_SYSTEM;
+                make_null_stdio();
+                log_set_target(LOG_TARGET_KMSG);
+                log_open();
+
                 if (in_initrd()) {
                         char *rd_timestamp = NULL;
 
@@ -1302,11 +1330,6 @@ int main(int argc, char *argv[]) {
                         }
                 }
 
-                arg_running_as = MANAGER_SYSTEM;
-
-                make_null_stdio();
-                log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_JOURNAL : LOG_TARGET_JOURNAL_OR_KMSG);
-
                 if (!skip_setup) {
                         if (selinux_setup(&loaded_policy) < 0)
                                 goto finish;
@@ -1314,24 +1337,52 @@ int main(int argc, char *argv[]) {
                                 goto finish;
                 }
 
-                log_open();
-
                 if (label_init(NULL) < 0)
                         goto finish;
 
-                if (!skip_setup)
+                if (!skip_setup) {
                         if (hwclock_is_localtime() > 0) {
                                 int min;
 
-                                r = hwclock_apply_localtime_delta(&min);
+                                /* The first-time call to settimeofday() does a time warp in the kernel */
+                                r = hwclock_set_timezone(&min);
                                 if (r < 0)
                                         log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
                                 else
                                         log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
+                        } else {
+                                /* Do dummy first-time call to seal the kernel's time warp magic */
+                                hwclock_reset_timezone();
+
+                                /* Tell the kernel our time zone */
+                                r = hwclock_set_timezone(NULL);
+                                if (r < 0)
+                                        log_error("Failed to set the kernel's time zone, ignoring: %s", strerror(-r));
                         }
+                }
+
+                /* Set the default for later on, but don't actually
+                 * open the logs like this for now. Note that if we
+                 * are transitioning from the initrd there might still
+                 * be journal fd open, and we shouldn't attempt
+                 * opening that before we parsed /proc/cmdline which
+                 * might redirect output elsewhere. */
+                log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+
+        } else if (getpid() == 1) {
+
+                /* Running inside a container, as PID 1 */
+                arg_running_as = SYSTEMD_SYSTEM;
+                log_set_target(LOG_TARGET_CONSOLE);
+                log_open();
+
+                /* For the later on, see above... */
+                log_set_target(LOG_TARGET_JOURNAL);
 
         } else {
-                arg_running_as = MANAGER_USER;
+
+                /* Running as user instance */
+                arg_running_as = SYSTEMD_USER;
                 log_set_target(LOG_TARGET_AUTO);
                 log_open();
         }
@@ -1343,16 +1394,8 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        /* By default, mount "cpu" and "cpuacct" together */
-        arg_join_controllers = new(char**, 3);
-        if (!arg_join_controllers)
-                goto finish;
-
-        arg_join_controllers[0] = strv_new("cpu", "cpuacct", "cpuset", NULL);
-        arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL);
-        arg_join_controllers[2] = NULL;
-
-        if (!arg_join_controllers[0])
+        r = initialize_join_controllers();
+        if (r < 0)
                 goto finish;
 
         /* Mount /proc, /sys and friends, so that /proc/cmdline and
@@ -1372,7 +1415,7 @@ int main(int argc, char *argv[]) {
         if (parse_config_file() < 0)
                 goto finish;
 
-        if (arg_running_as == MANAGER_SYSTEM)
+        if (arg_running_as == SYSTEMD_SYSTEM)
                 if (parse_proc_cmdline() < 0)
                         goto finish;
 
@@ -1381,12 +1424,20 @@ int main(int argc, char *argv[]) {
         if (parse_argv(argc, argv) < 0)
                 goto finish;
 
-        if (arg_action == ACTION_TEST && geteuid() == 0) {
+        if (arg_action == ACTION_TEST &&
+            geteuid() == 0) {
                 log_error("Don't run test mode as root.");
                 goto finish;
         }
 
-        if (arg_running_as == MANAGER_SYSTEM &&
+        if (arg_running_as == SYSTEMD_USER &&
+            arg_action == ACTION_RUN &&
+            sd_booted() <= 0) {
+                log_error("Trying to run as user instance, but the system has not been booted with systemd.");
+                goto finish;
+        }
+
+        if (arg_running_as == SYSTEMD_SYSTEM &&
             arg_action == ACTION_RUN &&
             running_in_chroot() > 0) {
                 log_error("Cannot be run in a chroot() environment.");
@@ -1432,9 +1483,9 @@ int main(int argc, char *argv[]) {
 #else
                "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
 #endif
-               arg_running_as == MANAGER_SYSTEM);
+               arg_running_as == SYSTEMD_SYSTEM);
 
-        if (arg_running_as == MANAGER_SYSTEM) {
+        if (arg_running_as == SYSTEMD_SYSTEM) {
                 /* Parse the data passed to us. We leave this
                  * variables set, but the manager later on will not
                  * pass them on to our children. */
@@ -1465,7 +1516,7 @@ int main(int argc, char *argv[]) {
         /* Move out of the way, so that we won't block unmounts */
         assert_se(chdir("/")  == 0);
 
-        if (arg_running_as == MANAGER_SYSTEM) {
+        if (arg_running_as == SYSTEMD_SYSTEM) {
                 /* Become a session leader if we aren't one yet. */
                 setsid();
 
@@ -1478,7 +1529,7 @@ int main(int argc, char *argv[]) {
 
         /* Reset the console, but only if this is really init and we
          * are freshly booted */
-        if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN)
+        if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN)
                 console_setup(getpid() == 1 && !skip_setup);
 
         /* Open the logging devices, if possible and necessary */
@@ -1495,7 +1546,7 @@ int main(int argc, char *argv[]) {
                         goto finish;
         }
 
-        if (arg_running_as == MANAGER_SYSTEM) {
+        if (arg_running_as == SYSTEMD_SYSTEM) {
                 const char *virtualization = NULL;
 
                 log_info(PACKAGE_STRING " running in system mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
@@ -1510,7 +1561,7 @@ int main(int argc, char *argv[]) {
         } else
                 log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
 
-        if (arg_running_as == MANAGER_SYSTEM && !skip_setup) {
+        if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) {
                 locale_setup();
 
                 if (arg_show_status || plymouth_running())
@@ -1526,7 +1577,7 @@ int main(int argc, char *argv[]) {
                 test_cgroups();
         }
 
-        if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
+        if (arg_running_as == SYSTEMD_SYSTEM && arg_runtime_watchdog > 0)
                 watchdog_set_timeout(&arg_runtime_watchdog);
 
         if (arg_timer_slack_nsec != (nsec_t) -1)
@@ -1546,7 +1597,7 @@ int main(int argc, char *argv[]) {
                 }
         }
 
-        if (arg_running_as == MANAGER_USER) {
+        if (arg_running_as == SYSTEMD_USER) {
                 /* Become reaper of our children */
                 if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) {
                         log_warning("Failed to make us a subreaper: %m");
@@ -1555,7 +1606,7 @@ int main(int argc, char *argv[]) {
                 }
         }
 
-        if (arg_running_as == MANAGER_SYSTEM)
+        if (arg_running_as == SYSTEMD_SYSTEM)
                 bump_rlimit_nofile(&saved_rlimit_nofile);
 
         r = manager_new(arg_running_as, &m);
@@ -1794,7 +1845,7 @@ finish:
                         args[i++] = SYSTEMD_BINARY_PATH;
                         if (switch_root_dir)
                                 args[i++] = "--switched-root";
-                        args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user";
+                        args[i++] = arg_running_as == SYSTEMD_SYSTEM ? "--system" : "--user";
                         args[i++] = "--deserialize";
                         args[i++] = sfd;
                         args[i++] = NULL;