chiark / gitweb /
main: ISOLATE rather than REPLACE default.target
[elogind.git] / src / core / main.c
index 04fc0b3b59fda78108d91920f519b35ab72f5f44..2bbea7ec2f153d8bbb9e6cedde01929e1927e7f9 100644 (file)
 #include "switch-root.h"
 #include "capability.h"
 #include "killall.h"
+#include "env-util.h"
+#include "hwclock.h"
+#include "sd-daemon.h"
 
 #include "mount-setup.h"
 #include "loopback-setup.h"
+#ifdef HAVE_KMOD
 #include "kmod-setup.h"
+#endif
 #include "hostname-setup.h"
 #include "machine-id-setup.h"
 #include "locale-setup.h"
-#include "hwclock.h"
 #include "selinux-setup.h"
 #include "ima-setup.h"
+#include "fileio.h"
 
 static enum {
         ACTION_RUN,
@@ -339,7 +344,8 @@ static int parse_proc_cmdline_word(const char *word) {
                 else
                         arg_default_std_error = r;
         } else if (startswith(word, "systemd.setenv=")) {
-                char *cenv, *eq;
+                _cleanup_free_ char *cenv = NULL;
+                char *eq;
                 int r;
 
                 cenv = strdup(word + 15);
@@ -348,16 +354,23 @@ static int parse_proc_cmdline_word(const char *word) {
 
                 eq = strchr(cenv, '=');
                 if (!eq) {
-                        r = unsetenv(cenv);
-                        if (r < 0)
-                                log_warning("unsetenv failed %m. Ignoring.");
+                        if (!env_name_is_valid(cenv))
+                                log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
+                        else  {
+                                r = unsetenv(cenv);
+                                if (r < 0)
+                                        log_warning("Unsetting environment variable '%s' failed, ignoring: %m", cenv);
+                        }
                 } else {
-                        *eq = 0;
-                        r = setenv(cenv, eq + 1, 1);
-                        if (r < 0)
-                                log_warning("setenv failed %m. Ignoring.");
+                        if (!env_assignment_is_valid(cenv))
+                                log_warning("Environment variable assignment '%s' is not valid. Ignoring.", cenv);
+                        else {
+                                *eq = 0;
+                                r = setenv(cenv, eq + 1, 1);
+                                if (r < 0)
+                                        log_warning("Setting environment variable '%s=%s' failed, ignoring: %m", cenv, eq + 1);
+                        }
                 }
-                free(cenv);
 
         } else if (startswith(word, "systemd.") ||
                    (in_initrd() && startswith(word, "rd.systemd."))) {
@@ -931,14 +944,18 @@ static int parse_argv(int argc, char *argv[]) {
                         int fd;
                         FILE *f;
 
-                        if ((r = safe_atoi(optarg, &fd)) < 0 || fd < 0) {
+                        r = safe_atoi(optarg, &fd);
+                        if (r < 0 || fd < 0) {
                                 log_error("Failed to parse deserialize option %s.", optarg);
-                                return r;
+                                return r < 0 ? r : -EINVAL;
                         }
 
-                        if (!(f = fdopen(fd, "r"))) {
+                        fd_cloexec(fd, true);
+
+                        f = fdopen(fd, "r");
+                        if (!f) {
                                 log_error("Failed to open serialization fd: %m");
-                                return r;
+                                return -errno;
                         }
 
                         if (serialization)
@@ -1057,7 +1074,6 @@ static int help(void) {
 
 static int version(void) {
         puts(PACKAGE_STRING);
-        puts(DISTRIBUTION);
         puts(SYSTEMD_FEATURES);
 
         return 0;
@@ -1227,6 +1243,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;
@@ -1327,8 +1365,15 @@ int main(int argc, char *argv[]) {
                                         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 */
+                        } else if (!in_initrd()) {
+                                /*
+                                 * Do dummy first-time call to seal the kernel's time warp magic
+                                 *
+                                 * Do not call this this from inside the initrd. The initrd might not
+                                 * carry /etc/adjtime with LOCAL, but the real system could be set up
+                                 * that way. In such case, we need to delay the time-warp or the sealing
+                                 * until we reach the real system.
+                                 */
                                 hwclock_reset_timezone();
 
                                 /* Tell the kernel our time zone */
@@ -1371,16 +1416,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
@@ -1409,11 +1446,19 @@ 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 == 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) {
@@ -1442,16 +1487,15 @@ int main(int argc, char *argv[]) {
         log_close();
 
         /* Remember open file descriptors for later deserialization */
-        if (serialization) {
-                r = fdset_new_fill(&fds);
-                if (r < 0) {
-                        log_error("Failed to allocate fd set: %s", strerror(-r));
-                        goto finish;
-                }
+        r = fdset_new_fill(&fds);
+        if (r < 0) {
+                log_error("Failed to allocate fd set: %s", strerror(-r));
+                goto finish;
+        } else
+                fdset_cloexec(fds, true);
 
+        if (serialization)
                 assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
-        } else
-                close_all_fds(NULL, 0);
 
         /* Set up PATH unless it is already set */
         setenv("PATH",
@@ -1486,6 +1530,12 @@ int main(int argc, char *argv[]) {
                 unsetenv("USER");
                 unsetenv("LOGNAME");
 
+                /* We suppress the socket activation env vars, as
+                 * we'll try to match *any* open fd to units if
+                 * possible. */
+                unsetenv("LISTEN_FDS");
+                unsetenv("LISTEN_PID");
+
                 /* All other variables are left as is, so that clients
                  * can still read them via /proc/1/environ */
         }
@@ -1526,7 +1576,7 @@ int main(int argc, char *argv[]) {
         if (arg_running_as == SYSTEMD_SYSTEM) {
                 const char *virtualization = NULL;
 
-                log_info(PACKAGE_STRING " running in system mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
+                log_info(PACKAGE_STRING " running in system mode. (" SYSTEMD_FEATURES ")");
 
                 detect_virtualization(&virtualization);
                 if (virtualization)
@@ -1536,7 +1586,7 @@ int main(int argc, char *argv[]) {
                         log_info("Running in initial RAM disk.");
 
         } else
-                log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
+                log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES ")");
 
         if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) {
                 locale_setup();
@@ -1544,7 +1594,9 @@ int main(int argc, char *argv[]) {
                 if (arg_show_status || plymouth_running())
                         status_welcome();
 
+#ifdef HAVE_KMOD
                 kmod_setup();
+#endif
                 hostname_setup();
                 machine_id_setup();
                 loopback_setup();
@@ -1619,10 +1671,7 @@ int main(int argc, char *argv[]) {
 
         /* This will close all file descriptors that were opened, but
          * not claimed by any unit. */
-        if (fds) {
-                fdset_free(fds);
-                fds = NULL;
-        }
+        fdset_free(fds);
 
         if (serialization) {
                 fclose(serialization);
@@ -1671,7 +1720,7 @@ int main(int argc, char *argv[]) {
                         manager_dump_units(m, stdout, "\t");
                 }
 
-                r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
+                r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, false, &error, &default_unit_job);
                 if (r < 0) {
                         log_error("Failed to start default target: %s", bus_error(&error, r));
                         dbus_error_free(&error);