jounral: write bit fiddling test
authorLennart Poettering <lennart@poettering.net>
Fri, 17 Aug 2012 22:40:03 +0000 (00:40 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 Aug 2012 22:40:03 +0000 (00:40 +0200)
This test goes through every single bit in a journal file, toggles it,
and checks if this change is detected by the verification.

src/journal/journal-verify.c
src/journal/journal-verify.h
src/journal/journalctl.c
src/journal/test-journal-verify.c

index 39cf3a3..f66b235 100644 (file)
@@ -394,7 +394,8 @@ static int verify_hash_table(
                 int data_fd, uint64_t n_data,
                 int entry_fd, uint64_t n_entries,
                 int entry_array_fd, uint64_t n_entry_arrays,
-                usec_t *last_usec) {
+                usec_t *last_usec,
+                bool show_progress) {
 
         uint64_t i, n;
         int r;
@@ -409,7 +410,8 @@ static int verify_hash_table(
         for (i = 0; i < n; i++) {
                 uint64_t last = 0, p;
 
-                draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
+                if (show_progress)
+                        draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
 
                 p = le64toh(f->data_hash_table[i].head_hash_offset);
                 while (p != 0) {
@@ -535,7 +537,8 @@ static int verify_entry_array(
                 int data_fd, uint64_t n_data,
                 int entry_fd, uint64_t n_entries,
                 int entry_array_fd, uint64_t n_entry_arrays,
-                usec_t *last_usec) {
+                usec_t *last_usec,
+                bool show_progress) {
 
         uint64_t i = 0, a, n, last = 0;
         int r;
@@ -552,7 +555,8 @@ static int verify_entry_array(
                 uint64_t next, m, j;
                 Object *o;
 
-                draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
+                if (show_progress)
+                        draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
 
                 if (a == 0) {
                         log_error("Array chain too short at %llu of %llu",
@@ -674,7 +678,8 @@ static int journal_file_parse_verification_key(JournalFile *f, const char *key)
 int journal_file_verify(
                 JournalFile *f,
                 const char *key,
-                usec_t *first_validated, usec_t *last_validated, usec_t *last_contained) {
+                usec_t *first_validated, usec_t *last_validated, usec_t *last_contained,
+                bool show_progress) {
         int r;
         Object *o;
         uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0;
@@ -728,7 +733,8 @@ int journal_file_verify(
 
         p = le64toh(f->header->header_size);
         while (p != 0) {
-                draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
+                if (show_progress)
+                        draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
 
                 r = journal_file_move_to_object(f, -1, p, &o);
                 if (r < 0) {
@@ -891,8 +897,6 @@ int journal_file_verify(
                                 goto fail;
                         }
 
-                        log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
-
                         if (le64toh(o->tag.seqnum) != n_tags + 1) {
                                 log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
                                 r = -EBADMSG;
@@ -1070,7 +1074,8 @@ int journal_file_verify(
                                data_fd, n_data,
                                entry_fd, n_entries,
                                entry_array_fd, n_entry_arrays,
-                               &last_usec);
+                               &last_usec,
+                               show_progress);
         if (r < 0)
                 goto fail;
 
@@ -1078,11 +1083,13 @@ int journal_file_verify(
                               data_fd, n_data,
                               entry_fd, n_entries,
                               entry_array_fd, n_entry_arrays,
-                              &last_usec);
+                              &last_usec,
+                              show_progress);
         if (r < 0)
                 goto fail;
 
-        flush_progress();
+        if (show_progress)
+                flush_progress();
 
         mmap_cache_close_fd(f->mmap, data_fd);
         mmap_cache_close_fd(f->mmap, entry_fd);
@@ -1102,7 +1109,8 @@ int journal_file_verify(
         return 0;
 
 fail:
-        flush_progress();
+        if (show_progress)
+                flush_progress();
 
         log_error("File corruption detected at %s:%llu (of %llu, %llu%%).",
                   f->path,
index e4449c6..a4633ad 100644 (file)
@@ -23,4 +23,4 @@
 
 #include "journal-file.h"
 
-int journal_file_verify(JournalFile *f, const char *key, usec_t *first_validated, usec_t *last_validated, usec_t *last_contained);
+int journal_file_verify(JournalFile *f, const char *key, usec_t *first_validated, usec_t *last_validated, usec_t *last_contained, bool show_progress);
index 25f41f6..ba678a2 100644 (file)
@@ -637,7 +637,7 @@ static int verify(sd_journal *j) {
                         log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
 #endif
 
-                k = journal_file_verify(f, arg_verify_key, &from, &to, &total);
+                k = journal_file_verify(f, arg_verify_key, &from, &to, &total, true);
                 if (k == -EINVAL) {
                         /* If the key was invalid give up right-away. */
                         return k;
@@ -648,7 +648,7 @@ static int verify(sd_journal *j) {
                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
                         log_info("PASS: %s", f->path);
 
-                        if (journal_file_fss_enabled(f))
+                        if (arg_verify_key && journal_file_fss_enabled(f))
                                 log_info("=> Validated from %s to %s, %s missing",
                                          format_timestamp(a, sizeof(a), from),
                                          format_timestamp(b, sizeof(b), to),
index df0a5dd..4e6c119 100644 (file)
 #include "log.h"
 #include "journal-file.h"
 #include "journal-verify.h"
+#include "journal-authenticate.h"
 
 #define N_ENTRIES 6000
 #define RANDOM_RANGE 77
 
+static void bit_toggle(const char *fn, uint64_t p) {
+        uint8_t b;
+        ssize_t r;
+        int fd;
+
+        fd = open(fn, O_RDWR|O_CLOEXEC);
+        assert(fd >= 0);
+
+        r = pread(fd, &b, 1, p/8);
+        assert(r == 1);
+
+        b ^= 1 << (p % 8);
+
+        r = pwrite(fd, &b, 1, p/8);
+        assert(r == 1);
+
+        close_nointr_nofail(fd);
+}
+
+static int raw_verify(const char *fn, const char *verification_key) {
+        JournalFile *f;
+        int r;
+
+        r = journal_file_open(fn, O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f);
+        if (r < 0)
+                return r;
+
+        r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false);
+        journal_file_close(f);
+
+        return r;
+}
+
 int main(int argc, char *argv[]) {
         char t[] = "/tmp/journal-XXXXXX";
         unsigned n;
         JournalFile *f;
         const char *verification_key = argv[1];
-        usec_t from, to, total;
+        usec_t from = 0, to = 0, total = 0;
         char a[FORMAT_TIMESTAMP_MAX];
         char b[FORMAT_TIMESTAMP_MAX];
         char c[FORMAT_TIMESPAN_MAX];
+        struct stat st;
+        uint64_t p;
 
         log_set_max_level(LOG_DEBUG);
 
@@ -71,19 +107,36 @@ int main(int argc, char *argv[]) {
 
         log_info("Verifying...");
 
-        assert_se(journal_file_open("test.journal", O_RDONLY, 0666, false, false, NULL, NULL, NULL, &f) == 0);
-
+        assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f) == 0);
         journal_file_print_header(f);
 
-        assert_se(journal_file_verify(f, verification_key, &from, &to, &total) >= 0);
-
-        log_info("=> Validated from %s to %s, %s missing",
-                 format_timestamp(a, sizeof(a), from),
-                 format_timestamp(b, sizeof(b), to),
-                 format_timespan(c, sizeof(c), total > to ? total - to : 0));
+        assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0);
 
+        if (verification_key && journal_file_fss_enabled(f)) {
+                log_info("=> Validated from %s to %s, %s missing",
+                         format_timestamp(a, sizeof(a), from),
+                         format_timestamp(b, sizeof(b), to),
+                         format_timespan(c, sizeof(c), total > to ? total - to : 0));
+        }
         journal_file_close(f);
 
+        log_info("Toggling bits...");
+
+        assert_se(stat("test.journal", &st) >= 0);
+
+        for (p = 240*8; p < ((uint64_t) st.st_size * 8); p ++) {
+                bit_toggle("test.journal", p);
+
+                log_info("[ %llu+%llu]", (unsigned long long) p / 8, (unsigned long long) p % 8);
+
+                if (raw_verify("test.journal", verification_key) >= 0) {
+                        log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %llu (bit %llu) can be toggled without detection." ANSI_HIGHLIGHT_OFF, (unsigned long long) p / 8, (unsigned long long) p % 8);
+                        sleep(1);
+                }
+
+                bit_toggle("test.journal", p);
+        }
+
         log_info("Exiting...");
 
         assert_se(rm_rf_dangerous(t, false, true, false) >= 0);