+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \
} while (0)
+#define error_errno(_offset, error, _fmt, ...) do { \
+ flush_progress(); \
+ log_error_errno(error, OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \
+ } while (0)
+
static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) {
uint64_t i;
warning(offset, "Unused data (entry_offset==0)");
if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) {
- error(offset, "Bad n_entries: %"PRIu64, o->data.n_entries);
+ error(offset, "Bad n_entries: %"PRIu64, le64toh(o->data.n_entries));
return -EBADMSG;
}
le64toh(o->object.size) - offsetof(Object, data.payload),
&b, &alloc, &b_size, 0);
if (r < 0) {
- error(offset, "%s decompression failed: %s",
- object_compressed_to_string(compression), strerror(-r));
+ error_errno(offset, r, "%s decompression failed: %m",
+ object_compressed_to_string(compression));
return r;
}
return -EBADMSG;
}
- if (!VALID64(o->data.next_hash_offset) ||
- !VALID64(o->data.next_field_offset) ||
- !VALID64(o->data.entry_offset) ||
- !VALID64(o->data.entry_array_offset)) {
+ if (!VALID64(le64toh(o->data.next_hash_offset)) ||
+ !VALID64(le64toh(o->data.next_field_offset)) ||
+ !VALID64(le64toh(o->data.entry_offset)) ||
+ !VALID64(le64toh(o->data.entry_array_offset))) {
error(offset, "Invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt,
- o->data.next_hash_offset,
- o->data.next_field_offset,
- o->data.entry_offset,
- o->data.entry_array_offset);
+ le64toh(o->data.next_hash_offset),
+ le64toh(o->data.next_field_offset),
+ le64toh(o->data.entry_offset),
+ le64toh(o->data.entry_array_offset));
return -EBADMSG;
}
return -EBADMSG;
}
- if (!VALID64(o->field.next_hash_offset) ||
- !VALID64(o->field.head_data_offset)) {
+ if (!VALID64(le64toh(o->field.next_hash_offset)) ||
+ !VALID64(le64toh(o->field.head_data_offset))) {
error(offset,
"Invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt,
- o->field.next_hash_offset,
- o->field.head_data_offset);
+ le64toh(o->field.next_hash_offset),
+ le64toh(o->field.head_data_offset));
return -EBADMSG;
}
break;
}
for (i = 0; i < journal_file_entry_n_items(o); i++) {
- if (o->entry.items[i].object_offset == 0 ||
- !VALID64(o->entry.items[i].object_offset)) {
+ if (le64toh(o->entry.items[i].object_offset) == 0 ||
+ !VALID64(le64toh(o->entry.items[i].object_offset))) {
error(offset,
"Invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt,
i, journal_file_entry_n_items(o),
- o->entry.items[i].object_offset);
+ le64toh(o->entry.items[i].object_offset));
return -EBADMSG;
}
}
return -EBADMSG;
}
- if (!VALID64(o->entry_array.next_entry_array_offset)) {
+ if (!VALID64(le64toh(o->entry_array.next_entry_array_offset))) {
error(offset,
"Invalid object entry array next_entry_array_offset: "OFSfmt,
- o->entry_array.next_entry_array_offset);
+ le64toh(o->entry_array.next_entry_array_offset));
return -EBADMSG;
}
return -EBADMSG;
}
- if (!VALID_EPOCH(o->tag.epoch)) {
+ if (!VALID_EPOCH(le64toh(o->tag.epoch))) {
error(offset,
"Invalid object tag epoch: %"PRIu64,
- o->tag.epoch);
+ le64toh(o->tag.epoch));
return -EBADMSG;
}
return 0;
}
-static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
+static int contains_uint64(MMapCache *m, MMapFileDescriptor *f, uint64_t n, uint64_t p) {
uint64_t a, b;
int r;
assert(m);
- assert(fd >= 0);
+ assert(f);
/* Bisection ... */
c = (a + b) / 2;
- r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
+ r = mmap_cache_get(m, f, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, NULL);
if (r < 0)
return r;
static int entry_points_to_data(
JournalFile *f,
- int entry_fd,
+ MMapFileDescriptor *cache_entry_fd,
uint64_t n_entries,
uint64_t entry_p,
uint64_t data_p) {
bool found = false;
assert(f);
- assert(entry_fd >= 0);
+ assert(cache_entry_fd);
- if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
+ if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, entry_p)) {
error(data_p, "Data object references invalid entry at "OFSfmt, entry_p);
return -EBADMSG;
}
static int verify_data(
JournalFile *f,
Object *o, uint64_t p,
- int entry_fd, uint64_t n_entries,
- int entry_array_fd, uint64_t n_entry_arrays) {
+ MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
+ MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays) {
uint64_t i, n, a, last, q;
int r;
assert(f);
assert(o);
- assert(entry_fd >= 0);
- assert(entry_array_fd >= 0);
+ assert(cache_entry_fd);
+ assert(cache_entry_array_fd);
n = le64toh(o->data.n_entries);
a = le64toh(o->data.entry_array_offset);
assert(o->data.entry_offset);
last = q = le64toh(o->data.entry_offset);
- r = entry_points_to_data(f, entry_fd, n_entries, q, p);
+ r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p);
if (r < 0)
return r;
return -EBADMSG;
}
- if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
+ if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) {
error(p, "Invalid array offset "OFSfmt, a);
return -EBADMSG;
}
}
last = q;
- r = entry_points_to_data(f, entry_fd, n_entries, q, p);
+ r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p);
if (r < 0)
return r;
static int verify_hash_table(
JournalFile *f,
- int data_fd, uint64_t n_data,
- int entry_fd, uint64_t n_entries,
- int entry_array_fd, uint64_t n_entry_arrays,
+ MMapFileDescriptor *cache_data_fd, uint64_t n_data,
+ MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
+ MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays,
usec_t *last_usec,
bool show_progress) {
int r;
assert(f);
- assert(data_fd >= 0);
- assert(entry_fd >= 0);
- assert(entry_array_fd >= 0);
+ assert(cache_data_fd);
+ assert(cache_entry_fd);
+ assert(cache_entry_array_fd);
assert(last_usec);
n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
Object *o;
uint64_t next;
- if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
+ if (!contains_uint64(f->mmap, cache_data_fd, n_data, p)) {
error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
return -EBADMSG;
}
- r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays);
+ r = verify_data(f, o, p, cache_entry_fd, n_entries, cache_entry_array_fd, n_entry_arrays);
if (r < 0)
return r;
static int verify_entry(
JournalFile *f,
Object *o, uint64_t p,
- int data_fd, uint64_t n_data) {
+ MMapFileDescriptor *cache_data_fd, uint64_t n_data) {
uint64_t i, n;
int r;
assert(f);
assert(o);
- assert(data_fd >= 0);
+ assert(cache_data_fd);
n = journal_file_entry_n_items(o);
for (i = 0; i < n; i++) {
q = le64toh(o->entry.items[i].object_offset);
h = le64toh(o->entry.items[i].hash);
- if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
+ if (!contains_uint64(f->mmap, cache_data_fd, n_data, q)) {
error(p, "Invalid data object of entry");
return -EBADMSG;
}
static int verify_entry_array(
JournalFile *f,
- int data_fd, uint64_t n_data,
- int entry_fd, uint64_t n_entries,
- int entry_array_fd, uint64_t n_entry_arrays,
+ MMapFileDescriptor *cache_data_fd, uint64_t n_data,
+ MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
+ MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays,
usec_t *last_usec,
bool show_progress) {
int r;
assert(f);
- assert(data_fd >= 0);
- assert(entry_fd >= 0);
- assert(entry_array_fd >= 0);
+ assert(cache_data_fd);
+ assert(cache_entry_fd);
+ assert(cache_entry_array_fd);
assert(last_usec);
n = le64toh(f->header->n_entries);
return -EBADMSG;
}
- if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
+ if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) {
error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
}
last = p;
- if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
+ if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, p)) {
error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
if (r < 0)
return r;
- r = verify_entry(f, o, p, data_fd, n_data);
+ r = verify_entry(f, o, p, cache_data_fd, n_data);
if (r < 0)
return r;
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;
usec_t last_usec = 0;
int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
+ MMapFileDescriptor *cache_data_fd = NULL, *cache_entry_fd = NULL, *cache_entry_array_fd = NULL;
unsigned i;
bool found_last = false;
- _cleanup_free_ char *tmp_dir = NULL;
+ const char *tmp_dir = NULL;
-#ifdef HAVE_GCRYPT
+#if HAVE_GCRYPT
uint64_t last_tag = 0;
#endif
assert(f);
if (key) {
-#ifdef HAVE_GCRYPT
+#if HAVE_GCRYPT
r = journal_file_parse_verification_key(f, key);
if (r < 0) {
log_error("Failed to parse seed.");
} else if (f->seal)
return -ENOKEY;
- r = var_tmp(&tmp_dir);
+ r = var_tmp_dir(&tmp_dir);
if (r < 0) {
log_error_errno(r, "Failed to determine temporary directory: %m");
goto fail;
goto fail;
}
+ cache_data_fd = mmap_cache_add_fd(f->mmap, data_fd);
+ if (!cache_data_fd) {
+ r = log_oom();
+ goto fail;
+ }
+
+ cache_entry_fd = mmap_cache_add_fd(f->mmap, entry_fd);
+ if (!cache_entry_fd) {
+ r = log_oom();
+ goto fail;
+ }
+
+ cache_entry_array_fd = mmap_cache_add_fd(f->mmap, entry_array_fd);
+ if (!cache_entry_array_fd) {
+ r = log_oom();
+ goto fail;
+ }
+
if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) {
log_error("Cannot verify file with unknown extensions.");
r = -EOPNOTSUPP;
r = journal_file_object_verify(f, p, o);
if (r < 0) {
- error(p, "Invalid object contents: %s", strerror(-r));
+ error_errno(p, r, "Invalid object contents: %m");
goto fail;
}
goto fail;
}
-#ifdef HAVE_GCRYPT
+#if HAVE_GCRYPT
if (f->seal) {
uint64_t q, rt;
debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
- rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
+ rt = f->fss_start_usec + le64toh(o->tag.epoch) * f->fss_interval_usec;
if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
error(p, "tag/entry realtime timestamp out of synchronization");
r = -EBADMSG;
* referenced is consistent. */
r = verify_entry_array(f,
- data_fd, n_data,
- entry_fd, n_entries,
- entry_array_fd, n_entry_arrays,
+ cache_data_fd, n_data,
+ cache_entry_fd, n_entries,
+ cache_entry_array_fd, n_entry_arrays,
&last_usec,
show_progress);
if (r < 0)
goto fail;
r = verify_hash_table(f,
- data_fd, n_data,
- entry_fd, n_entries,
- entry_array_fd, n_entry_arrays,
+ cache_data_fd, n_data,
+ cache_entry_fd, n_entries,
+ cache_entry_array_fd, n_entry_arrays,
&last_usec,
show_progress);
if (r < 0)
if (show_progress)
flush_progress();
- mmap_cache_close_fd(f->mmap, data_fd);
- mmap_cache_close_fd(f->mmap, entry_fd);
- mmap_cache_close_fd(f->mmap, entry_array_fd);
+ mmap_cache_free_fd(f->mmap, cache_data_fd);
+ mmap_cache_free_fd(f->mmap, cache_entry_fd);
+ mmap_cache_free_fd(f->mmap, cache_entry_array_fd);
safe_close(data_fd);
safe_close(entry_fd);
(unsigned long long) f->last_stat.st_size,
100 * p / f->last_stat.st_size);
- if (data_fd >= 0) {
- mmap_cache_close_fd(f->mmap, data_fd);
+ if (data_fd >= 0)
safe_close(data_fd);
- }
- if (entry_fd >= 0) {
- mmap_cache_close_fd(f->mmap, entry_fd);
+ if (entry_fd >= 0)
safe_close(entry_fd);
- }
- if (entry_array_fd >= 0) {
- mmap_cache_close_fd(f->mmap, entry_array_fd);
+ if (entry_array_fd >= 0)
safe_close(entry_array_fd);
- }
+
+ if (cache_data_fd)
+ mmap_cache_free_fd(f->mmap, cache_data_fd);
+
+ if (cache_entry_fd)
+ mmap_cache_free_fd(f->mmap, cache_entry_fd);
+
+ if (cache_entry_array_fd)
+ mmap_cache_free_fd(f->mmap, cache_entry_array_fd);
return r;
}