diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index 0545f9d84b..43b3a3667e 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -55,6 +55,7 @@
systemd.unit=
rd.systemd.unit=
systemd.dump_core
+ systemd.early_core_pattern=
systemd.crash_chvt
systemd.crash_shell
systemd.crash_reboot
@@ -90,6 +91,16 @@
+
+ systemd.early_core_pattern=
+
+ During early boot, the generation of core dump files is disabled until a core dump handler (if any)
+ takes over. This parameter allows to specifies an absolute path where core dump files should be stored until
+ a handler is installed. The path should be absolute and may contain specifiers, see
+ core5 for details.
+
+
+
systemd.restore_state=
diff --git a/src/core/main.c b/src/core/main.c
index 078decb432..ce45f2ded2 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -109,6 +109,7 @@ static usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL;
static unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST;
static usec_t arg_runtime_watchdog = 0;
static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
+static char *arg_early_core_pattern = NULL;
static char *arg_watchdog_device = NULL;
static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
@@ -351,6 +352,16 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
else
arg_dump_core = r;
+ } else if (proc_cmdline_key_streq(key, "systemd.early_core_pattern")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ if (path_is_absolute(value))
+ (void) parse_path_argument_and_warn(value, false, &arg_early_core_pattern);
+ else
+ log_warning("Specified core pattern '%s' is not an absolute path, ignoring.", value);
+
} else if (proc_cmdline_key_streq(key, "systemd.crash_chvt")) {
if (!value)
@@ -466,7 +477,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
- parse_path_argument_and_warn(value, false, &arg_watchdog_device);
+ (void) parse_path_argument_and_warn(value, false, &arg_watchdog_device);
} else if (streq(key, "quiet") && !value) {
@@ -1482,13 +1493,29 @@ static void initialize_coredump(bool skip_setup) {
if (setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
log_warning_errno(errno, "Failed to set RLIMIT_CORE: %m");
- /* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored
- * until the systemd-coredump tool is enabled via sysctl. */
+ /* But at the same time, turn off the core_pattern logic by default, so that no
+ * coredumps are stored until the systemd-coredump tool is enabled via
+ * sysctl. However it can be changed via the kernel command line later so core
+ * dumps can still be generated during early startup and in initramfs. */
if (!skip_setup)
disable_coredumps();
#endif
}
+static void initialize_core_pattern(bool skip_setup) {
+ int r;
+
+ if (skip_setup || !arg_early_core_pattern)
+ return;
+
+ if (getpid_cached() != 1)
+ return;
+
+ r = write_string_file("/proc/sys/kernel/core_pattern", arg_early_core_pattern, 0);
+ if (r < 0)
+ log_warning_errno(r, "Failed to write '%s' to /proc/sys/kernel/core_pattern, ignoring: %m", arg_early_core_pattern);
+}
+
static void do_reexecute(
int argc,
char *argv[],
@@ -2345,6 +2372,9 @@ int main(int argc, char *argv[]) {
if (arg_action == ACTION_RUN) {
+ /* A core pattern might have been specified via the cmdline. */
+ initialize_core_pattern(skip_setup);
+
/* Close logging fds, in order not to confuse collecting passed fds and terminal logic below */
log_close();