]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journal: Add journal_file_read_object()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 29 Nov 2021 09:24:44 +0000 (10:24 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 6 Dec 2021 13:54:06 +0000 (14:54 +0100)
src/libsystemd/sd-journal/journal-file.c
src/libsystemd/sd-journal/journal-file.h

index 3722519dc4234bee071358b2c5e8da646ad791fc..7068b6bb17848a6a55e7551bb79961ba688ae94a 100644 (file)
@@ -990,6 +990,65 @@ 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;
+        uint64_t s;
+
+        assert(f);
+        assert(ret);
+
+        /* Objects may only be located at multiple of 64 bit */
+        if (!VALID64(offset))
+                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
+                                       "Attempt to read object at non-64bit boundary: %" PRIu64,
+                                       offset);
+
+        /* Object may not be located in the file header */
+        if (offset < le64toh(f->header->header_size))
+                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
+                                       "Attempt to read object located in file header: %" PRIu64,
+                                       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;
+
+        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))
+                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
+                                       "Attempt to read overly short object: %" PRIu64,
+                                       offset);
+
+        if (o.object.type <= OBJECT_UNUSED)
+                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
+                                       "Attempt to read object with invalid type: %" PRIu64,
+                                       offset);
+
+        if (s < minimum_header_size(&o))
+                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
+                                       "Attempt to read truncated 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,
+                                       offset);
+
+        r = journal_file_check_object(f, offset, &o);
+        if (r < 0)
+                return r;
+
+        *ret = o;
+        return 0;
+}
+
 static uint64_t journal_file_entry_seqnum(
                 JournalFile *f,
                 uint64_t *seqnum) {
index 92784337c2e73e1119abd07aad218275249d3d38..81b2ff23e1d08e64ae242cf7045010aaec625379 100644 (file)
@@ -202,6 +202,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);
 
 uint64_t journal_file_entry_n_items(Object *o) _pure_;
 uint64_t journal_file_entry_array_n_items(Object *o) _pure_;