diff --git a/src/journal/journald-file.c b/src/journal/journald-file.c index 3315eaf13c..d4765b98df 100644 --- a/src/journal/journald-file.c +++ b/src/journal/journald-file.c @@ -23,7 +23,7 @@ static int journald_file_truncate(JournalFile *f) { int r; /* truncate excess from the end of archives */ - r = journal_file_tail_end(f, &p); + r = journal_file_tail_end_by_pread(f, &p); if (r < 0) return log_debug_errno(r, "Failed to determine end of tail object: %m"); diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index c85dec89be..67eb77be23 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -91,8 +91,7 @@ # pragma GCC diagnostic ignored "-Waddress-of-packed-member" #endif -int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) { - Object tail; +int journal_file_tail_end_by_pread(JournalFile *f, uint64_t *ret_offset) { uint64_t p; int r; @@ -100,10 +99,14 @@ int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) { assert(f->header); assert(ret_offset); + /* Same as journal_file_tail_end_by_mmap() below, but operates with pread() to avoid the mmap cache + * (and thus is thread safe) */ + p = le64toh(f->header->tail_object_offset); if (p == 0) p = le64toh(f->header->header_size); else { + Object tail; uint64_t sz; r = journal_file_read_object_header(f, OBJECT_UNUSED, p, &tail); @@ -126,6 +129,43 @@ int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) { return 0; } +int journal_file_tail_end_by_mmap(JournalFile *f, uint64_t *ret_offset) { + uint64_t p; + int r; + + assert(f); + assert(f->header); + assert(ret_offset); + + /* Same as journal_file_tail_end_by_pread() above, but operates with the usual mmap logic */ + + p = le64toh(f->header->tail_object_offset); + if (p == 0) + p = le64toh(f->header->header_size); + else { + Object *tail; + uint64_t sz; + + r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail); + if (r < 0) + return r; + + sz = le64toh(READ_NOW(tail->object.size)); + if (sz > UINT64_MAX - sizeof(uint64_t) + 1) + return -EBADMSG; + + sz = ALIGN64(sz); + if (p > UINT64_MAX - sz) + return -EBADMSG; + + p += sz; + } + + *ret_offset = p; + + return 0; +} + int journal_file_set_offline_thread_join(JournalFile *f) { int r; @@ -941,7 +981,7 @@ int journal_file_append_object( if (r < 0) return r; - r = journal_file_tail_end(f, &p); + r = journal_file_tail_end_by_mmap(f, &p); if (r < 0) return r; diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h index 1e903b23e2..59509deec9 100644 --- a/src/libsystemd/sd-journal/journal-file.h +++ b/src/libsystemd/sd-journal/journal-file.h @@ -187,7 +187,8 @@ static inline bool VALID_EPOCH(uint64_t u) { int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret); int journal_file_read_object_header(JournalFile *f, ObjectType type, uint64_t offset, Object *ret); -int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset); +int journal_file_tail_end_by_pread(JournalFile *f, uint64_t *ret_offset); +int journal_file_tail_end_by_mmap(JournalFile *f, uint64_t *ret_offset); uint64_t journal_file_entry_n_items(Object *o) _pure_; uint64_t journal_file_entry_array_n_items(Object *o) _pure_;