journal-verify.c revision 56e81f7ca8276e40f8c88c4c30713a5b54009613
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering This file is part of systemd.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Copyright 2012 Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is free software; you can redistribute it and/or modify it
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering under the terms of the GNU Lesser General Public License as published by
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering (at your option) any later version.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is distributed in the hope that it will be useful, but
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Lesser General Public License for more details.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering You should have received a copy of the GNU Lesser General Public License
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering * - verify FSPRG
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering * - Allow building without libgcrypt
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering * - check with sparse
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering * - 64bit conversions
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic int journal_file_object_verify(JournalFile *f, Object *o) {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering /* This does various superficial tests about the length an
c2373f848dddcc1827cf715c5ef778dc8d475761Lennart Poettering * possible field values. It does not follow any references to
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering * other objects. */
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if ((o->object.flags & OBJECT_COMPRESSED) &&
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if (le64toh(o->data.entry_offset) <= 0 ||
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if (o->object.flags & OBJECT_COMPRESSED) {
de190aef08bb267b645205a747762df573b36834Lennart Poettering le64toh(o->object.size) - offsetof(Object, data.payload),
de190aef08bb267b645205a747762df573b36834Lennart Poettering h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
de190aef08bb267b645205a747762df573b36834Lennart Poettering if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0)
de190aef08bb267b645205a747762df573b36834Lennart Poettering if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0)
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
case OBJECT_ENTRY_ARRAY:
return -EBADMSG;
return -EBADMSG;
case OBJECT_TAG:
return -EBADMSG;
usec_t z, x;
x = *last_usec;
*last_usec = z;
static void flush_progress(void) {
ssize_t k;
return -errno;
return -EIO;
uint64_t a, b;
assert(m);
uint64_t c, *z;
r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, c * sizeof(uint64_t), sizeof(uint64_t), (void **) &z);
static int entry_points_to_data(
JournalFile *f,
int entry_fd,
uint64_t i, n, a;
Object *o;
bool found = false;
assert(f);
return -EBADMSG;
n = journal_file_entry_n_items(o);
found = true;
if (!found) {
return -EBADMSG;
uint64_t m, j;
m = journal_file_entry_array_n_items(o);
static int verify_data(
JournalFile *f,
assert(f);
assert(o);
assert(n > 0);
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
m = journal_file_entry_array_n_items(o);
if (q <= last) {
return -EBADMSG;
last = q;
a = next;
static int verify_hash_table(
JournalFile *f,
uint64_t i, n;
assert(f);
Object *o;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
last = p;
p = next;
return -EBADMSG;
uint64_t n, h, q;
assert(f);
h = hash % n;
Object *o;
static int verify_entry(
JournalFile *f,
uint64_t i, n;
assert(f);
assert(o);
n = journal_file_entry_n_items(o);
uint64_t q, h;
Object *u;
return -EBADMSG;
return -EBADMSG;
r = data_object_in_hash_table(f, h, q);
return -EBADMSG;
static int verify_entry_array(
JournalFile *f,
assert(f);
Object *o;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
m = journal_file_entry_array_n_items(o);
uint64_t p;
if (p <= last) {
return -EBADMSG;
last = p;
return -EBADMSG;
a = next;
if (!seed)
return -ENOMEM;
for (c = 0; c < seed_size; c++) {
x = unhexchar(*k);
return -EINVAL;
y = unhexchar(*k);
return -EINVAL;
return -EINVAL;
return -EINVAL;
Object *o;
uint64_t p = 0;
bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
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;
assert(f);
if (seed) {
if (data_fd < 0) {
r = -errno;
goto fail;
if (entry_fd < 0) {
r = -errno;
goto fail;
if (entry_array_fd < 0) {
r = -errno;
goto fail;
r = journal_file_hmac_put_header(f);
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
n_objects ++;
r = journal_file_object_verify(f, o);
goto fail;
r = -EBADMSG;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
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 ++;
goto fail;
if (found_main_entry_array) {
r = -EBADMSG;
goto fail;
found_main_entry_array = true;
goto fail;
n_data++;
n_fields++;
r = -EBADMSG;
goto fail;
le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
r = -EBADMSG;
goto fail;
n_weird ++;
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,
&last_usec);
goto fail;
r = verify_hash_table(f,
&last_usec);
goto fail;
fail:
f->path,
if (data_fd >= 0) {
if (entry_fd >= 0) {
if (entry_array_fd >= 0) {