X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fmain.c;h=7c66665e843957f931149bc12e166467f40ffae4;hb=ca5dc4b67dd6956bea663ade032352a58bf163c6;hp=486dac8a8aa2487b0a225c7038b64c2ee3b097d3;hpb=2660882b52ae1a5d97a2344633a999d88a3cd45b;p=elogind.git diff --git a/src/core/main.c b/src/core/main.c index 486dac8a8..7c66665e8 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -50,6 +50,7 @@ #include "watchdog.h" #include "path-util.h" #include "switch-root.h" +#include "capability.h" #include "mount-setup.h" #include "loopback-setup.h" @@ -77,15 +78,16 @@ static bool arg_crash_shell = false; static int arg_crash_chvt = -1; static bool arg_confirm_spawn = false; static bool arg_show_status = true; -#ifdef HAVE_SYSV_COMPAT -static bool arg_sysv_console = true; -#endif +static bool arg_switched_root = false; static char **arg_default_controllers = NULL; static char ***arg_join_controllers = NULL; static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; static usec_t arg_runtime_watchdog = 0; static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; +static struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {}; +static uint64_t arg_capability_bounding_set_drop = 0; +static nsec_t arg_timer_slack_nsec = (nsec_t) -1; static FILE* serialization = NULL; @@ -167,7 +169,7 @@ _noreturn_ static void crash(int sig) { else if (pid == 0) { int fd, r; - if ((fd = acquire_terminal("/dev/console", false, true, true)) < 0) + if ((fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1)) < 0) log_error("Failed to acquire terminal: %s", strerror(-fd)); else if ((r = make_stdio(fd)) < 0) log_error("Failed to duplicate terminal fd: %s", strerror(-r)); @@ -228,11 +230,13 @@ static int set_default_unit(const char *u) { assert(u); - if (!(c = strdup(u))) + c = strdup(u); + if (!c) return -ENOMEM; free(arg_default_unit); arg_default_unit = c; + return 0; } @@ -254,10 +258,17 @@ static int parse_proc_cmdline_word(const char *word) { assert(word); - if (startswith(word, "systemd.unit=")) - return set_default_unit(word + 13); + if (startswith(word, "systemd.unit=")) { + + if (!in_initrd()) + return set_default_unit(word + 13); + + } else if (startswith(word, "rd.systemd.unit=")) { + + if (in_initrd()) + return set_default_unit(word + 16); - else if (startswith(word, "systemd.log_target=")) { + } else if (startswith(word, "systemd.log_target=")) { if (log_set_target_from_string(word + 19) < 0) log_warning("Failed to parse log target %s. Ignoring.", word + 19); @@ -350,30 +361,20 @@ static int parse_proc_cmdline_word(const char *word) { log_warning("setenv failed %s. Ignoring.", strerror(errno)); } free(cenv); -#ifdef HAVE_SYSV_COMPAT - } else if (startswith(word, "systemd.sysv_console=")) { - int r; - - if ((r = parse_boolean(word + 21)) < 0) - log_warning("Failed to parse SysV console switch %s. Ignoring.", word + 20); - else - arg_sysv_console = r; -#endif - } else if (startswith(word, "systemd.")) { + } else if (startswith(word, "systemd.") || + (in_initrd() && startswith(word, "rd.systemd."))) { log_warning("Unknown kernel switch %s. Ignoring.", word); log_info("Supported kernel switches:\n" "systemd.unit=UNIT Default unit to start\n" + "rd.systemd.unit=UNIT Default unit to start when run in initrd\n" "systemd.dump_core=0|1 Dump core on crash\n" "systemd.crash_shell=0|1 Run shell on crash\n" "systemd.crash_chvt=N Change to VT #N on crash\n" "systemd.confirm_spawn=0|1 Confirm every process spawn\n" "systemd.show_status=0|1 Show status updates on the console during bootup\n" -#ifdef HAVE_SYSV_COMPAT - "systemd.sysv_console=0|1 Connect output of SysV scripts to console\n" -#endif "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n" " Log target\n" "systemd.log_level=LEVEL Log level\n" @@ -382,14 +383,12 @@ static int parse_proc_cmdline_word(const char *word) { "systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n" " Set default log output for services\n" "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n" - " Set default log error output for services\n"); + " Set default log error output for services\n" + "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n"); - } else if (streq(word, "quiet")) { + } else if (streq(word, "quiet")) arg_show_status = false; -#ifdef HAVE_SYSV_COMPAT - arg_sysv_console = false; -#endif - } else { + else if (!in_initrd()) { unsigned i; /* SysV compatibility */ @@ -655,9 +654,6 @@ static int parse_config_file(void) { { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core }, { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell }, { "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status }, -#ifdef HAVE_SYSV_COMPAT - { "Manager", "SysVConsole", config_parse_bool, 0, &arg_sysv_console }, -#endif { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt }, { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL }, { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers }, @@ -666,6 +662,24 @@ static int parse_config_file(void) { { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, { "Manager", "RuntimeWatchdogSec", config_parse_usec, 0, &arg_runtime_watchdog }, { "Manager", "ShutdownWatchdogSec", config_parse_usec, 0, &arg_shutdown_watchdog }, + { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop }, + { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec }, + { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU]}, + { "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE]}, + { "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA]}, + { "Manager", "DefaultLimitSTACK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_STACK]}, + { "Manager", "DefaultLimitCORE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CORE]}, + { "Manager", "DefaultLimitRSS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RSS]}, + { "Manager", "DefaultLimitNOFILE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NOFILE]}, + { "Manager", "DefaultLimitAS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_AS]}, + { "Manager", "DefaultLimitNPROC", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NPROC]}, + { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK]}, + { "Manager", "DefaultLimitLOCKS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_LOCKS]}, + { "Manager", "DefaultLimitSIGPENDING",config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING]}, + { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE]}, + { "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE]}, + { "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO]}, + { "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME]}, { NULL, NULL, NULL, 0, NULL } }; @@ -745,7 +759,6 @@ static int parse_argv(int argc, char *argv[]) { ARG_CRASH_SHELL, ARG_CONFIRM_SPAWN, ARG_SHOW_STATUS, - ARG_SYSV_CONSOLE, ARG_DESERIALIZE, ARG_SWITCHED_ROOT, ARG_INTROSPECT, @@ -768,9 +781,6 @@ static int parse_argv(int argc, char *argv[]) { { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL }, { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN }, { "show-status", optional_argument, NULL, ARG_SHOW_STATUS }, -#ifdef HAVE_SYSV_COMPAT - { "sysv-console", optional_argument, NULL, ARG_SYSV_CONSOLE }, -#endif { "deserialize", required_argument, NULL, ARG_DESERIALIZE }, { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT }, { "introspect", optional_argument, NULL, ARG_INTROSPECT }, @@ -911,17 +921,6 @@ static int parse_argv(int argc, char *argv[]) { arg_show_status = r; break; -#ifdef HAVE_SYSV_COMPAT - case ARG_SYSV_CONSOLE: - r = optarg ? parse_boolean(optarg) : 1; - if (r < 0) { - log_error("Failed to parse SysV console boolean %s.", optarg); - return r; - } - arg_sysv_console = r; - break; -#endif - case ARG_DESERIALIZE: { int fd; FILE *f; @@ -945,7 +944,7 @@ static int parse_argv(int argc, char *argv[]) { } case ARG_SWITCHED_ROOT: - /* Nothing special yet */ + arg_switched_root = true; break; case ARG_INTROSPECT: { @@ -1037,9 +1036,6 @@ static int help(void) { " --crash-shell[=0|1] Run shell on crash\n" " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n" " --show-status[=0|1] Show status updates on the console during bootup\n" -#ifdef HAVE_SYSV_COMPAT - " --sysv-console[=0|1] Connect output of SysV scripts to console\n" -#endif " --log-target=TARGET Set log target (console, journal, syslog, kmsg, journal-or-kmsg, syslog-or-kmsg, null)\n" " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n" " --log-color[=0|1] Highlight important log messages\n" @@ -1188,6 +1184,7 @@ int main(int argc, char *argv[]) { int j; bool loaded_policy = false; bool arm_reboot_watchdog = false; + bool queue_default_job = false; char *switch_root_dir = NULL, *switch_root_init = NULL; #ifdef HAVE_SYSV_COMPAT @@ -1455,6 +1452,23 @@ int main(int argc, char *argv[]) { if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0) watchdog_set_timeout(&arg_runtime_watchdog); + if (arg_timer_slack_nsec != (nsec_t) -1) + if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0) + log_error("Failed to adjust timer slack: %m"); + + if (arg_capability_bounding_set_drop) { + r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true); + if (r < 0) { + log_error("Failed to drop capability bounding set: %s", strerror(-r)); + goto finish; + } + r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop); + if (r < 0) { + log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r)); + goto finish; + } + } + r = manager_new(arg_running_as, &m); if (r < 0) { log_error("Failed to allocate manager object: %s", strerror(-r)); @@ -1462,14 +1476,13 @@ int main(int argc, char *argv[]) { } m->confirm_spawn = arg_confirm_spawn; -#ifdef HAVE_SYSV_COMPAT - m->sysv_console = arg_sysv_console; -#endif m->default_std_output = arg_default_std_output; m->default_std_error = arg_default_std_error; m->runtime_watchdog = arg_runtime_watchdog; m->shutdown_watchdog = arg_shutdown_watchdog; + manager_set_default_rlimits(m, arg_default_rlimit); + if (dual_timestamp_is_set(&initrd_timestamp)) m->initrd_timestamp = initrd_timestamp; @@ -1478,16 +1491,18 @@ int main(int argc, char *argv[]) { manager_set_show_status(m, arg_show_status); + /* Remember whether we should queue the default job */ + queue_default_job = !serialization || arg_switched_root; + before_startup = now(CLOCK_MONOTONIC); r = manager_startup(m, serialization, fds); if (r < 0) log_error("Failed to fully start up daemon: %s", strerror(-r)); + /* This will close all file descriptors that were opened, but + * not claimed by any unit. */ if (fds) { - /* This will close all file descriptors that were opened, but - * not claimed by any unit. */ - fdset_free(fds); fds = NULL; } @@ -1495,7 +1510,9 @@ int main(int argc, char *argv[]) { if (serialization) { fclose(serialization); serialization = NULL; - } else { + } + + if (queue_default_job) { DBusError error; Unit *target = NULL; Job *default_unit_job; @@ -1629,6 +1646,9 @@ finish: if (m) manager_free(m); + for (j = 0; j < RLIMIT_NLIMITS; j++) + free (arg_default_rlimit[j]); + free(arg_default_unit); strv_free(arg_default_controllers); free_join_controllers(); @@ -1711,12 +1731,15 @@ finish: args[0] = "/sbin/init"; execv(args[0], (char* const*) args); - log_warning("Failed to execute /sbin/init, trying fallback: %m"); + if (errno == ENOENT) { + log_warning("No /sbin/init, trying fallback"); - args[0] = "/bin/sh"; - args[1] = NULL; - execv(args[0], (char* const*) args); - log_error("Failed to execute /bin/sh, giving up: %m"); + args[0] = "/bin/sh"; + args[1] = NULL; + execv(args[0], (char* const*) args); + log_error("Failed to execute /bin/sh, giving up: %m"); + } else + log_warning("Failed to execute /sbin/init, giving up: %m"); } if (serialization)