#include <valgrind/valgrind.h>
#endif
-#include "sd-daemon.h"
#include "sd-bus.h"
+#include "sd-daemon.h"
+#include "alloc-util.h"
#include "architecture.h"
#include "build.h"
#include "bus-error.h"
#include "bus-util.h"
-#include "capability.h"
+#include "capability-util.h"
#include "clock-util.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
#include "dbus-manager.h"
#include "def.h"
#include "env-util.h"
+#include "fd-util.h"
#include "fdset.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hostname-setup.h"
#include "ima-setup.h"
#include "killall.h"
#include "missing.h"
#include "mount-setup.h"
#include "pager.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "selinux-setup.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "smack-setup.h"
#include "special.h"
+#include "stat-util.h"
+#include "stdio-util.h"
#include "strv.h"
#include "switch-root.h"
#include "terminal-util.h"
+#include "user-util.h"
#include "virt.h"
#include "watchdog.h"
static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
-static uint64_t arg_capability_bounding_set_drop = 0;
+static uint64_t arg_capability_bounding_set = CAP_ALL;
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 bool arg_default_cpu_accounting = false;
static bool arg_default_blockio_accounting = false;
static bool arg_default_memory_accounting = false;
-static bool arg_default_tasks_accounting = false;
+static bool arg_default_tasks_accounting = true;
+static uint64_t arg_default_tasks_max = UINT64_C(512);
static void pager_open_if_enabled(void) {
}
noreturn static void crash(int sig) {
+ struct sigaction sa;
+ pid_t pid;
if (getpid() != 1)
/* Pass this on immediately, if this is not PID 1 */
else if (!arg_dump_core)
log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig));
else {
- struct sigaction sa = {
+ sa = (struct sigaction) {
.sa_handler = nop_signal_handler,
.sa_flags = SA_NOCLDSTOP|SA_RESTART,
};
- pid_t pid;
/* We want to wait for the core process, hence let's enable SIGCHLD */
(void) sigaction(SIGCHLD, &sa, NULL);
if (arg_crash_chvt >= 0)
(void) chvt(arg_crash_chvt);
- if (arg_crash_shell) {
- struct sigaction sa = {
- .sa_handler = SIG_IGN,
- .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART,
- };
- pid_t pid;
+ sa = (struct sigaction) {
+ .sa_handler = SIG_IGN,
+ .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART,
+ };
+
+ /* Let the kernel reap children for us */
+ (void) sigaction(SIGCHLD, &sa, NULL);
+ if (arg_crash_shell) {
log_notice("Executing crash shell in 10s...");
(void) sleep(10);
- /* Let the kernel reap children for us */
- (void) sigaction(SIGCHLD, &sa, NULL);
-
pid = raw_clone(SIGCHLD, NULL);
if (pid < 0)
log_emergency_errno(errno, "Failed to fork off crash shell: %m");
(void) execle("/bin/sh", "/bin/sh", NULL, environ);
log_emergency_errno(errno, "execle() failed: %m");
- freeze_or_reboot();
_exit(EXIT_FAILURE);
} else {
log_info("Spawned crash shell as PID "PID_FMT".", pid);
- freeze();
+ (void) wait_for_terminate(pid, NULL);
}
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
- static const char * const rlmap[] = {
- "emergency", SPECIAL_EMERGENCY_TARGET,
- "-b", SPECIAL_EMERGENCY_TARGET,
- "rescue", SPECIAL_RESCUE_TARGET,
- "single", SPECIAL_RESCUE_TARGET,
- "-s", SPECIAL_RESCUE_TARGET,
- "s", SPECIAL_RESCUE_TARGET,
- "S", SPECIAL_RESCUE_TARGET,
- "1", SPECIAL_RESCUE_TARGET,
- "2", SPECIAL_MULTI_USER_TARGET,
- "3", SPECIAL_MULTI_USER_TARGET,
- "4", SPECIAL_MULTI_USER_TARGET,
- "5", SPECIAL_GRAPHICAL_TARGET,
- };
int r;
assert(key);
log_set_target(LOG_TARGET_CONSOLE);
} else if (!in_initrd() && !value) {
- unsigned i;
+ const char *target;
/* SysV compatibility */
- for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
- if (streq(key, rlmap[i]))
- return free_and_strdup(&arg_default_unit, rlmap[i+1]);
+ target = runlevel_to_target(key);
+ if (target)
+ return free_and_strdup(&arg_default_unit, target);
}
return 0;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(data);
r = parse_crash_chvt(rvalue);
if (r < 0) {
for (a = arg_join_controllers; *a; a++) {
if (strv_overlap(*a, l)) {
- if (strv_extend_strv(&l, *a) < 0) {
+ if (strv_extend_strv(&l, *a, false) < 0) {
strv_free(l);
strv_free_free(t);
return log_oom();
{ "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
{ "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
- { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
+ { "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
#ifdef HAVE_SECCOMP
{ "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
#endif
{ "Manager", "DefaultStartLimitInterval", 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, 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", "DefaultLimitCPU", config_parse_sec_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
+ { "Manager", "DefaultLimitFSIZE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE] },
+ { "Manager", "DefaultLimitDATA", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_DATA] },
+ { "Manager", "DefaultLimitSTACK", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_STACK] },
+ { "Manager", "DefaultLimitCORE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_CORE] },
+ { "Manager", "DefaultLimitRSS", config_parse_bytes_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", "DefaultLimitAS", config_parse_bytes_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", "DefaultLimitMEMLOCK", config_parse_bytes_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", "DefaultLimitMSGQUEUE", config_parse_bytes_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] },
+ { "Manager", "DefaultLimitRTTIME", config_parse_usec_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
+ { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
{}
};
const char *fn, *conf_dirs_nulstr;
- fn = arg_running_as == MANAGER_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf";
- conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ? CONF_DIRS_NULSTR("systemd/system.conf") : CONF_DIRS_NULSTR("systemd/user.conf");
+ fn = arg_running_as == MANAGER_SYSTEM ?
+ PKGSYSCONFDIR "/system.conf" :
+ PKGSYSCONFDIR "/user.conf";
+
+ conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ?
+ CONF_PATHS_NULSTR("systemd/system.conf.d") :
+ CONF_PATHS_NULSTR("systemd/user.conf.d");
+
config_parse_many(fn, conf_dirs_nulstr, "Manager\0",
config_item_table_lookup, items, false, NULL);
m->default_blockio_accounting = arg_default_blockio_accounting;
m->default_memory_accounting = arg_default_memory_accounting;
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_environment_add(m, NULL, arg_default_environment);
return 0;
}
-static void test_mtab(void) {
-
- static const char ok[] =
- "/proc/self/mounts\0"
- "/proc/mounts\0"
- "../proc/self/mounts\0"
- "../proc/mounts\0";
-
- _cleanup_free_ char *p = NULL;
- int r;
-
- /* Check that /etc/mtab is a symlink to the right place or
- * non-existing. But certainly not a file, or a symlink to
- * some weird place... */
-
- r = readlink_malloc("/etc/mtab", &p);
- if (r == -ENOENT)
- return;
- if (r >= 0 && nulstr_contains(ok, p))
- return;
-
- log_error("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
- "This is not supported anymore. "
- "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
- freeze_or_reboot();
-}
-
static void test_usr(void) {
/* Check that /usr is not a separate fs */
static int write_container_id(void) {
const char *c;
+ int r;
c = getenv("container");
if (isempty(c))
return 0;
- return write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE);
+ r = write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to write /run/systemd/container, ignoring: %m");
+
+ return 1;
+}
+
+static int bump_unix_max_dgram_qlen(void) {
+ _cleanup_free_ char *qlen = NULL;
+ 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. */
+
+ r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to read AF_UNIX datagram queue length, ignoring: %m");
+
+ r = safe_atolu(qlen, &v);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m");
+
+ 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);
+ 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");
+
+ return 1;
}
int main(int argc, char *argv[]) {
hostname_setup();
machine_id_setup(NULL);
loopback_setup();
+ bump_unix_max_dgram_qlen();
- test_mtab();
test_usr();
}
if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
log_error_errno(errno, "Failed to adjust timer slack: %m");
- if (arg_capability_bounding_set_drop) {
- r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
+ if (!cap_test_all(arg_capability_bounding_set)) {
+ r = capability_bounding_set_drop_usermode(arg_capability_bounding_set);
if (r < 0) {
log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m");
error_message = "Failed to drop capability bounding set of usermode helpers";
goto finish;
}
- r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
+ r = capability_bounding_set_drop(arg_capability_bounding_set, true);
if (r < 0) {
log_emergency_errno(r, "Failed to drop capability bounding set: %m");
error_message = "Failed to drop capability bounding set";
if (empty_etc) {
r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, false, NULL, 0);
if (r < 0)
- log_warning_errno(r, "Failed to populate /etc with preset unit settings, ignoring: %m");
+ log_full_errno(r == -EEXIST ? LOG_NOTICE : LOG_WARNING, r, "Failed to populate /etc with preset unit settings, ignoring: %m");
else
log_info("Populated /etc with preset unit settings.");
}
arg_serialization = safe_fclose(arg_serialization);
if (queue_default_job) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Unit *target = NULL;
Job *default_unit_job;
manager_dump_units(m, stdout, "\t");
}
- r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, false, &error, &default_unit_job);
+ r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, &error, &default_unit_job);
if (r == -EPERM) {
log_debug("Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
- r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
+ sd_bus_error_free(&error);
+
+ r = manager_add_job(m, JOB_START, target, JOB_REPLACE, &error, &default_unit_job);
if (r < 0) {
log_emergency("Failed to start default target: %s", bus_error_message(&error, r));
error_message = "Failed to start default target";