]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/main.c
main: use log_error_errno() at one more place
[thirdparty/systemd.git] / src / core / main.c
index 4b2d1492373189e75f203f8bd590ac66bb153f44..5714fb5ef4fc64f29a4ee973ff82ef13a4d76336 100644 (file)
@@ -1,22 +1,4 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
 
 #include <errno.h>
 #include <fcntl.h>
 #include "clock-util.h"
 #include "conf-parser.h"
 #include "cpu-set-util.h"
+#include "dbus.h"
 #include "dbus-manager.h"
 #include "def.h"
 #include "emergency-action.h"
 #include "env-util.h"
+#include "exit-status.h"
 #include "fd-util.h"
 #include "fdset.h"
 #include "fileio.h"
@@ -69,6 +53,7 @@
 #include "manager.h"
 #include "missing.h"
 #include "mount-setup.h"
+#include "os-util.h"
 #include "pager.h"
 #include "parse-util.h"
 #include "path-util.h"
@@ -100,7 +85,8 @@ static enum {
         ACTION_HELP,
         ACTION_VERSION,
         ACTION_TEST,
-        ACTION_DUMP_CONFIGURATION_ITEMS
+        ACTION_DUMP_CONFIGURATION_ITEMS,
+        ACTION_DUMP_BUS_PROPERTIES,
 } arg_action = ACTION_RUN;
 static char *arg_default_unit = NULL;
 static bool arg_system = false;
@@ -109,7 +95,7 @@ static int arg_crash_chvt = -1;
 static bool arg_crash_shell = false;
 static bool arg_crash_reboot = false;
 static char *arg_confirm_spawn = NULL;
-static ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
+static ShowStatus arg_show_status = _SHOW_STATUS_INVALID;
 static bool arg_switched_root = false;
 static bool arg_no_pager = false;
 static bool arg_service_watchdogs = true;
@@ -127,6 +113,7 @@ static char *arg_watchdog_device = NULL;
 static char **arg_default_environment = NULL;
 static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
 static uint64_t arg_capability_bounding_set = CAP_ALL;
+static bool arg_no_new_privs = false;
 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;
@@ -319,6 +306,7 @@ static int parse_confirm_spawn(const char *value, char **console) {
                 s = strjoin("/dev/", value);
         if (!s)
                 return -ENOMEM;
+
         *console = s;
         return 0;
 }
@@ -482,7 +470,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
 
         } else if (streq(key, "quiet") && !value) {
 
-                if (arg_show_status == _SHOW_STATUS_UNSET)
+                if (arg_show_status == _SHOW_STATUS_INVALID)
                         arg_show_status = SHOW_STATUS_AUTO;
 
         } else if (streq(key, "debug") && !value) {
@@ -532,10 +520,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                 return 0;                                             \
         }
 
-DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level")
-DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
-DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
-DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
+DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level");
+DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target");
+DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" );
+DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location");
 
 static int config_parse_cpu_affinity2(
                 const char *unit,
@@ -616,8 +604,8 @@ static int config_parse_output_restricted(
                 return 0;
         }
 
-        if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE)) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file: are not supported as defaults, ignoring: %s", rvalue);
+        if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -671,6 +659,7 @@ static int parse_config_file(void) {
                 { "Manager", "ShutdownWatchdogSec",       config_parse_sec,              0, &arg_shutdown_watchdog                 },
                 { "Manager", "WatchdogDevice",            config_parse_path,             0, &arg_watchdog_device                   },
                 { "Manager", "CapabilityBoundingSet",     config_parse_capability_set,   0, &arg_capability_bounding_set           },
+                { "Manager", "NoNewPrivileges",           config_parse_bool,             0, &arg_no_new_privs                      },
 #if HAVE_SECCOMP
                 { "Manager", "SystemCallArchitectures",   config_parse_syscall_archs,    0, &arg_syscall_archs                     },
 #endif
@@ -685,22 +674,22 @@ static int parse_config_file(void) {
                 { "Manager", "DefaultStartLimitIntervalSec",config_parse_sec,            0, &arg_default_start_limit_interval      },
                 { "Manager", "DefaultStartLimitBurst",    config_parse_unsigned,         0, &arg_default_start_limit_burst         },
                 { "Manager", "DefaultEnvironment",        config_parse_environ,          0, &arg_default_environment               },
-                { "Manager", "DefaultLimitCPU",           config_parse_limit,            RLIMIT_CPU, arg_default_rlimit            },
-                { "Manager", "DefaultLimitFSIZE",         config_parse_limit,            RLIMIT_FSIZE, arg_default_rlimit          },
-                { "Manager", "DefaultLimitDATA",          config_parse_limit,            RLIMIT_DATA, arg_default_rlimit           },
-                { "Manager", "DefaultLimitSTACK",         config_parse_limit,            RLIMIT_STACK, arg_default_rlimit          },
-                { "Manager", "DefaultLimitCORE",          config_parse_limit,            RLIMIT_CORE, arg_default_rlimit           },
-                { "Manager", "DefaultLimitRSS",           config_parse_limit,            RLIMIT_RSS, arg_default_rlimit            },
-                { "Manager", "DefaultLimitNOFILE",        config_parse_limit,            RLIMIT_NOFILE, arg_default_rlimit         },
-                { "Manager", "DefaultLimitAS",            config_parse_limit,            RLIMIT_AS, arg_default_rlimit             },
-                { "Manager", "DefaultLimitNPROC",         config_parse_limit,            RLIMIT_NPROC, arg_default_rlimit          },
-                { "Manager", "DefaultLimitMEMLOCK",       config_parse_limit,            RLIMIT_MEMLOCK, arg_default_rlimit        },
-                { "Manager", "DefaultLimitLOCKS",         config_parse_limit,            RLIMIT_LOCKS, arg_default_rlimit          },
-                { "Manager", "DefaultLimitSIGPENDING",    config_parse_limit,            RLIMIT_SIGPENDING, arg_default_rlimit     },
-                { "Manager", "DefaultLimitMSGQUEUE",      config_parse_limit,            RLIMIT_MSGQUEUE, arg_default_rlimit       },
-                { "Manager", "DefaultLimitNICE",          config_parse_limit,            RLIMIT_NICE, arg_default_rlimit           },
-                { "Manager", "DefaultLimitRTPRIO",        config_parse_limit,            RLIMIT_RTPRIO, arg_default_rlimit         },
-                { "Manager", "DefaultLimitRTTIME",        config_parse_limit,            RLIMIT_RTTIME, arg_default_rlimit         },
+                { "Manager", "DefaultLimitCPU",           config_parse_rlimit,           RLIMIT_CPU, arg_default_rlimit            },
+                { "Manager", "DefaultLimitFSIZE",         config_parse_rlimit,           RLIMIT_FSIZE, arg_default_rlimit          },
+                { "Manager", "DefaultLimitDATA",          config_parse_rlimit,           RLIMIT_DATA, arg_default_rlimit           },
+                { "Manager", "DefaultLimitSTACK",         config_parse_rlimit,           RLIMIT_STACK, arg_default_rlimit          },
+                { "Manager", "DefaultLimitCORE",          config_parse_rlimit,           RLIMIT_CORE, arg_default_rlimit           },
+                { "Manager", "DefaultLimitRSS",           config_parse_rlimit,           RLIMIT_RSS, arg_default_rlimit            },
+                { "Manager", "DefaultLimitNOFILE",        config_parse_rlimit,           RLIMIT_NOFILE, arg_default_rlimit         },
+                { "Manager", "DefaultLimitAS",            config_parse_rlimit,           RLIMIT_AS, arg_default_rlimit             },
+                { "Manager", "DefaultLimitNPROC",         config_parse_rlimit,           RLIMIT_NPROC, arg_default_rlimit          },
+                { "Manager", "DefaultLimitMEMLOCK",       config_parse_rlimit,           RLIMIT_MEMLOCK, arg_default_rlimit        },
+                { "Manager", "DefaultLimitLOCKS",         config_parse_rlimit,           RLIMIT_LOCKS, arg_default_rlimit          },
+                { "Manager", "DefaultLimitSIGPENDING",    config_parse_rlimit,           RLIMIT_SIGPENDING, arg_default_rlimit     },
+                { "Manager", "DefaultLimitMSGQUEUE",      config_parse_rlimit,           RLIMIT_MSGQUEUE, arg_default_rlimit       },
+                { "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", "DefaultIOAccounting",       config_parse_bool,             0, &arg_default_io_accounting             },
                 { "Manager", "DefaultIPAccounting",       config_parse_bool,             0, &arg_default_ip_accounting             },
@@ -738,6 +727,10 @@ static void set_manager_defaults(Manager *m) {
 
         assert(m);
 
+        /* Propagates the various default unit property settings into the manager object, i.e. properties that do not
+         * affect the manager itself, but are just what newly allocated units will have set if they haven't set
+         * anything else. (Also see set_manager_settings() for the settings that affect the manager's own behaviour) */
+
         m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
         m->default_std_output = arg_default_std_output;
         m->default_std_error = arg_default_std_error;
@@ -762,6 +755,9 @@ static void set_manager_settings(Manager *m) {
 
         assert(m);
 
+        /* Propagates the various manager settings into the manager object, i.e. properties that effect the manager
+         * itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */
+
         m->confirm_spawn = arg_confirm_spawn;
         m->service_watchdogs = arg_service_watchdogs;
         m->runtime_watchdog = arg_runtime_watchdog;
@@ -772,7 +768,6 @@ static void set_manager_settings(Manager *m) {
 }
 
 static int parse_argv(int argc, char *argv[]) {
-
         enum {
                 ARG_LOG_LEVEL = 0x100,
                 ARG_LOG_TARGET,
@@ -785,6 +780,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_PAGER,
                 ARG_VERSION,
                 ARG_DUMP_CONFIGURATION_ITEMS,
+                ARG_DUMP_BUS_PROPERTIES,
                 ARG_DUMP_CORE,
                 ARG_CRASH_CHVT,
                 ARG_CRASH_SHELL,
@@ -812,6 +808,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "help",                     no_argument,       NULL, 'h'                          },
                 { "version",                  no_argument,       NULL, ARG_VERSION                  },
                 { "dump-configuration-items", no_argument,       NULL, ARG_DUMP_CONFIGURATION_ITEMS },
+                { "dump-bus-properties",      no_argument,       NULL, ARG_DUMP_BUS_PROPERTIES      },
                 { "dump-core",                optional_argument, NULL, ARG_DUMP_CORE                },
                 { "crash-chvt",               required_argument, NULL, ARG_CRASH_CHVT               },
                 { "crash-shell",              optional_argument, NULL, ARG_CRASH_SHELL              },
@@ -931,6 +928,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
                         break;
 
+                case ARG_DUMP_BUS_PROPERTIES:
+                        arg_action = ACTION_DUMP_BUS_PROPERTIES;
+                        break;
+
                 case ARG_DUMP_CORE:
                         if (!optarg)
                                 arg_dump_core = true;
@@ -988,10 +989,8 @@ static int parse_argv(int argc, char *argv[]) {
                 case ARG_SHOW_STATUS:
                         if (optarg) {
                                 r = parse_show_status(optarg, &arg_show_status);
-                                if (r < 0) {
-                                        log_error("Failed to parse show status boolean %s.", optarg);
-                                        return r;
-                                }
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to parse show status boolean: %s", optarg);
                         } else
                                 arg_show_status = SHOW_STATUS_YES;
                         break;
@@ -1074,6 +1073,7 @@ static int help(void) {
                "     --test                      Determine startup sequence, dump it and exit\n"
                "     --no-pager                  Do not pipe output into a pager\n"
                "     --dump-configuration-items  Dump understood unit configuration items\n"
+               "     --dump-bus-properties       Dump exposed bus properties\n"
                "     --unit=UNIT                 Set default unit\n"
                "     --system                    Run a system instance, even if PID != 1\n"
                "     --user                      Run a user instance\n"
@@ -1130,20 +1130,14 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
         if (r < 0)
                 return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m");
 
-        *_f = f;
-        *_fds = fds;
-
-        f = NULL;
-        fds = NULL;
+        *_f = TAKE_PTR(f);
+        *_fds = TAKE_PTR(fds);
 
         return 0;
 }
 
 static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
-        struct rlimit nl;
-        int r;
-        int min_max;
-        _cleanup_free_ char *nr_open = NULL;
+        int r, nr;
 
         assert(saved_rlimit);
 
@@ -1164,17 +1158,9 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
                 arg_default_rlimit[RLIMIT_NOFILE] = rl;
         }
 
-        /* Get current RLIMIT_NOFILE maximum compiled into the kernel. */
-        r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
-        if (r >= 0)
-                r = safe_atoi(nr_open, &min_max);
-        /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
-        if (r < 0)
-                min_max = 1024 * 1024;
-
-        /* Bump up the resource limit for ourselves substantially */
-        nl.rlim_cur = nl.rlim_max = min_max;
-        r = setrlimit_closest(RLIMIT_NOFILE, &nl);
+        /* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */
+        nr = read_nr_open();
+        r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
         if (r < 0)
                 return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m");
 
@@ -1229,23 +1215,18 @@ static int enforce_syscall_archs(Set *archs) {
 
 static int status_welcome(void) {
         _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
-        const char *fn;
         int r;
 
-        if (arg_show_status <= 0)
+        if (IN_SET(arg_show_status, SHOW_STATUS_NO, SHOW_STATUS_AUTO))
                 return 0;
 
-        FOREACH_STRING(fn, "/etc/os-release", "/usr/lib/os-release") {
-                r = parse_env_file(fn, NEWLINE,
-                                   "PRETTY_NAME", &pretty_name,
-                                   "ANSI_COLOR", &ansi_color,
-                                   NULL);
-
-                if (r != -ENOENT)
-                        break;
-        }
-        if (r < 0 && r != -ENOENT)
-                log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
+        r = parse_os_release(NULL,
+                             "PRETTY_NAME", &pretty_name,
+                             "ANSI_COLOR", &ansi_color,
+                             NULL);
+        if (r < 0)
+                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+                               "Failed to read os-release file, ignoring: %m");
 
         if (log_get_show_color())
                 return status_printf(NULL, false, false,
@@ -1279,10 +1260,9 @@ static int bump_unix_max_dgram_qlen(void) {
         unsigned long v;
         int r;
 
-        /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel
-         * default of 16 is simply too low. We set the value really
-         * really early during boot, so that it is actually applied to
-         * all our sockets, including the $NOTIFY_SOCKET one. */
+        /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel default of 16 is simply too low. We set the value
+         * really really early during boot, so that it is actually applied to all our sockets, including the
+         * $NOTIFY_SOCKET one. */
 
         r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
         if (r < 0)
@@ -1290,16 +1270,12 @@ static int bump_unix_max_dgram_qlen(void) {
 
         r = safe_atolu(qlen, &v);
         if (r < 0)
-                return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m");
+                return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length '%s', ignoring: %m", qlen);
 
         if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
                 return 0;
 
-        qlen = mfree(qlen);
-        if (asprintf(&qlen, "%lu\n", DEFAULT_UNIX_MAX_DGRAM_QLEN) < 0)
-                return log_oom();
-
-        r = write_string_file("/proc/sys/net/unix/max_dgram_qlen", qlen, 0);
+        r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", 0, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN);
         if (r < 0)
                 return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
                                       "Failed to bump AF_UNIX datagram queue length, ignoring: %m");
@@ -1487,7 +1463,7 @@ static void initialize_clock(void) {
 }
 
 static void initialize_coredump(bool skip_setup) {
-
+#if ENABLE_COREDUMP
         if (getpid_cached() != 1)
                 return;
 
@@ -1500,6 +1476,7 @@ static void initialize_coredump(bool skip_setup) {
          * until the systemd-coredump tool is enabled via sysctl. */
         if (!skip_setup)
                 disable_coredumps();
+#endif
 }
 
 static void do_reexecute(
@@ -1656,20 +1633,35 @@ static int invoke_main_loop(
 
                 switch (m->exit_code) {
 
-                case MANAGER_RELOAD:
+                case MANAGER_RELOAD: {
+                        LogTarget saved_log_target;
+                        int saved_log_level;
+
                         log_info("Reloading.");
 
+                        /* First, save any overridden log level/target, then parse the configuration file, which might
+                         * change the log level to new settings. */
+
+                        saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
+                        saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
+
                         r = parse_config_file();
                         if (r < 0)
                                 log_warning_errno(r, "Failed to parse config file, ignoring: %m");
 
                         set_manager_defaults(m);
 
+                        if (saved_log_level >= 0)
+                                manager_override_log_level(m, saved_log_level);
+                        if (saved_log_target >= 0)
+                                manager_override_log_target(m, saved_log_target);
+
                         r = manager_reload(m);
                         if (r < 0)
                                 log_warning_errno(r, "Failed to reload, ignoring: %m");
 
                         break;
+                }
 
                 case MANAGER_REEXECUTE:
 
@@ -1865,6 +1857,13 @@ static int initialize_runtime(
                 }
         }
 
+        if (arg_system && arg_no_new_privs) {
+                if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+                        *ret_error_message = "Failed to disable new privileges";
+                        return log_emergency_errno(errno, "Failed to disable new privileges: %m");
+                }
+        }
+
         if (arg_syscall_archs) {
                 r = enforce_syscall_archs(arg_syscall_archs);
                 if (r < 0) {
@@ -1898,28 +1897,15 @@ static int do_queue_default_job(
 
         log_debug("Activating default unit: %s", arg_default_unit);
 
-        r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
-        if (r < 0)
-                log_error("Failed to load default target: %s", bus_error_message(&error, r));
-        else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND))
-                log_error_errno(target->load_error, "Failed to load default target: %m");
-        else if (target->load_state == UNIT_MASKED)
-                log_error("Default target masked.");
-
-        if (!target || target->load_state != UNIT_LOADED) {
-                log_info("Trying to load rescue target...");
+        r = manager_load_startable_unit_or_warn(m, arg_default_unit, NULL, &target);
+        if (r < 0) {
+                log_info("Falling back to rescue target: " SPECIAL_RESCUE_TARGET);
 
-                r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
+                r = manager_load_startable_unit_or_warn(m, SPECIAL_RESCUE_TARGET, NULL, &target);
                 if (r < 0) {
-                        *ret_error_message = "Failed to load rescue target";
-                        return log_emergency_errno(r, "Failed to load rescue target: %s", bus_error_message(&error, r));
-                } else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND)) {
-                        *ret_error_message = "Failed to load rescue target";
-                        return log_emergency_errno(target->load_error, "Failed to load rescue target: %m");
-                } else if (target->load_state == UNIT_MASKED) {
-                        *ret_error_message = "Rescue target masked";
-                        log_emergency("Rescue target masked.");
-                        return -ERFKILL;
+                        *ret_error_message = r == -ERFKILL ? "Rescue target masked"
+                                                           : "Failed to load rescue target";
+                        return r;
                 }
         }
 
@@ -1948,12 +1934,9 @@ static int do_queue_default_job(
 }
 
 static void free_arguments(void) {
-        size_t j;
 
         /* Frees all arg_* variables, with the exception of arg_serialization */
-
-        for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++)
-                arg_default_rlimit[j] = mfree(arg_default_rlimit[j]);
+        rlimit_free_all(arg_default_rlimit);
 
         arg_default_unit = mfree(arg_default_unit);
         arg_confirm_spawn = mfree(arg_confirm_spawn);
@@ -2000,7 +1983,7 @@ static int load_configuration(int argc, char **argv, const char **ret_error_mess
         }
 
         /* Initialize the show status setting if it hasn't been set explicitly yet */
-        if (arg_show_status == _SHOW_STATUS_UNSET)
+        if (arg_show_status == _SHOW_STATUS_INVALID)
                 arg_show_status = SHOW_STATUS_YES;
 
         return 0;
@@ -2150,7 +2133,6 @@ static bool early_skip_setup_check(int argc, char *argv[]) {
          * anyway, even if in that case we also do deserialization. */
 
         for (i = 1; i < argc; i++) {
-
                 if (streq(argv[i], "--switched-root"))
                         return false; /* If we switched root, don't skip the setup. */
                 else if (streq(argv[i], "--deserialize"))
@@ -2199,11 +2181,14 @@ int main(int argc, char *argv[]) {
         log_set_upgrade_syslog_to_journal(true);
 
         if (getpid_cached() == 1) {
+                /* When we run as PID 1 force system mode */
+                arg_system = true;
+
                 /* Disable the umask logic */
                 umask(0);
 
-                /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be activated
-                 * yet (even though the log socket for it exists). */
+                /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be
+                 * activated yet (even though the log socket for it exists). */
                 log_set_prohibit_ipc(true);
 
                 /* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
@@ -2211,62 +2196,68 @@ int main(int argc, char *argv[]) {
                  * child process right before execve()'ing the actual binary, at a point in time where socket
                  * activation stderr/stdout area already set up. */
                 log_set_always_reopen_console(true);
-        }
 
-        if (getpid_cached() == 1 && detect_container() <= 0) {
+                if (detect_container() <= 0) {
 
-                /* Running outside of a container as PID 1 */
-                arg_system = true;
-                log_set_target(LOG_TARGET_KMSG);
-                log_open();
+                        /* Running outside of a container as PID 1 */
+                        log_set_target(LOG_TARGET_KMSG);
+                        log_open();
 
-                if (in_initrd())
-                        initrd_timestamp = userspace_timestamp;
+                        if (in_initrd())
+                                initrd_timestamp = userspace_timestamp;
 
-                if (!skip_setup) {
-                        r = mount_setup_early();
-                        if (r < 0) {
-                                error_message = "Failed to mount early API filesystems";
-                                goto finish;
+                        if (!skip_setup) {
+                                r = mount_setup_early();
+                                if (r < 0) {
+                                        error_message = "Failed to mount early API filesystems";
+                                        goto finish;
+                                }
+
+                                r = initialize_security(
+                                                &loaded_policy,
+                                                &security_start_timestamp,
+                                                &security_finish_timestamp,
+                                                &error_message);
+                                if (r < 0)
+                                        goto finish;
                         }
 
-                        r = initialize_security(
-                                        &loaded_policy,
-                                        &security_start_timestamp,
-                                        &security_finish_timestamp,
-                                        &error_message);
-                        if (r < 0)
+                        if (mac_selinux_init() < 0) {
+                                error_message = "Failed to initialize SELinux policy";
                                 goto finish;
-                }
+                        }
 
-                if (mac_selinux_init() < 0) {
-                        error_message = "Failed to initialize SELinux policy";
-                        goto finish;
+                        if (!skip_setup)
+                                initialize_clock();
+
+                        /* 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 {
+                        /* Running inside a container, as PID 1 */
+                        log_set_target(LOG_TARGET_CONSOLE);
+                        log_open();
+
+                        /* For later on, see above... */
+                        log_set_target(LOG_TARGET_JOURNAL);
+
+                        /* clear the kernel timestamp,
+                         * because we are in a container */
+                        kernel_timestamp = DUAL_TIMESTAMP_NULL;
                 }
 
-                if (!skip_setup)
-                        initialize_clock();
-
-                /* 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_cached() == 1) {
-                /* Running inside a container, as PID 1 */
-                arg_system = true;
-                log_set_target(LOG_TARGET_CONSOLE);
-                log_open();
+                initialize_coredump(skip_setup);
 
-                /* For later on, see above... */
-                log_set_target(LOG_TARGET_JOURNAL);
+                r = fixup_environment();
+                if (r < 0) {
+                        log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
+                        error_message = "Failed to fix up PID1 environment";
+                        goto finish;
+                }
 
-                /* clear the kernel timestamp,
-                 * because we are in a container */
-                kernel_timestamp = DUAL_TIMESTAMP_NULL;
         } else {
                 /* Running as user instance */
                 arg_system = false;
@@ -2278,24 +2269,14 @@ int main(int argc, char *argv[]) {
                 kernel_timestamp = DUAL_TIMESTAMP_NULL;
         }
 
-        initialize_coredump(skip_setup);
-
-        r = fixup_environment();
-        if (r < 0) {
-                log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
-                error_message = "Failed to fix up PID1 environment";
-                goto finish;
-        }
-
         if (arg_system) {
-
-                /* Try to figure out if we can use colors with the console. No
-                 * need to do that for user instances since they never log
-                 * into the console. */
+                /* Try to figure out if we can use colors with the console. No need to do that for user instances since
+                 * they never log into the console. */
                 log_show_color(colors_enabled());
+
                 r = make_null_stdio();
                 if (r < 0)
-                        log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
+                        log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m");
         }
 
         /* Mount /proc, /sys and friends, so that /proc/cmdline and
@@ -2325,8 +2306,8 @@ int main(int argc, char *argv[]) {
         if (r < 0)
                 goto finish;
 
-        if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS))
-                pager_open(arg_no_pager, false);
+        if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES))
+                (void) pager_open(arg_no_pager, false);
 
         if (arg_action != ACTION_RUN)
                 skip_setup = true;
@@ -2341,6 +2322,10 @@ int main(int argc, char *argv[]) {
                 unit_dump_config_items(stdout);
                 retval = EXIT_SUCCESS;
                 goto finish;
+        } else if (arg_action == ACTION_DUMP_BUS_PROPERTIES) {
+                dump_bus_properties(stdout);
+                retval = EXIT_SUCCESS;
+                goto finish;
         }
 
         assert_se(IN_SET(arg_action, ACTION_RUN, ACTION_TEST));
@@ -2386,8 +2371,8 @@ int main(int argc, char *argv[]) {
         m->timestamps[MANAGER_TIMESTAMP_KERNEL] = kernel_timestamp;
         m->timestamps[MANAGER_TIMESTAMP_INITRD] = initrd_timestamp;
         m->timestamps[MANAGER_TIMESTAMP_USERSPACE] = userspace_timestamp;
-        m->timestamps[MANAGER_TIMESTAMP_SECURITY_START] = security_start_timestamp;
-        m->timestamps[MANAGER_TIMESTAMP_SECURITY_FINISH] = security_finish_timestamp;
+        m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_START)] = security_start_timestamp;
+        m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_FINISH)] = security_finish_timestamp;
 
         set_manager_defaults(m);
         set_manager_settings(m);
@@ -2439,10 +2424,10 @@ int main(int argc, char *argv[]) {
 finish:
         pager_close();
 
-        if (m)
+        if (m) {
                 arg_shutdown_watchdog = m->shutdown_watchdog;
-
-        m = manager_free(m);
+                m = manager_free(m);
+        }
 
         free_arguments();
         mac_selinux_finish();
@@ -2469,13 +2454,12 @@ finish:
                  * in become_shutdown() so normally we cannot free them yet. */
                 watchdog_free_device();
                 arg_watchdog_device = mfree(arg_watchdog_device);
-                return 0;
+                return retval;
         }
 #endif
 
         if (shutdown_verb) {
                 r = become_shutdown(shutdown_verb, retval);
-
                 log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting");
                 error_message = "Failed to execute shutdown binary";
         }