]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journal: various fixes to journal_file_read_object()
authorLennart Poettering <lennart@poettering.net>
Tue, 1 Feb 2022 17:31:12 +0000 (18:31 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 1 Feb 2022 17:45:23 +0000 (18:45 +0100)
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
src/libsystemd/sd-journal/journal-file.c
src/libsystemd/sd-journal/journal-file.h

index 4e095acc934fe6923f85e4b0a6aa62047ac2c0d3..3315eaf13ca80d705822b3b714244bb9c9e29058 100644 (file)
@@ -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;
index dc866b89052fa6d70ac83e1831608b71607e871c..c85dec89be90b7f7915f7e362079ef15f54a2d14 100644 (file)
@@ -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);
 
-        s = le64toh(o.object.size);
+        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,
index f673e05e72baecd15f0203ea1931e9ed5005a212..1e903b23e2526bcf83b5ac15a2ac3485d2f6c0c5 100644 (file)
@@ -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);