diff options
author | Tobias Stoeckmann <stoeckmann@users.noreply.github.com> | 2017-03-13 08:14:42 +0100 |
---|---|---|
committer | Martin Pitt <martinpitt@users.noreply.github.com> | 2017-03-13 08:14:42 +0100 |
commit | 6f94e420e8355421fc31713a0df760d6b20473ac (patch) | |
tree | 23ade59ba785d02c64ada0a17e936aaa54acbcb2 /src/journal/journal-file.c | |
parent | Merge pull request #5571 from keszybz/tarball-generation-tweaks (diff) | |
download | systemd-6f94e420e8355421fc31713a0df760d6b20473ac.tar.xz systemd-6f94e420e8355421fc31713a0df760d6b20473ac.zip |
journal: prevent integer overflow while validating header (#5569)
It is possible to overflow uint64_t while validating the header of
a journal file. To prevent this, the addition itself is checked to
be within the limits of UINT64_MAX first.
To keep this readable, I have introduced two stack variables which
hold the converted values during validation.
Diffstat (limited to '')
-rw-r--r-- | src/journal/journal-file.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index a6ccb679a8..14cb01a600 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -546,6 +546,8 @@ static bool warn_wrong_flags(const JournalFile *f, bool compatible) { } static int journal_file_verify_header(JournalFile *f) { + uint64_t arena_size, header_size; + assert(f); assert(f->header); @@ -564,17 +566,21 @@ static int journal_file_verify_header(JournalFile *f) { if (f->header->state >= _STATE_MAX) return -EBADMSG; + header_size = le64toh(f->header->header_size); + /* The first addition was n_data, so check that we are at least this large */ - if (le64toh(f->header->header_size) < HEADER_SIZE_MIN) + if (header_size < HEADER_SIZE_MIN) return -EBADMSG; if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) return -EBADMSG; - if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size) + arena_size = le64toh(f->header->arena_size); + + if (UINT64_MAX - header_size < arena_size || header_size + 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))) + if (le64toh(f->header->tail_object_offset) > header_size + arena_size) return -ENODATA; if (!VALID64(le64toh(f->header->data_hash_table_offset)) || |