You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
5.5 KiB
137 lines
5.5 KiB
2 days ago
|
From 6e5dce6e2f9cc43375eb481c2d533606d2a07e1b Mon Sep 17 00:00:00 2001
|
||
|
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||
|
Date: Mon, 22 Apr 2024 17:25:31 +0900
|
||
|
Subject: [PATCH] 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.
|
||
|
|
||
|
(cherry picked from commit bd0ec61ae3bb7a5200b344bab46ba2d6b9406aac)
|
||
|
|
||
|
Resolves: RHEL-33890
|
||
|
---
|
||
|
src/journal/journald-server.c | 67 +++++++++++++++++++++++++----------
|
||
|
1 file changed, 48 insertions(+), 19 deletions(-)
|
||
|
|
||
|
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
|
||
|
index 56f2ea8583..0ff6a43e5b 100644
|
||
|
--- a/src/journal/journald-server.c
|
||
|
+++ b/src/journal/journald-server.c
|
||
|
@@ -667,6 +667,33 @@ void server_rotate(Server *s) {
|
||
|
server_process_deferred_closes(s);
|
||
|
}
|
||
|
|
||
|
+static void server_rotate_journal(Server *s, ManagedJournalFile *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) do_rotate(s, &s->system_journal, "system", s->seal, /* uid= */ 0);
|
||
|
+ else if (f == s->runtime_journal)
|
||
|
+ (void) 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 = 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) {
|
||
|
ManagedJournalFile *f;
|
||
|
int r;
|
||
|
@@ -819,7 +846,7 @@ static bool shall_try_append_again(JournalFile *f, int r) {
|
||
|
}
|
||
|
|
||
|
static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n, int priority) {
|
||
|
- bool vacuumed = false, rotate = false;
|
||
|
+ bool vacuumed = false;
|
||
|
struct dual_timestamp ts;
|
||
|
ManagedJournalFile *f;
|
||
|
int r;
|
||
|
@@ -841,23 +868,25 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n
|
||
|
* bisection works correctly. */
|
||
|
|
||
|
log_info("Time jumped backwards, rotating.");
|
||
|
- rotate = true;
|
||
|
- } else {
|
||
|
+ server_rotate(s);
|
||
|
+ server_vacuum(s, /* verbose = */ false);
|
||
|
+ vacuumed = true;
|
||
|
+ }
|
||
|
|
||
|
- f = find_journal(s, uid);
|
||
|
- if (!f)
|
||
|
- return;
|
||
|
+ f = find_journal(s, uid);
|
||
|
+ if (!f)
|
||
|
+ return;
|
||
|
|
||
|
- if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_DEBUG)) {
|
||
|
- log_debug("%s: Journal header limits reached or header out-of-date, rotating.",
|
||
|
- f->file->path);
|
||
|
- rotate = true;
|
||
|
+ if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_DEBUG)) {
|
||
|
+ if (vacuumed) {
|
||
|
+ log_warning("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->file->path);
|
||
|
+
|
||
|
+ server_rotate_journal(s, TAKE_PTR(f), uid);
|
||
|
+ server_vacuum(s, /* verbose = */ false);
|
||
|
vacuumed = true;
|
||
|
|
||
|
f = find_journal(s, uid);
|
||
|
@@ -883,8 +912,8 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n
|
||
|
else
|
||
|
log_ratelimit_full_errno(LOG_INFO, r, "Failed to write entry to %s (%zu items, %zu bytes), rotating before retrying: %m", f->file->path, n, IOVEC_TOTAL_SIZE(iovec, n));
|
||
|
|
||
|
- server_rotate(s);
|
||
|
- server_vacuum(s, false);
|
||
|
+ server_rotate_journal(s, TAKE_PTR(f), uid);
|
||
|
+ server_vacuum(s, /* verbose = */ false);
|
||
|
|
||
|
f = find_journal(s, uid);
|
||
|
if (!f)
|
||
|
@@ -1211,10 +1240,10 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
|
||
|
|
||
|
log_info("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) {
|
||
|
+ if (!s->system_journal->file) {
|
||
|
log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful.");
|
||
|
r = -EIO;
|
||
|
goto finish;
|