From e5d8473335ee399b12d803288fcc09d4bd3b120b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Feb 2022 18:31:12 +0100 Subject: [PATCH] journal: various fixes to journal_file_read_object() This fixes a bunch of issues: pread() returns ssize_t, and returns errors in 'errno', handle that correctly. More importantly: it might incompletely read data in case we hit EOF. Check for that, and handle it. Finally, rename the function to journal_file_read_object_header(), since it really doesn't read full objects, but only their headers. Follow-up for: 117e21121e857b4b7d81949542e8dd257265970a --- src/journal/journald-file.c | 4 ++-- src/libsystemd/sd-journal/journal-file.c | 29 ++++++++++++++++-------- src/libsystemd/sd-journal/journal-file.h | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/journal/journald-file.c b/src/journal/journald-file.c index 4e095acc93..3315eaf13c 100644 --- a/src/journal/journald-file.c +++ b/src/journal/journald-file.c @@ -45,7 +45,7 @@ static int journald_file_entry_array_punch_hole(JournalFile *f, uint64_t p, uint return 0; for (uint64_t q = p; q != 0; q = le64toh(o.entry_array.next_entry_array_offset)) { - r = journal_file_read_object(f, OBJECT_ENTRY_ARRAY, q, &o); + r = journal_file_read_object_header(f, OBJECT_ENTRY_ARRAY, q, &o); if (r < 0) return r; @@ -119,7 +119,7 @@ static int journald_file_punch_holes(JournalFile *f) { for (uint64_t q = le64toh(items[j].head_hash_offset); q != 0; q = le64toh(o.data.next_hash_offset)) { - r = journal_file_read_object(f, OBJECT_DATA, q, &o); + r = journal_file_read_object_header(f, OBJECT_DATA, q, &o); if (r < 0) { log_debug_errno(r, "Invalid data object: %m, ignoring"); break; diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index dc866b8905..c85dec89be 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -106,7 +106,7 @@ int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) { else { uint64_t sz; - r = journal_file_read_object(f, OBJECT_UNUSED, p, &tail); + r = journal_file_read_object_header(f, OBJECT_UNUSED, p, &tail); if (r < 0) return r; @@ -818,10 +818,11 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset return 0; } -int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) { - int r; - Object o; +int journal_file_read_object_header(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) { uint64_t s; + ssize_t n; + Object o; + int r; assert(f); @@ -838,17 +839,22 @@ int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, O offset); /* This will likely read too much data but it avoids having to call pread() twice. */ - r = pread(f->fd, &o, sizeof(Object), offset); - if (r < 0) - return r; + n = pread(f->fd, &o, sizeof(o), offset); + if (n < 0) + return log_debug_errno(errno, "Failed to read journal file at offset: %" PRIu64, + offset); + + if ((size_t) n < sizeof(o.object)) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), + "Failed to read short object at offset: %" PRIu64, + offset); s = le64toh(o.object.size); - if (s == 0) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Attempt to read uninitialized object: %" PRIu64, offset); - if (s < sizeof(ObjectHeader)) + if (s < sizeof(o.object)) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Attempt to read overly short object: %" PRIu64, offset); @@ -863,6 +869,11 @@ int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, O "Attempt to read truncated object: %" PRIu64, offset); + if ((size_t) n < minimum_header_size(&o)) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), + "Short read while reading object: %" PRIu64, + offset); + if (type > OBJECT_UNUSED && o.object.type != type) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Attempt to read object of unexpected type: %" PRIu64, diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h index f673e05e72..1e903b23e2 100644 --- a/src/libsystemd/sd-journal/journal-file.h +++ b/src/libsystemd/sd-journal/journal-file.h @@ -185,7 +185,7 @@ static inline bool VALID_EPOCH(uint64_t u) { FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_KEYED_HASH) int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret); -int journal_file_read_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);