summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/journal/journal-def.h7
-rw-r--r--src/journal/journal-file.c18
-rw-r--r--src/journal/journal-file.h1
-rw-r--r--src/journal/journal-verify.c21
4 files changed, 43 insertions, 4 deletions
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
index 52c55ab4bb..45c3cde9f0 100644
--- a/src/journal/journal-def.h
+++ b/src/journal/journal-def.h
@@ -140,9 +140,10 @@ union Object {
};
enum {
- STATE_OFFLINE,
- STATE_ONLINE,
- STATE_ARCHIVED
+ STATE_OFFLINE = 0,
+ STATE_ONLINE = 1,
+ STATE_ARCHIVED = 2,
+ _STATE_MAX
};
/* Header flags */
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 08d4285d0e..3cf28a7f3c 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -203,6 +203,9 @@ static int journal_file_verify_header(JournalFile *f) {
#endif
}
+ if (f->header->state >= _STATE_MAX)
+ return -EBADMSG;
+
/* The first addition was n_data, so check that we are at least this large */
if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
return -EBADMSG;
@@ -211,7 +214,16 @@ static int journal_file_verify_header(JournalFile *f) {
!JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
return -EBADMSG;
- if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
+ if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size)
+ return -ENODATA;
+
+ if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
+ return -ENODATA;
+
+ if (!VALID64(f->header->data_hash_table_offset) ||
+ !VALID64(f->header->field_hash_table_offset) ||
+ !VALID64(f->header->tail_object_offset) ||
+ !VALID64(f->header->entry_array_offset))
return -ENODATA;
if (f->writable) {
@@ -351,6 +363,10 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec
assert(f);
assert(ret);
+ /* Objects may only be located at multiple of 64 bit */
+ if (!VALID64(offset))
+ return -EFAULT;
+
/* One context for each type, plus one catch-all for the rest */
context = type > 0 && type < _OBJECT_TYPE_MAX ? type : 0;
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 58de214359..2d2bf319a0 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -117,6 +117,7 @@ int journal_file_open_reliably(
JournalFile **ret);
#define ALIGN64(x) (((x) + 7ULL) & ~7ULL)
+#define VALID64(x) (((x) & 7ULL) == 0ULL)
#define JOURNAL_HEADER_CONTAINS(h, field) \
(le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field))
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index f9a930e42e..7be0d2e5d7 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -45,6 +45,8 @@
* */
static int journal_file_object_verify(JournalFile *f, Object *o) {
+ uint64_t i;
+
assert(f);
assert(o);
@@ -87,12 +89,22 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
if (h1 != h2)
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))
+ return -EBADMSG;
+
break;
}
case OBJECT_FIELD:
if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
return -EBADMSG;
+
+ if (!VALID64(o->field.next_hash_offset) ||
+ !VALID64(o->field.head_data_offset))
+ return -EBADMSG;
break;
case OBJECT_ENTRY:
@@ -106,6 +118,12 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
le64toh(o->entry.realtime) <= 0)
return -EBADMSG;
+ 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))
+ return -EBADMSG;
+ }
+
break;
case OBJECT_DATA_HASH_TABLE:
@@ -125,6 +143,9 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0)
return -EBADMSG;
+ if (!VALID64(o->entry_array.next_entry_array_offset))
+ return -EBADMSG;
+
break;
case OBJECT_TAG: