From d830bb1fc132d31b5e82ba3c676051a4000d1538 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sun, 12 Apr 2026 15:43:35 +0200 Subject: [PATCH 1/3] journal: move the {DATA,ENTRY}_SIZE constants to sd-journal So we can access them from the code there as well. --- src/core/unit.h | 2 +- src/coredump/coredump-config.c | 2 +- src/journal/journald-native.c | 1 - src/libsystemd/sd-journal/journal-def.h | 15 +++++++++++++++ src/shared/journal-importer.h | 14 -------------- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/core/unit.h b/src/core/unit.h index 380ce7fac8..e503c2e344 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -10,7 +10,7 @@ #include "install.h" #include "iterator.h" #include "job.h" -#include "journal-importer.h" +#include "journal-def.h" #include "list.h" #include "log.h" #include "log-context.h" diff --git a/src/coredump/coredump-config.c b/src/coredump/coredump-config.c index de2bb68bf3..cb7bb1adcc 100644 --- a/src/coredump/coredump-config.c +++ b/src/coredump/coredump-config.c @@ -3,7 +3,7 @@ #include "conf-parser.h" #include "coredump-config.h" #include "format-util.h" -#include "journal-importer.h" +#include "journal-def.h" #include "log.h" #include "string-table.h" #include "string-util.h" diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index fade424ebc..1c36ca9434 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -10,7 +10,6 @@ #include "fd-util.h" #include "format-util.h" #include "iovec-util.h" -#include "journal-importer.h" #include "journal-internal.h" #include "journald-client.h" #include "journald-console.h" diff --git a/src/libsystemd/sd-journal/journal-def.h b/src/libsystemd/sd-journal/journal-def.h index f20c9a357a..84849a1e95 100644 --- a/src/libsystemd/sd-journal/journal-def.h +++ b/src/libsystemd/sd-journal/journal-def.h @@ -6,6 +6,21 @@ #include "sd-forward.h" #include "sparse-endian.h" +/* Make sure not to make this smaller than the maximum coredump size. + * See JOURNAL_SIZE_MAX in coredump-config.h */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#define ENTRY_SIZE_MAX (1024*1024*770u) +#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*32u) +#define DATA_SIZE_MAX (1024*1024*768u) +#else +#define ENTRY_SIZE_MAX (1024*1024*13u) +#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*8u) +#define DATA_SIZE_MAX (1024*1024*11u) +#endif + +/* The maximum number of fields in an entry */ +#define ENTRY_FIELD_COUNT_MAX 1024u + /* * If you change this file you probably should also change its documentation: * diff --git a/src/shared/journal-importer.h b/src/shared/journal-importer.h index f218d80dfd..21de703781 100644 --- a/src/shared/journal-importer.h +++ b/src/shared/journal-importer.h @@ -8,22 +8,8 @@ #include "iovec-wrapper.h" #include "time-util.h" -/* Make sure not to make this smaller than the maximum coredump size. - * See JOURNAL_SIZE_MAX in coredump.c */ -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -#define ENTRY_SIZE_MAX (1024*1024*770u) -#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*32u) -#define DATA_SIZE_MAX (1024*1024*768u) -#else -#define ENTRY_SIZE_MAX (1024*1024*13u) -#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*8u) -#define DATA_SIZE_MAX (1024*1024*11u) -#endif #define LINE_CHUNK 8*1024u -/* The maximum number of fields in an entry */ -#define ENTRY_FIELD_COUNT_MAX 1024u - typedef struct JournalImporter { int fd; bool passive_fd; From 2cda5f6169e4a03e9860d315e7b4a7b0d61ca11f Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sun, 12 Apr 2026 16:24:53 +0200 Subject: [PATCH 2/3] compress: limit the output to dst_max bytes with LZ4 if set We already do that with other algorithms, so let's make decompress_blob_lz4() consistent with the rest. --- src/basic/compress.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basic/compress.c b/src/basic/compress.c index 251eb02fbb..b2a42f44e9 100644 --- a/src/basic/compress.c +++ b/src/basic/compress.c @@ -739,6 +739,8 @@ static int decompress_blob_lz4( size = unaligned_read_le64(src); if (size < 0 || (unsigned) size != unaligned_read_le64(src)) return -EFBIG; + if (dst_max > 0 && (size_t) size > dst_max) + return -ENOBUFS; out = greedy_realloc(dst, size, 1); if (!out) return -ENOMEM; From 31d360fb0b28859aba891aaefb1452f820a5861a Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sun, 12 Apr 2026 15:02:11 +0200 Subject: [PATCH 3/3] journal: limit decompress_blob() output to DATA_SIZE_MAX We already have checks in place during compression that limit the data we compress, so they shouldn't decompress to anything larger than DATA_SIZE_MAX unless they've been tampered with. Let's make this explicit and limit all our decompress_blob() calls in journal-handling code to that limit. One possible scenario this should prevent is when one tries to open and verify a journal file that contains a compression bomb in its payload: $ ls -lh test.journal -rw-rw-r--+ 1 fsumsal fsumsal 1.2M Apr 12 15:07 test.journal $ systemd-run --user --wait --pipe -- build-local/journalctl --verify --file=$PWD/test.journal Running as unit: run-p682422-i4875779.service 000110: Invalid hash (00000000 vs. 11e4948d73bdafdd) 000110: Invalid object contents: Bad message File corruption detected at /home/fsumsal/repos/@systemd/systemd/test.journal:272 (of 1249896 bytes, 0%). FAIL: /home/fsumsal/repos/@systemd/systemd/test.journal (Bad message) Finished with result: exit-code Main processes terminated with: code=exited, status=1/FAILURE Service runtime: 48.051s CPU time consumed: 47.941s Memory peak: 8G (swap: 0B) Same could be, in theory, possible with just `journalctl --file=`, but the reproducer would be a bit more complicated (haven't tried it, yet). Lastly, the change in journal-remote is mostly hardening, as the maximum input size to decompress_blob() there is mandated by MHD's connection memory limit (set to JOURNAL_SERVER_MEMORY_MAX which is 128 KiB at the time of writing), so the possible output size there is already quite limited (e.g. ~800 - 900 MiB for xz-compressed data). --- src/journal-remote/journal-remote-main.c | 2 +- src/libsystemd/sd-journal/journal-file.c | 2 +- src/libsystemd/sd-journal/journal-verify.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c index fbb53cc42f..9cb84bbe1e 100644 --- a/src/journal-remote/journal-remote-main.c +++ b/src/journal-remote/journal-remote-main.c @@ -286,7 +286,7 @@ static int process_http_upload( _cleanup_free_ char *buf = NULL; size_t buf_size; - r = decompress_blob(source->compression, upload_data, *upload_data_size, (void **) &buf, &buf_size, 0); + r = decompress_blob(source->compression, upload_data, *upload_data_size, (void **) &buf, &buf_size, DATA_SIZE_MAX); if (r < 0) return mhd_respondf(connection, r, MHD_HTTP_BAD_REQUEST, "Decompression of received blob failed."); diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 54c647d75b..a4b270ceb7 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -1971,7 +1971,7 @@ static int maybe_decompress_payload( return 1; } - r = decompress_blob(compression, payload, size, &f->compress_buffer, &rsize, 0); + r = decompress_blob(compression, payload, size, &f->compress_buffer, &rsize, DATA_SIZE_MAX); if (r < 0) return r; diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c index 1b3bf3fca3..11532c5f8a 100644 --- a/src/libsystemd/sd-journal/journal-verify.c +++ b/src/libsystemd/sd-journal/journal-verify.c @@ -126,7 +126,7 @@ static int hash_payload(JournalFile *f, Object *o, uint64_t offset, const uint8_ _cleanup_free_ void *b = NULL; size_t b_size; - r = decompress_blob(c, src, size, &b, &b_size, 0); + r = decompress_blob(c, src, size, &b, &b_size, DATA_SIZE_MAX); if (r < 0) { error_errno(offset, r, "%s decompression failed: %m", compression_to_string(c));