journal-verify.c revision 1ec7120e50bc084342f8c44aea771c79aaeb774d
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2012 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* This does various superficial tests about the length an
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * possible field values. It does not follow any references to
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * other objects. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning(OFSfmt": unused data (entry_offset==0)", offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": bad n_entries: %"PRIu64, offset, o->data.n_entries);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error(OFSfmt": bad object size (<= %zu): %"PRIu64,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen compression = o->object.flags & OBJECT_COMPRESSION_MASK;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen le64toh(o->object.size) - offsetof(Object, data.payload),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": %s decompression failed: %s", offset,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering object_compressed_to_string(compression), strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": invalid hash (%08"PRIx64" vs. %08"PRIx64, offset, h1, h2);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error(OFSfmt": invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error(OFSfmt": bad field size (<= %zu): %"PRIu64,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!VALID64(o->field.next_hash_offset) ||
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering log_error(OFSfmt": invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_error(OFSfmt": bad entry size (<= %zu): %"PRIu64,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_error(OFSfmt": invalid number items in entry: %"PRIu64,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering (le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_error(OFSfmt": invalid entry seqnum: %"PRIx64,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (!VALID_REALTIME(le64toh(o->entry.realtime))) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering log_error(OFSfmt": invalid entry realtime timestamp: %"PRIu64,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_error(OFSfmt": invalid entry monotonic timestamp: %"PRIu64,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering for (i = 0; i < journal_file_entry_n_items(o); i++) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (o->entry.items[i].object_offset == 0 ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !VALID64(o->entry.items[i].object_offset)) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_error(OFSfmt": invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": invalid %s hash table size: %"PRIu64,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < journal_file_hash_table_n_items(o); i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (o->hash_table.items[i].head_hash_offset != 0 &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !VALID64(le64toh(o->hash_table.items[i].head_hash_offset))) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering le64toh(o->hash_table.items[i].head_hash_offset));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (o->hash_table.items[i].tail_hash_offset != 0 &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset))) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering le64toh(o->hash_table.items[i].tail_hash_offset));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((o->hash_table.items[i].head_hash_offset != 0) !=
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (o->hash_table.items[i].tail_hash_offset != 0)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering le64toh(o->hash_table.items[i].head_hash_offset),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering le64toh(o->hash_table.items[i].tail_hash_offset));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 ||
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering (le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": invalid object entry array size: %"PRIu64,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (!VALID64(o->entry_array.next_entry_array_offset)) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_error(OFSfmt": invalid object entry array next_entry_array_offset: "OFSfmt,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers for (i = 0; i < journal_file_entry_array_n_items(o); i++)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error(OFSfmt": invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (le64toh(o->object.size) != sizeof(TagObject)) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_error(OFSfmt": invalid object tag size: %"PRIu64,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error(OFSfmt": invalid object tag epoch: %"PRIu64,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic void draw_progress(uint64_t p, usec_t *last_usec) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned n, i, j, k;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen j = (n * (unsigned) p) / 65535ULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs("\r\x1B[?25l" ANSI_HIGHLIGHT_GREEN_ON, stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < j; i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < k; i++)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic void flush_progress(void) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned n, i;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen for (i = 0; i < n + 5; i++)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (k != sizeof(p))
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Bisection ... */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen a = 0; b = n;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (a < b) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering c = (a + b) / 2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (a + 1 >= b)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Data object references invalid entry at %"PRIu64, data_p);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = journal_file_move_to_object(f, OBJECT_ENTRY, entry_p, &o);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen for (i = 0; i < n; i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (le64toh(o->entry.items[i].object_offset) == data_p) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Data object not referenced by linked entry at %"PRIu64, data_p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Check if this entry is also in main entry array. Since the
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * main entry array has already been verified we can rely on
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * its consistency.*/
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen n = le64toh(f->header->n_entries);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering a = le64toh(f->header->entry_array_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering while (i < n) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u = MIN(n - i, m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (entry_p <= le64toh(o->entry_array.items[u-1])) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering while (x < y) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering z = (x + y) / 2;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (le64toh(o->entry_array.items[z]) == entry_p)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (x + 1 >= y)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (entry_p < le64toh(o->entry_array.items[z]))
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Entry object doesn't exist in main entry array at %"PRIu64, entry_p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering a = le64toh(o->entry_array.next_entry_array_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int entry_array_fd, uint64_t n_entry_arrays) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Entry array means at least two objects */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (a && n < 2) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Entry array present (entry_array_offset=%"PRIu64", but n_entries=%"PRIu64,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* We already checked that earlier */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering last = q = le64toh(o->data.entry_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = entry_points_to_data(f, entry_fd, n_entries, q, p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering while (i < n) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Array chain too short at %"PRIu64, p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Invalid array at %"PRIu64, p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering next = le64toh(o->entry_array.next_entry_array_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Array chain has cycle at %"PRIu64, p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (j = 0; i < n && j < m; i++, j++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Data object's entry array not sorted at %"PRIu64, p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = entry_points_to_data(f, entry_fd, n_entries, q, p);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Pointer might have moved, reposition */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int entry_array_fd, uint64_t n_entry_arrays,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (i = 0; i < n; i++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering p = le64toh(f->data_hash_table[i].head_hash_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering while (p != 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Invalid data object at hash entry %"PRIu64" of %"PRIu64,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering next = le64toh(o->data.next_hash_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Hash value mismatch in hash entry %"PRIu64" of %"PRIu64,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Tail hash pointer mismatch in hash table");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering q = le64toh(f->data_hash_table[h].head_hash_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering while (q != 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, q, &o);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering for (i = 0; i < n; i++) {
19887cd06a3af2f045e763986eda19e208bd3f85Zbigniew Jędrzejewski-Szmek q = le64toh(o->entry.items[i].object_offset);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Invalid data object at entry %"PRIu64, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, OBJECT_DATA, q, &u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Hash mismatch for data object at entry %"PRIu64, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Data object missing from hash at entry %"PRIu64, p);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering int entry_array_fd, uint64_t n_entry_arrays,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering a = le64toh(f->header->entry_array_offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (i < n) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Array chain too short at %"PRIu64" of %"PRIu64, i, n);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Invalid array at %"PRIu64" of %"PRIu64, i, n);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering next = le64toh(o->entry_array.next_entry_array_offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Array chain has cycle at %"PRIu64" of %"PRIu64, i, n);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (j = 0; i < n && j < m; i++, j++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Entry array not sorted at %"PRIu64" of %"PRIu64,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Invalid array entry at %"PRIu64" of %"PRIu64,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = verify_entry(f, o, p, data_fd, n_data);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Pointer might have moved, reposition */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering usec_t *first_contained, usec_t *last_validated, usec_t *last_contained,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_parse_verification_key(f, key);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (f->seal)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering data_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create data file: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering entry_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create entry file: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering entry_array_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create entry array file: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Cannot verify file with unknown extensions.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < sizeof(f->header->reserved); i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Reserved field in non-zero.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* First iteration: we go through all objects, verify the
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * superficial structure, headers, hashes. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (p != 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = journal_file_move_to_object(f, -1, p, &o);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Invalid object at "OFSfmt, p);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering if (p > le64toh(f->header->tail_object_offset)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Invalid tail object pointer");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (p == le64toh(f->header->tail_object_offset))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Invalid object contents at "OFSfmt": %s", p, strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
case OBJECT_DATA:
goto fail;
n_data++;
case OBJECT_FIELD:
n_fields++;
case OBJECT_ENTRY:
r = -EBADMSG;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
if (!entry_seqnum_set &&
r = -EBADMSG;
goto fail;
if (entry_seqnum_set &&
r = -EBADMSG;
goto fail;
entry_seqnum_set = true;
if (entry_monotonic_set &&
r = -EBADMSG;
goto fail;
entry_monotonic_set = true;
if (!entry_realtime_set &&
r = -EBADMSG;
goto fail;
entry_realtime_set = true;
n_entries ++;
case OBJECT_DATA_HASH_TABLE:
r = -EBADMSG;
goto fail;
le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
r = -EBADMSG;
goto fail;
case OBJECT_FIELD_HASH_TABLE:
r = -EBADMSG;
goto fail;
le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
r = -EBADMSG;
goto fail;
case OBJECT_ENTRY_ARRAY:
goto fail;
if (found_main_entry_array) {
r = -EBADMSG;
goto fail;
found_main_entry_array = true;
case OBJECT_TAG:
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
#ifdef HAVE_GCRYPT
if (f->seal) {
r = -EBADMSG;
goto fail;
goto fail;
r = journal_file_hmac_start(f);
goto fail;
if (last_tag == 0) {
r = journal_file_hmac_put_header(f);
goto fail;
q = last_tag;
goto fail;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
f->hmac_running = false;
n_tags ++;
n_weird ++;
if (!found_last) {
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
if (!found_main_entry_array) {
r = -EBADMSG;
goto fail;
if (entry_seqnum_set &&
r = -EBADMSG;
goto fail;
if (entry_monotonic_set &&
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
r = verify_entry_array(f,
goto fail;
r = verify_hash_table(f,
goto fail;
if (show_progress)
if (first_contained)
if (last_validated)
if (last_contained)
fail:
if (show_progress)
f->path,
if (data_fd >= 0) {
if (entry_fd >= 0) {
if (entry_array_fd >= 0) {