summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-04-22 10:25:31 +0200
committerLuca Boccassi <luca.boccassi@gmail.com>2024-04-23 15:13:05 +0200
commitbd0ec61ae3bb7a5200b344bab46ba2d6b9406aac (patch)
tree3d97b3b7cc2ac568e1327b67b2ba65035783c646 /src
parentcore: Limit terminal reset using ANSI sequences to /dev/console (diff)
downloadsystemd-bd0ec61ae3bb7a5200b344bab46ba2d6b9406aac.tar.xz
systemd-bd0ec61ae3bb7a5200b344bab46ba2d6b9406aac.zip
journal: do not rotate unrelated journal files when full or corrupted
When we fail to add an entry to a journal file, typically when the file is full or corrupted, it is not necessary to rotate other journal files. Not only that's unnecessary, rotating all journal files allows unprivileged users to wipe system or other user's journals by writing many journal entries to their own user journal file. Let's rotate all journal files only when - it is really requested by a privileged user (e.g. by journalctl --rotate), or - the system time jumps backwards. And, otherwise rotate only the journal file we are currently writing.
Diffstat (limited to 'src')
-rw-r--r--src/journal/journald-server.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 285aea988a..02895b2068 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -720,6 +720,33 @@ void server_rotate(Server *s) {
server_process_deferred_closes(s);
}
+static void server_rotate_journal(Server *s, JournalFile *f, uid_t uid) {
+ int r;
+
+ assert(s);
+ assert(f);
+
+ /* This is similar to server_rotate(), but rotates only specified journal file.
+ *
+ * 💣💣💣 This invalidate 'f', and the caller cannot reuse the passed JournalFile object. 💣💣💣 */
+
+ if (f == s->system_journal)
+ (void) server_do_rotate(s, &s->system_journal, "system", s->seal, /* uid= */ 0);
+ else if (f == s->runtime_journal)
+ (void) server_do_rotate(s, &s->runtime_journal, "runtime", /* seal= */ false, /* uid= */ 0);
+ else {
+ assert(ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid)) == f);
+ r = server_do_rotate(s, &f, "user", s->seal, uid);
+ if (r >= 0)
+ ordered_hashmap_replace(s->user_journals, UID_TO_PTR(uid), f);
+ else if (!f)
+ /* Old file has been closed and deallocated */
+ ordered_hashmap_remove(s->user_journals, UID_TO_PTR(uid));
+ }
+
+ server_process_deferred_closes(s);
+}
+
void server_sync(Server *s) {
JournalFile *f;
int r;
@@ -904,7 +931,7 @@ static void server_write_to_journal(
size_t n,
int priority) {
- bool vacuumed = false, rotate = false;
+ bool vacuumed = false;
struct dual_timestamp ts;
JournalFile *f;
int r;
@@ -926,23 +953,26 @@ static void server_write_to_journal(
* bisection works correctly. */
log_ratelimit_info(JOURNAL_LOG_RATELIMIT, "Time jumped backwards, rotating.");
- rotate = true;
- } else {
+ server_rotate(s);
+ server_vacuum(s, /* verbose = */ false);
+ vacuumed = true;
+ }
- f = server_find_journal(s, uid);
- if (!f)
- return;
+ f = server_find_journal(s, uid);
+ if (!f)
+ return;
- if (journal_file_rotate_suggested(f, s->max_file_usec, LOG_DEBUG)) {
- log_debug("%s: Journal header limits reached or header out-of-date, rotating.",
- f->path);
- rotate = true;
+ if (journal_file_rotate_suggested(f, s->max_file_usec, LOG_DEBUG)) {
+ if (vacuumed) {
+ log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
+ "Suppressing rotation, as we already rotated immediately before write attempt. Giving up.");
+ return;
}
- }
- if (rotate) {
- server_rotate(s);
- server_vacuum(s, false);
+ log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
+
+ server_rotate_journal(s, TAKE_PTR(f), uid);
+ server_vacuum(s, /* verbose = */ false);
vacuumed = true;
f = server_find_journal(s, uid);
@@ -976,8 +1006,8 @@ static void server_write_to_journal(
return;
}
- server_rotate(s);
- server_vacuum(s, false);
+ server_rotate_journal(s, TAKE_PTR(f), uid);
+ server_vacuum(s, /* verbose = */ false);
f = server_find_journal(s, uid);
if (!f)
@@ -1327,8 +1357,8 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
log_ratelimit_info(JOURNAL_LOG_RATELIMIT, "Rotating system journal.");
- server_rotate(s);
- server_vacuum(s, false);
+ server_rotate_journal(s, s->system_journal, /* uid = */ 0);
+ server_vacuum(s, /* verbose = */ false);
if (!s->system_journal) {
log_ratelimit_notice(JOURNAL_LOG_RATELIMIT,