journal-verify.c revision e627440b41bb0284e4892f7aa9d84c77972487e2
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/***
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Copyright 2012 Lennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt***/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <unistd.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <sys/mman.h>
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt#include <fcntl.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include "util.h"
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include "macro.h"
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include "journal-def.h"
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen#include "journal-file.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "journal-authenticate.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "journal-verify.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "lookup3.h"
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include "compress.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "fsprg.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt/* FIXME:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt *
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * - write bit mucking test
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen * - tag timestamps should be between entry timestamps
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen * - output validated time ranges
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen * - add missing fields to journal header dump
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt *
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * - Allow building without libgcrypt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * - check with sparse
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * - 64bit conversions
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt *
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic int journal_file_object_verify(JournalFile *f, Object *o) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(f);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(o);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt /* This does various superficial tests about the length an
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt * possible field values. It does not follow any references to
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt * other objects. */
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if ((o->object.flags & OBJECT_COMPRESSED) &&
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt o->object.type != OBJECT_DATA)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -EBADMSG;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt switch (o->object.type) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt case OBJECT_DATA: {
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen uint64_t h1, h2;
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen if (le64toh(o->data.entry_offset) <= 0 ||
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen le64toh(o->data.n_entries) <= 0)
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen return -EBADMSG;
a276e6d68606861b552140cbcc003f4af10626fcTom Gundersen
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -EBADMSG;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt h1 = le64toh(o->data.hash);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (o->object.flags & OBJECT_COMPRESSED) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt void *b = NULL;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt uint64_t alloc = 0, b_size;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!uncompress_blob(o->data.payload,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt le64toh(o->object.size) - offsetof(Object, data.payload),
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt &b, &alloc, &b_size))
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return -EBADMSG;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt h2 = hash64(b, b_size);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt free(b);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt } else
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (h1 != h2)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return -EBADMSG;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt break;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt case OBJECT_FIELD:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case OBJECT_ENTRY:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt if (le64toh(o->entry.seqnum) <= 0 ||
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt le64toh(o->entry.realtime) <= 0)
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt return -EBADMSG;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt break;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt case OBJECT_DATA_HASH_TABLE:
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt case OBJECT_FIELD_HASH_TABLE:
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -EBADMSG;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -EBADMSG;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt break;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt case OBJECT_ENTRY_ARRAY:
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -EBADMSG;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -EBADMSG;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt break;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt case OBJECT_TAG:
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (le64toh(o->object.size) != sizeof(TagObject))
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -EBADMSG;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt break;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic void draw_progress(uint64_t p, usec_t *last_usec) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt unsigned n, i, j, k;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt usec_t z, x;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!isatty(STDOUT_FILENO))
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt z = now(CLOCK_MONOTONIC);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt x = *last_usec;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (x != 0 && x + 40 * USEC_PER_MSEC > z)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt *last_usec = z;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt n = (3 * columns()) / 4;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt j = (n * (unsigned) p) / 65535ULL;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt k = n - j;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt fputs("\r\x1B[?25l" ANSI_HIGHLIGHT_GREEN_ON, stdout);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (i = 0; i < j; i++)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt fputs("\xe2\x96\x88", stdout);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt fputs(ANSI_HIGHLIGHT_OFF, stdout);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (i = 0; i < k; i++)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt fputs("\xe2\x96\x91", stdout);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt fputs("\r\x1B[?25h", stdout);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt fflush(stdout);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic void flush_progress(void) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt unsigned n, i;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (!isatty(STDOUT_FILENO))
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt return;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt n = (3 * columns()) / 4;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt putchar('\r');
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt for (i = 0; i < n + 5; i++)
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt putchar(' ');
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt putchar('\r');
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt fflush(stdout);
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt}
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flyktstatic int write_uint64(int fd, uint64_t p) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt ssize_t k;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt k = write(fd, &p, sizeof(p));
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek if (k < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -errno;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (k != sizeof(p))
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return -EIO;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flyktstatic int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t a, b;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt int r;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(m);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(fd >= 0);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Bisection ... */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt a = 0; b = n;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt while (a < b) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt uint64_t c, *z;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt c = (a + b) / 2;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, c * sizeof(uint64_t), sizeof(uint64_t), (void **) &z);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return r;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt if (*z == p)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 1;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (p < *z)
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt b = c;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt else
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt a = c;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic int entry_points_to_data(
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt JournalFile *f,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int entry_fd,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t n_entries,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t entry_p,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t data_p) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t i, n, a;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt Object *o;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt bool found = false;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(f);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(entry_fd >= 0);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("Data object references invalid entry at %llu", (unsigned long long) data_p);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return -EBADMSG;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY, entry_p, &o);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (r < 0)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt n = journal_file_entry_n_items(o);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt for (i = 0; i < n; i++)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (le64toh(o->entry.items[i].object_offset) == data_p) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt found = true;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt break;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (!found) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Data object not referenced by linked entry at %llu", (unsigned long long) data_p);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return -EBADMSG;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt /* Check if this entry is also in main entry array. Since the
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt * main entry array has already been verified we can rely on
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt * its consistency.*/
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt n = le64toh(f->header->n_entries);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt a = le64toh(f->header->entry_array_offset);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt i = 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt while (i < n) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t m, j;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt m = journal_file_entry_array_n_items(o);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt for (j = 0; i < n && j < m; i++, j++)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (le64toh(o->entry_array.items[j]) == entry_p)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt a = le64toh(o->entry_array.next_entry_array_offset);;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic int verify_data(
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt JournalFile *f,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt Object *o, uint64_t p,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt int entry_fd, uint64_t n_entries,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt int entry_array_fd, uint64_t n_entry_arrays) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt uint64_t i, n, a, last, q;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt int r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt assert(f);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt assert(o);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt assert(entry_fd >= 0);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(entry_array_fd >= 0);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt n = le64toh(o->data.n_entries);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt a = le64toh(o->data.entry_array_offset);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt /* We already checked this earlier */
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(n > 0);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt last = q = le64toh(o->data.entry_offset);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = entry_points_to_data(f, entry_fd, n_entries, q, p);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt i = 1;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt while (i < n) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt uint64_t next, m, j;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (a == 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Array chain too short at %llu.", (unsigned long long) p);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Invalid array at %llu.", (unsigned long long) p);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return -EBADMSG;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt next = le64toh(o->entry_array.next_entry_array_offset);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (next != 0 && next <= a) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Array chain has cycle at %llu.", (unsigned long long) p);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt m = journal_file_entry_array_n_items(o);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt for (j = 0; i < n && j < m; i++, j++) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt q = le64toh(o->entry_array.items[j]);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (q <= last) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Data object's entry array not sorted at %llu.", (unsigned long long) p);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt last = q;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = entry_points_to_data(f, entry_fd, n_entries, q, p);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt /* Pointer might have moved, reposition */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt a = next;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt}
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flyktstatic int verify_hash_table(
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt JournalFile *f,
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt int data_fd, uint64_t n_data,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int entry_fd, uint64_t n_entries,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int entry_array_fd, uint64_t n_entry_arrays,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt usec_t *last_usec) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt uint64_t i, n;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(f);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(data_fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(entry_fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(entry_array_fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(last_usec);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
513a6fa8679510ea1b55967bdb482dd5f8a39f21Ronny Chevalier for (i = 0; i < n; i++) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt uint64_t last = 0, p;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt p = le64toh(f->data_hash_table[i].head_hash_offset);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt while (p != 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt Object *o;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt uint64_t next;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Invalid data object at hash entry %llu of %llu.",
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt (unsigned long long) i, (unsigned long long) n);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return -EBADMSG;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt next = le64toh(o->data.next_hash_offset);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (next != 0 && next <= p) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Hash chain has a cycle in hash entry %llu of %llu.",
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt (unsigned long long) i, (unsigned long long) n);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -EBADMSG;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (le64toh(o->data.hash) % n != i) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt log_error("Hash value mismatch in hash entry %llu of %llu.",
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt (unsigned long long) i, (unsigned long long) n);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return -EBADMSG;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt last = p;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt p = next;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Tail hash pointer mismatch in hash table.");
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return -EBADMSG;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt}
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flyktstatic int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt uint64_t n, h, q;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt int r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt assert(f);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt h = hash % n;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt q = le64toh(f->data_hash_table[h].head_hash_offset);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt while (q != 0) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt Object *o;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (p == q)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 1;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = journal_file_move_to_object(f, OBJECT_DATA, q, &o);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt q = le64toh(o->data.next_hash_offset);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic int verify_entry(
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt JournalFile *f,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt Object *o, uint64_t p,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int data_fd, uint64_t n_data) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t i, n;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(f);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(o);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(data_fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt n = journal_file_entry_n_items(o);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt for (i = 0; i < n; i++) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint64_t q, h;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt Object *u;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt q = le64toh(o->entry.items[i].object_offset);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt h = le64toh(o->entry.items[i].hash);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Invalid data object at entry %llu.",
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt (unsigned long long) o);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -EBADMSG;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = journal_file_move_to_object(f, OBJECT_DATA, q, &u);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (le64toh(u->data.hash) != h) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Hash mismatch for data object at entry %llu.",
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt (unsigned long long) p);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -EBADMSG;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = data_object_in_hash_table(f, h, q);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r == 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Data object missing from hash at entry %llu.",
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt (unsigned long long) p);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -EBADMSG;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic int verify_entry_array(
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt JournalFile *f,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int data_fd, uint64_t n_data,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int entry_fd, uint64_t n_entries,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int entry_array_fd, uint64_t n_entry_arrays,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt usec_t *last_usec) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt uint64_t i = 0, a, n, last = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(f);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(data_fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(entry_fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(entry_array_fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(last_usec);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt n = le64toh(f->header->n_entries);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt a = le64toh(f->header->entry_array_offset);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt while (i < n) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt uint64_t next, m, j;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt Object *o;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (a == 0) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Array chain too short at %llu of %llu.",
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt (unsigned long long) i, (unsigned long long) n);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return -EBADMSG;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Invalid array at %llu of %llu.",
513a6fa8679510ea1b55967bdb482dd5f8a39f21Ronny Chevalier (unsigned long long) i, (unsigned long long) n);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return -EBADMSG;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (r < 0)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return r;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt next = le64toh(o->entry_array.next_entry_array_offset);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (next != 0 && next <= a) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Array chain has cycle at %llu of %llu.",
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt (unsigned long long) i, (unsigned long long) n);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return -EBADMSG;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt m = journal_file_entry_array_n_items(o);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt for (j = 0; i < n && j < m; i++, j++) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt uint64_t p;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt p = le64toh(o->entry_array.items[j]);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (p <= last) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Entry array not sorted at %llu of %llu.",
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt (unsigned long long) i, (unsigned long long) n);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return -EBADMSG;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt last = p;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Invalid array entry at %llu of %llu.",
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt (unsigned long long) i, (unsigned long long) n);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return -EBADMSG;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = verify_entry(f, o, p, data_fd, n_data);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Pointer might have moved, reposition */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt a = next;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int journal_file_parse_verification_key(JournalFile *f, const char *key) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt uint8_t *seed;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt size_t seed_size, c;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const char *k;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt unsigned long long start, interval;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt seed_size = FSPRG_RECOMMENDED_SEEDLEN;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt seed = malloc(seed_size);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (!seed)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -ENOMEM;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt k = key;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt for (c = 0; c < seed_size; c++) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int x, y;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt while (*k == '-')
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt k++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt x = unhexchar(*k);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (x < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt free(seed);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt k++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt y = unhexchar(*k);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (y < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt free(seed);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt k++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt seed[c] = (uint8_t) (x * 16 + y);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (*k != '/') {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt free(seed);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt k++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = sscanf(k, "%llx-%llx", &start, &interval);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r != 2) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt free(seed);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt f->fsprg_seed = seed;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt f->fsprg_seed_size = seed_size;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt f->fss_start_usec = start;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt f->fss_interval_usec = interval;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktint journal_file_verify(JournalFile *f, const char *key) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt Object *o;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt uint64_t p = 0, last_tag = 0, last_epoch = 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt sd_id128_t entry_boot_id;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt 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;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt usec_t last_usec = 0;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt char data_path[] = "/var/tmp/journal-data-XXXXXX",
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt entry_path[] = "/var/tmp/journal-entry-XXXXXX",
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX";
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt assert(f);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (key) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = journal_file_parse_verification_key(f, key);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Failed to parse seed.");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt data_fd = mkostemp(data_path, O_CLOEXEC);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (data_fd < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Failed to create data file: %m");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -errno;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt unlink(data_path);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_fd = mkostemp(entry_path, O_CLOEXEC);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (entry_fd < 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Failed to create entry file: %m");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -errno;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt unlink(entry_path);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt entry_array_fd = mkostemp(entry_array_path, O_CLOEXEC);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (entry_array_fd < 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Failed to create entry array file: %m");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -errno;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt unlink(entry_array_path);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt /* First iteration: we go through all objects, verify the
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt * superficial structure, headers, hashes. */
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt p = le64toh(f->header->header_size);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt while (p != 0) {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = journal_file_move_to_object(f, -1, p, &o);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (r < 0) {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt log_error("Invalid object at %llu", (unsigned long long) p);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt goto fail;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (le64toh(f->header->tail_object_offset) < p) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Invalid tail object pointer.");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_objects ++;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = journal_file_object_verify(f, o);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Invalid object contents at %llu", (unsigned long long) p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (o->object.flags & OBJECT_COMPRESSED &&
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt !(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Compressed object without compression at %llu", (unsigned long long) p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt switch (o->object.type) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case OBJECT_DATA:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = write_uint64(data_fd, p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt n_data++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case OBJECT_FIELD:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt n_fields++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case OBJECT_ENTRY:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = write_uint64(entry_fd, p);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt goto fail;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (!entry_seqnum_set &&
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Head entry sequence number incorrect");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (entry_seqnum_set &&
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_seqnum >= le64toh(o->entry.seqnum)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_seqnum = le64toh(o->entry.seqnum);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_seqnum_set = true;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (entry_monotonic_set &&
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_monotonic > le64toh(o->entry.monotonic)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
6ec60d20724d2a32e20d25ef75d2af178c242bc2Ronny Chevalier
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_monotonic = le64toh(o->entry.monotonic);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_boot_id = o->entry.boot_id;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_monotonic_set = true;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (!entry_realtime_set &&
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Head entry realtime timestamp incorrect");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_realtime = le64toh(o->entry.realtime);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt entry_realtime_set = true;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt n_entries ++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case OBJECT_DATA_HASH_TABLE:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (n_data_hash_tables > 1) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("More than one data hash table at %llu", (unsigned long long) p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) ||
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Header fields for data hash table invalid.");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt n_data_hash_tables++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case OBJECT_FIELD_HASH_TABLE:
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (n_field_hash_tables > 1) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt log_error("More than one field hash table at %llu", (unsigned long long) p);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = -EBADMSG;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt goto fail;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Header fields for field hash table invalid.");
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = -EBADMSG;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_field_hash_tables++;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt break;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt case OBJECT_ENTRY_ARRAY:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = write_uint64(entry_array_fd, p);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (p == le64toh(f->header->entry_array_offset)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (found_main_entry_array) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt log_error("More than one main entry array at %llu", (unsigned long long) p);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt found_main_entry_array = true;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_entry_arrays++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case OBJECT_TAG: {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt uint64_t q;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Tag object without sealing at %llu", (unsigned long long) p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -EBADMSG;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (le64toh(o->tag.seqnum) != n_tags + 1) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (le64toh(o->tag.epoch) < last_epoch) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_error("Epoch sequence out of synchronization at %llu", (unsigned long long) p);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt r = -EBADMSG;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt goto fail;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt /* OK, now we know the epoch. So let's now set
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt * it, and calculate the HMAC for everything
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt * since the last tag. */
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch));
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (r < 0)
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt goto fail;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = journal_file_hmac_start(f);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt goto fail;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (last_tag == 0) {
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = journal_file_hmac_put_header(f);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt goto fail;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt q = le64toh(f->header->header_size);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt } else
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt q = last_tag;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt while (q <= p) {
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = journal_file_move_to_object(f, -1, q, &o);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (r < 0)
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt goto fail;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = journal_file_hmac_put_object(f, -1, q);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (r < 0)
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt goto fail;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt q = q + ALIGN64(le64toh(o->object.size));
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt }
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt /* Position might have changed, let's reposition things */
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = journal_file_move_to_object(f, -1, p, &o);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt goto fail;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Tag failed verification at %llu", (unsigned long long) p);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = -EBADMSG;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt goto fail;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt f->hmac_running = false;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt last_tag = p + ALIGN64(le64toh(o->object.size));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_tags ++;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt break;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt default:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_weird ++;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (p == le64toh(f->header->tail_object_offset))
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt p = 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt p = p + ALIGN64(le64toh(o->object.size));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (n_objects != le64toh(f->header->n_objects)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Object number mismatch");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (n_entries != le64toh(f->header->n_entries)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Entry number mismatch");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_data != le64toh(f->header->n_data)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Data number mismatch");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_fields != le64toh(f->header->n_fields)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Field number mismatch");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_tags != le64toh(f->header->n_tags)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Tag number mismatch");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) &&
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt n_entry_arrays != le64toh(f->header->n_entry_arrays)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Entry array number mismatch");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = -EBADMSG;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto fail;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (n_data_hash_tables != 1) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Missing data hash table");
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = -EBADMSG;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt goto fail;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (n_field_hash_tables != 1) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Missing field hash table");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = -EBADMSG;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto fail;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!found_main_entry_array) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Missing entry array");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = -EBADMSG;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto fail;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (entry_seqnum_set &&
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt entry_seqnum != le64toh(f->header->tail_entry_seqnum)) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_error("Invalid tail seqnum");
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = -EBADMSG;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (entry_monotonic_set &&
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (!sd_id128_equal(entry_boot_id, f->header->boot_id) ||
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_error("Invalid tail monotonic timestamp");
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = -EBADMSG;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_error("Invalid tail realtime timestamp");
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek r = -EBADMSG;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt goto fail;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt /* Second iteration: we follow all objects referenced from the
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * two entry points: the object hash table and the entry
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * array. We also check that everything referenced (directly
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * or indirectly) in the data hash table also exists in the
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * entry array, and vice versa. Note that we do not care for
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * unreferenced objects. We only care that everything that is
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * referenced is consistent. */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = verify_entry_array(f,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt data_fd, n_data,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt entry_fd, n_entries,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt entry_array_fd, n_entry_arrays,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt &last_usec);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = verify_hash_table(f,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt data_fd, n_data,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt entry_fd, n_entries,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt entry_array_fd, n_entry_arrays,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt &last_usec);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt flush_progress();
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt mmap_cache_close_fd(f->mmap, data_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt mmap_cache_close_fd(f->mmap, entry_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt mmap_cache_close_fd(f->mmap, entry_array_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt close_nointr_nofail(data_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt close_nointr_nofail(entry_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt close_nointr_nofail(entry_array_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktfail:
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt flush_progress();
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_error("File corruption detected at %s:%llu (of %llu, %llu%%).",
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt f->path,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (unsigned long long) p,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (unsigned long long) f->last_stat.st_size,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (unsigned long long) (100 * p / f->last_stat.st_size));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (data_fd >= 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt mmap_cache_close_fd(f->mmap, data_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt close_nointr_nofail(data_fd);
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (entry_fd >= 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt mmap_cache_close_fd(f->mmap, entry_fd);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt close_nointr_nofail(entry_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (entry_array_fd >= 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt mmap_cache_close_fd(f->mmap, entry_array_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt close_nointr_nofail(entry_array_fd);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt