]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/main.c
tree-wide: invoke rlimit_nofile_safe() before various exec{v,ve,l}() invocations
[thirdparty/systemd.git] / src / core / main.c
index cabcb9ec165cd51ee269e45ac0d5fa06646a1cd1..839dc062ff780700c9213beec517468c6ed66bcb 100644 (file)
@@ -28,6 +28,7 @@
 #include "bus-error.h"
 #include "bus-util.h"
 #include "capability-util.h"
+#include "cgroup-util.h"
 #include "clock-util.h"
 #include "conf-parser.h"
 #include "cpu-set-util.h"
@@ -57,6 +58,7 @@
 #include "pager.h"
 #include "parse-util.h"
 #include "path-util.h"
+#include "pretty-print.h"
 #include "proc-cmdline.h"
 #include "process-util.h"
 #include "raw-clone.h"
@@ -119,7 +121,7 @@ static nsec_t arg_timer_slack_nsec = NSEC_INFINITY;
 static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
 static Set* arg_syscall_archs = NULL;
 static FILE* arg_serialization = NULL;
-static bool arg_default_cpu_accounting = false;
+static int arg_default_cpu_accounting = -1;
 static bool arg_default_io_accounting = false;
 static bool arg_default_ip_accounting = false;
 static bool arg_default_blockio_accounting = false;
@@ -129,7 +131,14 @@ static uint64_t arg_default_tasks_max = UINT64_MAX;
 static sd_id128_t arg_machine_id = {};
 static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE;
 
-_noreturn_ static void freeze_or_reboot(void) {
+_noreturn_ static void freeze_or_exit_or_reboot(void) {
+
+        /* If we are running in a contianer, let's prefer exiting, after all we can propagate an exit code to the
+         * container manager, and thus inform it that something went wrong. */
+        if (detect_container() > 0) {
+                log_emergency("Exiting PID 1...");
+                exit(EXIT_EXCEPTION);
+        }
 
         if (arg_crash_reboot) {
                 log_notice("Rebooting in 10s...");
@@ -184,7 +193,7 @@ _noreturn_ static void crash(int sig) {
                         (void) kill(pid, sig); /* raise() would kill the parent */
 
                         assert_not_reached("We shouldn't be here...");
-                        _exit(EXIT_FAILURE);
+                        _exit(EXIT_EXCEPTION);
                 } else {
                         siginfo_t status;
                         int r;
@@ -227,17 +236,18 @@ _noreturn_ static void crash(int sig) {
                 else if (pid == 0) {
                         (void) setsid();
                         (void) make_console_stdio();
+                        (void) rlimit_nofile_safe();
                         (void) execle("/bin/sh", "/bin/sh", NULL, environ);
 
                         log_emergency_errno(errno, "execle() failed: %m");
-                        _exit(EXIT_FAILURE);
+                        _exit(EXIT_EXCEPTION);
                 } else {
                         log_info("Spawned crash shell as PID "PID_FMT".", pid);
                         (void) wait_for_terminate(pid, NULL);
                 }
         }
 
-        freeze_or_reboot();
+        freeze_or_exit_or_reboot();
 }
 
 static void install_crash_handler(void) {
@@ -702,7 +712,7 @@ static int parse_config_file(void) {
                 { "Manager", "DefaultLimitNICE",          config_parse_rlimit,           RLIMIT_NICE, arg_default_rlimit           },
                 { "Manager", "DefaultLimitRTPRIO",        config_parse_rlimit,           RLIMIT_RTPRIO, arg_default_rlimit         },
                 { "Manager", "DefaultLimitRTTIME",        config_parse_rlimit,           RLIMIT_RTTIME, arg_default_rlimit         },
-                { "Manager", "DefaultCPUAccounting",      config_parse_bool,             0, &arg_default_cpu_accounting            },
+                { "Manager", "DefaultCPUAccounting",      config_parse_tristate,         0, &arg_default_cpu_accounting            },
                 { "Manager", "DefaultIOAccounting",       config_parse_bool,             0, &arg_default_io_accounting             },
                 { "Manager", "DefaultIPAccounting",       config_parse_bool,             0, &arg_default_ip_accounting             },
                 { "Manager", "DefaultBlockIOAccounting",  config_parse_bool,             0, &arg_default_blockio_accounting        },
@@ -751,7 +761,14 @@ static void set_manager_defaults(Manager *m) {
         m->default_restart_usec = arg_default_restart_usec;
         m->default_start_limit_interval = arg_default_start_limit_interval;
         m->default_start_limit_burst = arg_default_start_limit_burst;
-        m->default_cpu_accounting = arg_default_cpu_accounting;
+
+        /* On 4.15+ with unified hierarchy, CPU accounting is essentially free as it doesn't require the CPU
+         * controller to be enabled, so the default is to enable it unless we got told otherwise. */
+        if (arg_default_cpu_accounting >= 0)
+                m->default_cpu_accounting = arg_default_cpu_accounting;
+        else
+                m->default_cpu_accounting = cpu_accounting_is_cheap();
+
         m->default_io_accounting = arg_default_io_accounting;
         m->default_ip_accounting = arg_default_ip_accounting;
         m->default_blockio_accounting = arg_default_blockio_accounting;
@@ -759,8 +776,10 @@ static void set_manager_defaults(Manager *m) {
         m->default_tasks_accounting = arg_default_tasks_accounting;
         m->default_tasks_max = arg_default_tasks_max;
 
-        manager_set_default_rlimits(m, arg_default_rlimit);
-        manager_transient_environment_add(m, arg_default_environment);
+        (void) manager_set_default_rlimits(m, arg_default_rlimit);
+
+        (void) manager_default_environment(m);
+        (void) manager_transient_environment_add(m, arg_default_environment);
 }
 
 static void set_manager_settings(Manager *m) {
@@ -1013,10 +1032,10 @@ static int parse_argv(int argc, char *argv[]) {
                         r = safe_atoi(optarg, &fd);
                         if (r < 0)
                                 log_error_errno(r, "Failed to parse deserialize option \"%s\": %m", optarg);
-                        if (fd < 0) {
-                                log_error("Invalid deserialize fd: %d", fd);
-                                return -EINVAL;
-                        }
+                        if (fd < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Invalid deserialize fd: %d",
+                                                       fd);
 
                         (void) fd_cloexec(fd, true);
 
@@ -1070,8 +1089,8 @@ static int parse_argv(int argc, char *argv[]) {
                 /* Hmm, when we aren't run as init system
                  * let's complain about excess arguments */
 
-                log_error("Excess arguments.");
-                return -EINVAL;
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Excess arguments.");
         }
 
         return 0;
@@ -1353,12 +1372,12 @@ static int status_welcome(void) {
                                "Failed to read os-release file, ignoring: %m");
 
         if (log_get_show_color())
-                return status_printf(NULL, false, false,
+                return status_printf(NULL, 0,
                                      "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
                                      isempty(ansi_color) ? "1" : ansi_color,
                                      isempty(pretty_name) ? "Linux" : pretty_name);
         else
-                return status_printf(NULL, false, false,
+                return status_printf(NULL, 0,
                                      "\nWelcome to %s!\n",
                                      isempty(pretty_name) ? "Linux" : pretty_name);
 }
@@ -1715,6 +1734,7 @@ static void do_reexecute(
         /* Reenable any blocked signals, especially important if we switch from initial ramdisk to init=... */
         (void) reset_all_signal_handlers();
         (void) reset_signal_mask();
+        (void) rlimit_nofile_safe();
 
         if (switch_root_init) {
                 args[0] = switch_root_init;
@@ -2131,50 +2151,43 @@ static int load_configuration(int argc, char **argv, const char **ret_error_mess
 static int safety_checks(void) {
 
         if (getpid_cached() == 1 &&
-            arg_action != ACTION_RUN) {
-                log_error("Unsupported execution mode while PID 1.");
-                return -EPERM;
-        }
+            arg_action != ACTION_RUN)
+                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+                                       "Unsupported execution mode while PID 1.");
 
         if (getpid_cached() == 1 &&
-            !arg_system) {
-                log_error("Can't run --user mode as PID 1.");
-                return -EPERM;
-        }
+            !arg_system)
+                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+                                       "Can't run --user mode as PID 1.");
 
         if (arg_action == ACTION_RUN &&
             arg_system &&
-            getpid_cached() != 1) {
-                log_error("Can't run system mode unless PID 1.");
-                return -EPERM;
-        }
+            getpid_cached() != 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+                                       "Can't run system mode unless PID 1.");
 
         if (arg_action == ACTION_TEST &&
-            geteuid() == 0) {
-                log_error("Don't run test mode as root.");
-                return -EPERM;
-        }
+            geteuid() == 0)
+                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+                                       "Don't run test mode as root.");
 
         if (!arg_system &&
             arg_action == ACTION_RUN &&
-            sd_booted() <= 0) {
-                log_error("Trying to run as user instance, but the system has not been booted with systemd.");
-                return -EOPNOTSUPP;
-        }
+            sd_booted() <= 0)
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                       "Trying to run as user instance, but the system has not been booted with systemd.");
 
         if (!arg_system &&
             arg_action == ACTION_RUN &&
-            !getenv("XDG_RUNTIME_DIR")) {
-                log_error("Trying to run as user instance, but $XDG_RUNTIME_DIR is not set.");
-                return -EUNATCH;
-        }
+            !getenv("XDG_RUNTIME_DIR"))
+                return log_error_errno(SYNTHETIC_ERRNO(EUNATCH),
+                                       "Trying to run as user instance, but $XDG_RUNTIME_DIR is not set.");
 
         if (arg_system &&
             arg_action == ACTION_RUN &&
-            running_in_chroot() > 0) {
-                log_error("Cannot be run in a chroot() environment.");
-                return -EOPNOTSUPP;
-        }
+            running_in_chroot() > 0)
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                       "Cannot be run in a chroot() environment.");
 
         return 0;
 }
@@ -2612,8 +2625,8 @@ finish:
                 if (error_message)
                         manager_status_printf(NULL, STATUS_TYPE_EMERGENCY,
                                               ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL,
-                                              "%s, freezing.", error_message);
-                freeze_or_reboot();
+                                              "%s.", error_message);
+                freeze_or_exit_or_reboot();
         }
 
         return retval;