]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/test-journal-verify.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
7 #include "chattr-util.h"
10 #include "journal-verify.h"
12 #include "managed-journal-file.h"
13 #include "mmap-cache.h"
16 #include "terminal-util.h"
19 #define N_ENTRIES 6000
20 #define RANDOM_RANGE 77
22 static void bit_toggle(const char *fn
, uint64_t p
) {
27 fd
= open(fn
, O_RDWR
|O_CLOEXEC
);
30 r
= pread(fd
, &b
, 1, p
/8);
35 r
= pwrite(fd
, &b
, 1, p
/8);
41 static int raw_verify(const char *fn
, const char *verification_key
) {
42 _cleanup_(mmap_cache_unrefp
) MMapCache
*m
= NULL
;
49 r
= journal_file_open(
53 JOURNAL_COMPRESS
|(verification_key
? JOURNAL_SEAL
: 0),
55 /* compress_threshold_bytes= */ UINT64_MAX
,
63 r
= journal_file_verify(f
, verification_key
, NULL
, NULL
, NULL
, false);
64 (void) journal_file_close(f
);
69 static int run_test(const char *verification_key
, ssize_t max_iterations
) {
70 _cleanup_(mmap_cache_unrefp
) MMapCache
*m
= NULL
;
71 char t
[] = "/var/tmp/journal-XXXXXX";
75 usec_t from
= 0, to
= 0, total
= 0;
82 /* journal_file_open() requires a valid machine id */
83 if (sd_id128_get_machine(NULL
) < 0)
84 return log_tests_skipped("No valid machine ID found");
86 test_setup_logging(LOG_DEBUG
);
88 assert_se(mkdtemp(t
));
89 assert_se(chdir(t
) >= 0);
90 (void) chattr_path(t
, FS_NOCOW_FL
, FS_NOCOW_FL
, NULL
);
92 log_info("Generating a test journal");
94 assert_se(journal_file_open(
98 JOURNAL_COMPRESS
|(verification_key
? JOURNAL_SEAL
: 0),
100 /* compress_threshold_bytes= */ UINT64_MAX
,
103 /* template= */ NULL
,
106 for (size_t n
= 0; n
< N_ENTRIES
; n
++) {
107 _cleanup_free_
char *test
= NULL
;
109 struct dual_timestamp ts
;
111 dual_timestamp_get(&ts
);
112 assert_se(asprintf(&test
, "RANDOM=%li", random() % RANDOM_RANGE
));
113 iovec
= IOVEC_MAKE_STRING(test
);
114 assert_se(journal_file_append_entry(
121 /* seqnum_id= */ NULL
,
122 /* ret_object= */ NULL
,
123 /* ret_offset= */ NULL
) == 0);
126 (void) journal_file_offline_close(df
);
128 log_info("Verifying with key: %s", strna(verification_key
));
130 assert_se(journal_file_open(
134 JOURNAL_COMPRESS
|(verification_key
? JOURNAL_SEAL
: 0),
136 /* compress_threshold_bytes= */ UINT64_MAX
,
139 /* template= */ NULL
,
141 journal_file_print_header(f
);
142 journal_file_dump(f
);
144 assert_se(journal_file_verify(f
, verification_key
, &from
, &to
, &total
, true) >= 0);
146 if (verification_key
&& JOURNAL_HEADER_SEALED(f
->header
))
147 log_info("=> Validated from %s to %s, %s missing",
148 FORMAT_TIMESTAMP(from
),
149 FORMAT_TIMESTAMP(to
),
150 FORMAT_TIMESPAN(total
> to
? total
- to
: 0, 0));
152 (void) journal_file_close(f
);
153 assert_se(stat("test.journal", &st
) >= 0);
155 start
= 38448 * 8 + 0;
156 end
= max_iterations
< 0 ? (uint64_t)st
.st_size
* 8 : start
+ max_iterations
;
157 log_info("Toggling bits %"PRIu64
" to %"PRIu64
, start
, end
);
159 for (uint64_t p
= start
; p
< end
; p
++) {
160 bit_toggle("test.journal", p
);
162 if (max_iterations
< 0)
163 log_info("[ %"PRIu64
"+%"PRIu64
"]", p
/ 8, p
% 8);
165 r
= raw_verify("test.journal", verification_key
);
166 /* Suppress the notice when running in the limited (CI) mode */
167 if (verification_key
&& max_iterations
< 0 && r
>= 0)
168 log_notice(ANSI_HIGHLIGHT_RED
">>>> %"PRIu64
" (bit %"PRIu64
") can be toggled without detection." ANSI_NORMAL
, p
/ 8, p
% 8);
170 bit_toggle("test.journal", p
);
173 assert_se(rm_rf(t
, REMOVE_ROOT
|REMOVE_PHYSICAL
) >= 0);
178 int main(int argc
, char *argv
[]) {
179 const char *verification_key
= NULL
;
180 int max_iterations
= 512;
183 /* Don't limit the number of iterations when the verification key
184 * is provided on the command line, we want to do that only in CIs */
185 verification_key
= argv
[1];
189 assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "0", 1) >= 0);
190 run_test(verification_key
, max_iterations
);
192 assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "1", 1) >= 0);
193 run_test(verification_key
, max_iterations
);
196 /* If we're running without any arguments and we're compiled with gcrypt
197 * check the journal verification stuff with a valid key as well */
199 verification_key
= "c262bd-85187f-0b1b04-877cc5/1c7af8-35a4e900";
201 assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "0", 1) >= 0);
202 run_test(verification_key
, max_iterations
);
204 assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "1", 1) >= 0);
205 run_test(verification_key
, max_iterations
);