]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/test-journal-verify.c
basic/fs-util: skip fsync_directory_of_file() if /proc/self/fd/ is not available...
[thirdparty/systemd.git] / src / journal / test-journal-verify.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
0284adc6
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2012 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
cf0fbc49 21#include <fcntl.h>
0284adc6
LP
22#include <stdio.h>
23#include <unistd.h>
0284adc6 24
3ffd4af2 25#include "fd-util.h"
0284adc6
LP
26#include "journal-file.h"
27#include "journal-verify.h"
3ffd4af2
LP
28#include "log.h"
29#include "rm-rf.h"
288a74cc 30#include "terminal-util.h"
3ffd4af2 31#include "util.h"
0284adc6
LP
32
33#define N_ENTRIES 6000
34#define RANDOM_RANGE 77
35
b72631e5
LP
36static void bit_toggle(const char *fn, uint64_t p) {
37 uint8_t b;
38 ssize_t r;
39 int fd;
40
41 fd = open(fn, O_RDWR|O_CLOEXEC);
787784c4 42 assert_se(fd >= 0);
b72631e5
LP
43
44 r = pread(fd, &b, 1, p/8);
787784c4 45 assert_se(r == 1);
b72631e5
LP
46
47 b ^= 1 << (p % 8);
48
49 r = pwrite(fd, &b, 1, p/8);
787784c4 50 assert_se(r == 1);
b72631e5 51
03e334a1 52 safe_close(fd);
b72631e5
LP
53}
54
55static int raw_verify(const char *fn, const char *verification_key) {
56 JournalFile *f;
57 int r;
58
5d1ce257 59 r = journal_file_open(-1, fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f);
b72631e5
LP
60 if (r < 0)
61 return r;
62
63 r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false);
69a3a6fd 64 (void) journal_file_close(f);
b72631e5
LP
65
66 return r;
67}
68
0284adc6
LP
69int main(int argc, char *argv[]) {
70 char t[] = "/tmp/journal-XXXXXX";
71 unsigned n;
72 JournalFile *f;
14d10188 73 const char *verification_key = argv[1];
b72631e5 74 usec_t from = 0, to = 0, total = 0;
6c7be122
LP
75 char a[FORMAT_TIMESTAMP_MAX];
76 char b[FORMAT_TIMESTAMP_MAX];
77 char c[FORMAT_TIMESPAN_MAX];
b72631e5
LP
78 struct stat st;
79 uint64_t p;
0284adc6 80
143bfdaf
HHPF
81 /* journal_file_open requires a valid machine id */
82 if (access("/etc/machine-id", F_OK) != 0)
83 return EXIT_TEST_SKIP;
84
0284adc6
LP
85 log_set_max_level(LOG_DEBUG);
86
87 assert_se(mkdtemp(t));
88 assert_se(chdir(t) >= 0);
89
90 log_info("Generating...");
91
5d1ce257 92 assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
0284adc6
LP
93
94 for (n = 0; n < N_ENTRIES; n++) {
95 struct iovec iovec;
96 struct dual_timestamp ts;
97 char *test;
98
99 dual_timestamp_get(&ts);
100
101 assert_se(asprintf(&test, "RANDOM=%lu", random() % RANDOM_RANGE));
102
103 iovec.iov_base = (void*) test;
104 iovec.iov_len = strlen(test);
105
106 assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
107
108 free(test);
109 }
110
69a3a6fd 111 (void) journal_file_close(f);
0284adc6
LP
112
113 log_info("Verifying...");
114
5d1ce257 115 assert_se(journal_file_open(-1, "test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
f7fab8a5
LP
116 /* journal_file_print_header(f); */
117 journal_file_dump(f);
3223f44f 118
b72631e5 119 assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0);
6c7be122 120
ece174c5 121 if (verification_key && JOURNAL_HEADER_SEALED(f->header))
b72631e5
LP
122 log_info("=> Validated from %s to %s, %s missing",
123 format_timestamp(a, sizeof(a), from),
124 format_timestamp(b, sizeof(b), to),
2fa4092c 125 format_timespan(c, sizeof(c), total > to ? total - to : 0, 0));
feb12d3e 126
69a3a6fd 127 (void) journal_file_close(f);
0284adc6 128
f7fab8a5
LP
129 if (verification_key) {
130 log_info("Toggling bits...");
b72631e5 131
f7fab8a5 132 assert_se(stat("test.journal", &st) >= 0);
b72631e5 133
f7fab8a5
LP
134 for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) {
135 bit_toggle("test.journal", p);
b72631e5 136
507f22bd 137 log_info("[ %"PRIu64"+%"PRIu64"]", p / 8, p % 8);
b72631e5 138
f7fab8a5 139 if (raw_verify("test.journal", verification_key) >= 0)
1fc464f6 140 log_notice(ANSI_HIGHLIGHT_RED ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_NORMAL, p / 8, p % 8);
b72631e5 141
f7fab8a5
LP
142 bit_toggle("test.journal", p);
143 }
b72631e5
LP
144 }
145
0284adc6
LP
146 log_info("Exiting...");
147
c6878637 148 assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
0284adc6
LP
149
150 return 0;
151}