Merge pull request #28127 from poettering/coredump-loop-read

coredump: fixes with overly large coredumps
This commit is contained in:
Luca Boccassi
2023-06-23 12:28:40 +01:00
committed by GitHub
3 changed files with 35 additions and 14 deletions
+7 -4
View File
@@ -97,11 +97,14 @@
<term><varname>ExternalSizeMax=</varname></term>
<term><varname>JournalSizeMax=</varname></term>
<listitem><para>The maximum (compressed or uncompressed) size in bytes of a core to be saved in
separate files on disk (default: 1G on 32bit, 32G on 64bit systems) or in the journal (default:
10M). Unit suffixes are allowed just as in <option>ProcessSizeMax=</option>.</para></listitem>
<listitem><para>The maximum (compressed or uncompressed) size in bytes of a coredump to be saved in
separate files on disk (default: 1G on 32-bit systems, 32G on 64-bit systems) or in the journal
(default: 767M). Note that the journal service enforces a hard limit on journal log records of 767M,
and will ignore larger submitted log records. Hence, <varname>JournalSizeMax=</varname> may be
lowered relative to the default, but not increased. Unit suffixes are allowed just as in
<option>ProcessSizeMax=</option>.</para>
<para><varname>ExternalSizeMax=infinity</varname> sets the core size to unlimited.</para>
<para><varname>ExternalSizeMax=infinity</varname> sets the core size to unlimited.</para></listitem>
</varlistentry>
<varlistentry>
+1 -2
View File
@@ -54,8 +54,7 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
assert(fd >= 0);
/* If called with nbytes == 0, let's call read() at least
* once, to validate the operation */
/* If called with nbytes == 0, let's call read() at least once, to validate the operation */
if (nbytes > (size_t) SSIZE_MAX)
return -EINVAL;
+27 -8
View File
@@ -172,9 +172,27 @@ static int parse_config(void) {
{}
};
return config_parse_config_file("coredump.conf", "Coredump\0",
config_item_table_lookup, items,
CONFIG_PARSE_WARN, NULL);
int r;
r = config_parse_config_file(
"coredump.conf",
"Coredump\0",
config_item_table_lookup,
items,
CONFIG_PARSE_WARN,
/* userdata= */ NULL);
if (r < 0)
return r;
/* Let's make sure we fix up the maximum size we send to the journal here on the client side, for
* efficiency reasons. journald wouldn't accept anything larger anyway. */
if (arg_journal_size_max > JOURNAL_SIZE_MAX) {
log_warning("JournalSizeMax= set to larger value (%s) than journald would accept (%s), lowering automatically.",
FORMAT_BYTES(arg_journal_size_max), FORMAT_BYTES(JOURNAL_SIZE_MAX));
arg_journal_size_max = JOURNAL_SIZE_MAX;
}
return 0;
}
static uint64_t storage_size_max(void) {
@@ -604,14 +622,15 @@ static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_s
return log_warning_errno(errno, "Failed to seek: %m");
field = malloc(9 + size);
if (!field) {
log_warning("Failed to allocate memory for coredump, coredump will not be stored.");
return -ENOMEM;
}
if (!field)
return log_warning_errno(SYNTHETIC_ERRNO(ENOMEM),
"Failed to allocate memory for coredump, coredump will not be stored.");
memcpy(field, "COREDUMP=", 9);
n = read(fd, field + 9, size);
/* NB: simple read() would fail for overly large coredumps, since read() on Linux can only deal with
* 0x7ffff000 bytes max. Hence call things in a loop. */
n = loop_read(fd, field + 9, size, /* do_poll= */ false);
if (n < 0)
return log_error_errno((int) n, "Failed to read core data: %m");
if ((size_t) n < size)