summaryrefslogtreecommitdiff
path: root/src/journal
diff options
context:
space:
mode:
authorFrantisek Sumsal <frantisek@sumsal.cz>2023-03-26 17:04:57 +0200
committerLuca Boccassi <luca.boccassi@gmail.com>2023-03-27 11:00:30 +0100
commit4c9c91defcdb7f8f40337a26c0d55b725d4245e1 (patch)
treed9010a9c194c8be9d84cd136c005127aae741fe4 /src/journal
parent830e52caa2bf1a29f56cb93e7ed85acb1bda11c3 (diff)
downloadsystemd-4c9c91defcdb7f8f40337a26c0d55b725d4245e1.tar.gz
test: verify the journal with and without a sealing key
The bit flips during journal verification cause various types of journal corruptions, so it's useful to go through it even without a sealing key to see how we handle corrupted stuff. Also, provide a sealing key if running in "CI mode" (i.e. arguments), to check the FSS-related codepaths in CIs as well.
Diffstat (limited to 'src/journal')
-rw-r--r--src/journal/meson.build1
-rw-r--r--src/journal/test-journal-verify.c131
2 files changed, 96 insertions, 36 deletions
diff --git a/src/journal/meson.build b/src/journal/meson.build
index 1490113f1c..c540a1ce45 100644
--- a/src/journal/meson.build
+++ b/src/journal/meson.build
@@ -105,6 +105,7 @@ tests += [
{
'sources' : files('test-journal-verify.c'),
'base' : test_journal_base,
+ 'timeout' : 90,
},
{
'sources' : files('test-journal.c'),
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index 7a90079fc8..f15071d81d 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -12,6 +12,7 @@
#include "managed-journal-file.h"
#include "mmap-cache.h"
#include "rm-rf.h"
+#include "strv.h"
#include "terminal-util.h"
#include "tests.h"
@@ -45,7 +46,17 @@ static int raw_verify(const char *fn, const char *verification_key) {
m = mmap_cache_new();
assert_se(m != NULL);
- r = journal_file_open(-1, fn, O_RDONLY, JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0), 0666, UINT64_MAX, NULL, m, NULL, &f);
+ r = journal_file_open(
+ /* fd= */ -1,
+ fn,
+ O_RDONLY,
+ JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0),
+ 0666,
+ /* compress_threshold_bytes= */ UINT64_MAX,
+ /* metrics= */ NULL,
+ m,
+ /* template= */ NULL,
+ &f);
if (r < 0)
return r;
@@ -55,16 +66,15 @@ static int raw_verify(const char *fn, const char *verification_key) {
return r;
}
-static int run_test(int argc, char *argv[]) {
+static int run_test(const char *verification_key, ssize_t max_iterations) {
_cleanup_(mmap_cache_unrefp) MMapCache *m = NULL;
char t[] = "/var/tmp/journal-XXXXXX";
- unsigned n;
+ struct stat st;
JournalFile *f;
ManagedJournalFile *df;
- const char *verification_key = argv[1];
usec_t from = 0, to = 0, total = 0;
- struct stat st;
- uint64_t p;
+ uint64_t start, end;
+ int r;
m = mmap_cache_new();
assert_se(m != NULL);
@@ -79,32 +89,57 @@ static int run_test(int argc, char *argv[]) {
assert_se(chdir(t) >= 0);
(void) chattr_path(t, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
- log_info("Generating...");
-
- assert_se(managed_journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0), 0666, UINT64_MAX, NULL, m, NULL, NULL, &df) == 0);
-
- for (n = 0; n < N_ENTRIES; n++) {
+ log_info("Generating a test journal");
+
+ assert_se(managed_journal_file_open(
+ /* fd= */ -1,
+ "test.journal",
+ O_RDWR|O_CREAT,
+ JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0),
+ 0666,
+ /* compress_threshold_bytes= */ UINT64_MAX,
+ /* metrics= */ NULL,
+ m,
+ /* deferred_closes= */ NULL,
+ /* template= */ NULL,
+ &df) == 0);
+
+ for (size_t n = 0; n < N_ENTRIES; n++) {
+ _cleanup_free_ char *test = NULL;
struct iovec iovec;
struct dual_timestamp ts;
- char *test;
dual_timestamp_get(&ts);
-
assert_se(asprintf(&test, "RANDOM=%li", random() % RANDOM_RANGE));
-
iovec = IOVEC_MAKE_STRING(test);
-
- assert_se(journal_file_append_entry(df->file, &ts, NULL, &iovec, 1, NULL, NULL, NULL, NULL) == 0);
-
- free(test);
+ assert_se(journal_file_append_entry(
+ df->file,
+ &ts,
+ /* boot_id= */ NULL,
+ &iovec,
+ /* n_iovec= */ 1,
+ /* seqnum= */ NULL,
+ /* seqnum_id= */ NULL,
+ /* ret_object= */ NULL,
+ /* ret_offset= */ NULL) == 0);
}
(void) managed_journal_file_close(df);
- log_info("Verifying...");
-
- assert_se(journal_file_open(-1, "test.journal", O_RDONLY, JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL: 0), 0666, UINT64_MAX, NULL, m, NULL, &f) == 0);
- /* journal_file_print_header(f); */
+ log_info("Verifying with key: %s", strna(verification_key));
+
+ assert_se(journal_file_open(
+ /* fd= */ -1,
+ "test.journal",
+ O_RDONLY,
+ JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0),
+ 0666,
+ /* compress_threshold_bytes= */ UINT64_MAX,
+ /* metrics= */ NULL,
+ m,
+ /* template= */ NULL,
+ &f) == 0);
+ journal_file_print_header(f);
journal_file_dump(f);
assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0);
@@ -116,37 +151,61 @@ static int run_test(int argc, char *argv[]) {
FORMAT_TIMESPAN(total > to ? total - to : 0, 0));
(void) journal_file_close(f);
+ assert_se(stat("test.journal", &st) >= 0);
- if (verification_key) {
- log_info("Toggling bits...");
-
- assert_se(stat("test.journal", &st) >= 0);
+ start = 38448 * 8 + 0;
+ end = max_iterations < 0 ? (uint64_t)st.st_size * 8 : start + max_iterations;
+ log_info("Toggling bits %"PRIu64 " to %"PRIu64, start, end);
- for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) {
- bit_toggle("test.journal", p);
+ for (uint64_t p = start; p < end; p++) {
+ bit_toggle("test.journal", p);
+ if (max_iterations < 0)
log_info("[ %"PRIu64"+%"PRIu64"]", p / 8, p % 8);
- if (raw_verify("test.journal", verification_key) >= 0)
- log_notice(ANSI_HIGHLIGHT_RED ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_NORMAL, p / 8, p % 8);
+ r = raw_verify("test.journal", verification_key);
+ /* Suppress the notice when running in the limited (CI) mode */
+ if (verification_key && max_iterations < 0 && r >= 0)
+ log_notice(ANSI_HIGHLIGHT_RED ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_NORMAL, p / 8, p % 8);
- bit_toggle("test.journal", p);
- }
+ bit_toggle("test.journal", p);
}
- log_info("Exiting...");
-
assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
return 0;
}
int main(int argc, char *argv[]) {
+ const char *verification_key = NULL;
+ int max_iterations = 512;
+
+ if (argc > 1) {
+ /* Don't limit the number of iterations when the verification key
+ * is provided on the command line, we want to do that only in CIs */
+ verification_key = argv[1];
+ max_iterations = -1;
+ }
+
assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "0", 1) >= 0);
- run_test(argc, argv);
+ run_test(verification_key, max_iterations);
assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "1", 1) >= 0);
- run_test(argc, argv);
+ run_test(verification_key, max_iterations);
+
+#if HAVE_GCRYPT
+ /* If we're running without any arguments and we're compiled with gcrypt
+ * check the journal verification stuff with a valid key as well */
+ if (argc <= 1) {
+ verification_key = "c262bd-85187f-0b1b04-877cc5/1c7af8-35a4e900";
+
+ assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "0", 1) >= 0);
+ run_test(verification_key, max_iterations);
+
+ assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "1", 1) >= 0);
+ run_test(verification_key, max_iterations);
+ }
+#endif
return 0;
}