chiark / gitweb /
journal: use a macro to check for file header flags
[elogind.git] / src / journal / journal-verify.c
index e3bd8ffbd7ce2ecf4c0b8e165842dbf7e9851677..6afeab9a80bb939e34dd3b6e9775093c1309b5cf 100644 (file)
@@ -35,7 +35,6 @@
 
 /* FIXME:
  *
- * - write bit mucking test
  * - evolve key even if nothing happened in regular intervals
  *
  * - Allow building without libgcrypt
@@ -115,7 +114,8 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
                         return -EBADMSG;
 
                 if (le64toh(o->entry.seqnum) <= 0 ||
-                    le64toh(o->entry.realtime) <= 0)
+                    !VALID_REALTIME(le64toh(o->entry.realtime)) ||
+                    !VALID_MONOTONIC(le64toh(o->entry.monotonic)))
                         return -EBADMSG;
 
                 for (i = 0; i < journal_file_entry_n_items(o); i++) {
@@ -134,6 +134,19 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
                 if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
                         return -EBADMSG;
 
+                for (i = 0; i < journal_file_hash_table_n_items(o); i++) {
+                        if (o->hash_table.items[i].head_hash_offset != 0 &&
+                            !VALID64(le64toh(o->hash_table.items[i].head_hash_offset)))
+                                return -EBADMSG;
+                        if (o->hash_table.items[i].tail_hash_offset != 0 &&
+                            !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset)))
+                                return -EBADMSG;
+
+                        if ((o->hash_table.items[i].head_hash_offset != 0) !=
+                            (o->hash_table.items[i].tail_hash_offset != 0))
+                                return -EBADMSG;
+                }
+
                 break;
 
         case OBJECT_ENTRY_ARRAY:
@@ -146,11 +159,20 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
                 if (!VALID64(o->entry_array.next_entry_array_offset))
                         return -EBADMSG;
 
+                for (i = 0; i < journal_file_entry_array_n_items(o); i++)
+                        if (o->entry_array.items[i] != 0 &&
+                            !VALID64(o->entry_array.items[i]))
+                                return -EBADMSG;
+
                 break;
 
         case OBJECT_TAG:
                 if (le64toh(o->object.size) != sizeof(TagObject))
                         return -EBADMSG;
+
+                if (!VALID_EPOCH(o->tag.epoch))
+                        return -EBADMSG;
+
                 break;
         }
 
@@ -243,10 +265,14 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
                 if (*z == p)
                         return 1;
 
+                if (a + 1 >= b)
+                        return 0;
+
                 if (p < *z)
                         b = c;
-                else
+                else {
                         a = c;
+                }
         }
 
         return 0;
@@ -682,7 +708,7 @@ int journal_file_verify(
                 bool show_progress) {
         int r;
         Object *o;
-        uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0;
+        uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
         uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
         sd_id128_t entry_boot_id;
         bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
@@ -779,8 +805,7 @@ int journal_file_verify(
                         goto fail;
                 }
 
-                if (o->object.flags & OBJECT_COMPRESSED &&
-                    !(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED)) {
+                if ((o->object.flags & OBJECT_COMPRESSED) && !JOURNAL_HEADER_COMPRESSED(f->header)) {
                         log_error("Compressed object in file without compression at %llu", (unsigned long long) p);
                         r = -EBADMSG;
                         goto fail;
@@ -801,7 +826,7 @@ int journal_file_verify(
                         break;
 
                 case OBJECT_ENTRY:
-                        if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED) && n_tags <= 0) {
+                        if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
                                 log_error("First entry before first tag at %llu", (unsigned long long) p);
                                 r = -EBADMSG;
                                 goto fail;
@@ -811,7 +836,7 @@ int journal_file_verify(
                         if (r < 0)
                                 goto fail;
 
-                        if (last_tag_realtime > le64toh(o->entry.realtime)) {
+                        if (le64toh(o->entry.realtime) < last_tag_realtime) {
                                 log_error("Older entry after newer tag at %llu", (unsigned long long) p);
                                 r = -EBADMSG;
                                 goto fail;
@@ -914,7 +939,7 @@ int journal_file_verify(
                 case OBJECT_TAG: {
                         uint64_t q, rt;
 
-                        if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED)) {
+                        if (!JOURNAL_HEADER_SEALED(f->header)) {
                                 log_error("Tag object in file without sealing at %llu", (unsigned long long) p);
                                 r = -EBADMSG;
                                 goto fail;
@@ -935,8 +960,8 @@ int journal_file_verify(
                         if (f->seal) {
                                 log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
 
-                                rt = (o->tag.epoch + 1) * f->fss_interval_usec + f->fss_start_usec;
-                                if (entry_realtime_set && entry_realtime >= rt) {
+                                rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
+                                if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
                                         log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p);
                                         r = -EBADMSG;
                                         goto fail;
@@ -987,6 +1012,7 @@ int journal_file_verify(
 
                                 f->hmac_running = false;
                                 last_tag_realtime = rt;
+                                last_sealed_realtime = entry_realtime;
                         }
 
                         last_tag = p + ALIGN64(le64toh(o->object.size));
@@ -1131,7 +1157,7 @@ int journal_file_verify(
         if (first_validated)
                 *first_validated = last_tag_realtime ? le64toh(f->header->head_entry_realtime) : 0;
         if (last_validated)
-                *last_validated = last_tag_realtime;
+                *last_validated = last_sealed_realtime;
         if (last_contained)
                 *last_contained = le64toh(f->header->tail_entry_realtime);