Skip to content

Commit e67b008

Browse files
blucapoettering
authored andcommitted
journald: set a lower size limit for FDs from unpriv processes
Unprivileged processes can send 768M in a FD-based message to journald, which will be malloc'ed in one go, likely causing memory issues. Set the limit for unprivileged users to 24M. Allow coredumps as an exception, since we always allowed storing up to the 768M max core files in the journal. Reported on yeswehack.com as #YWH-PGM9780-48
1 parent 775f042 commit e67b008

3 files changed

Lines changed: 53 additions & 1 deletion

File tree

docs/ENVIRONMENT.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,10 @@ SYSTEMD_HOME_DEBUG_SUFFIX=foo \
671671
specified algorithm takes an effect immediately, you need to explicitly run
672672
`journalctl --rotate`.
673673

674+
* `$SYSTEMD_JOURNAL_FD_SIZE_MAX` – Takes a size with the usual suffixes (K, M, ...) in
675+
string format. Overrides the default maximum allowed size for a file-descriptor
676+
based input record to be stored in the journal.
677+
674678
* `$SYSTEMD_CATALOG` – path to the compiled catalog database file to use for
675679
`journalctl -x`, `journalctl --update-catalog`, `journalctl --list-catalog`
676680
and related calls.

src/journal/journald-native.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,52 @@ void manager_process_native_message(
328328
} while (r == 0);
329329
}
330330

331+
static size_t entry_size_max_by_ucred(Manager *m, const struct ucred *ucred, const char *label) {
332+
static uint64_t entry_size_max = UINT64_MAX;
333+
static bool entry_size_max_checked = false;
334+
int r;
335+
336+
if (entry_size_max != UINT64_MAX)
337+
return entry_size_max;
338+
if (!entry_size_max_checked) {
339+
const char *p;
340+
341+
entry_size_max_checked = true;
342+
343+
p = secure_getenv("SYSTEMD_JOURNAL_FD_SIZE_MAX");
344+
if (p) {
345+
r = parse_size(p, 1024, &entry_size_max);
346+
if (r < 0)
347+
log_warning_errno(r, "Failed to parse $SYSTEMD_JOURNAL_FD_SIZE_MAX, ignoring: %m");
348+
else
349+
return entry_size_max;
350+
}
351+
}
352+
353+
/* Check for unprivileged senders, as the default limit of 768M is quite high and the socket is
354+
* unprivileged, to avoid abuses. */
355+
356+
if (!ucred)
357+
return ENTRY_SIZE_UNPRIV_MAX;
358+
if (ucred->uid == 0) /* Shortcut for root senders */
359+
return ENTRY_SIZE_MAX;
360+
361+
/* As an exception, allow coredumps to use the old max size for backward compatibility */
362+
if (pid_is_valid(ucred->pid)) {
363+
ClientContext *context = NULL;
364+
365+
r = client_context_get(m, ucred->pid, ucred, label, /* unit_id= */ NULL, &context);
366+
if (r < 0)
367+
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
368+
"Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
369+
ucred->pid);
370+
else if (context->unit && startswith(context->unit, "systemd-coredump@"))
371+
return ENTRY_SIZE_MAX;
372+
}
373+
374+
return ENTRY_SIZE_UNPRIV_MAX;
375+
}
376+
331377
int manager_process_native_file(
332378
Manager *m,
333379
int fd,
@@ -392,7 +438,7 @@ int manager_process_native_file(
392438

393439
/* When !sealed, set a lower memory limit. We have to read the file, effectively doubling memory
394440
* use. */
395-
if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2))
441+
if ((size_t) st.st_size > entry_size_max_by_ucred(m, ucred, label) / (sealed ? 1 : 2))
396442
return log_ratelimit_error_errno(SYNTHETIC_ERRNO(EFBIG), JOURNAL_LOG_RATELIMIT,
397443
"File passed too large (%"PRIu64" bytes), refusing.",
398444
(uint64_t) st.st_size);

src/shared/journal-importer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
* See JOURNAL_SIZE_MAX in coredump.c */
1313
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1414
#define ENTRY_SIZE_MAX (1024*1024*770u)
15+
#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*32u)
1516
#define DATA_SIZE_MAX (1024*1024*768u)
1617
#else
1718
#define ENTRY_SIZE_MAX (1024*1024*13u)
19+
#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*8u)
1820
#define DATA_SIZE_MAX (1024*1024*11u)
1921
#endif
2022
#define LINE_CHUNK 8*1024u

0 commit comments

Comments
 (0)