]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journal: prevent integer overflow while validating header (#5569) 5496/head
authorTobias Stoeckmann <stoeckmann@users.noreply.github.com>
Mon, 13 Mar 2017 07:14:42 +0000 (08:14 +0100)
committerMartin Pitt <martinpitt@users.noreply.github.com>
Mon, 13 Mar 2017 07:14:42 +0000 (08:14 +0100)
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.

src/journal/journal-file.c

index a6ccb679a8413b1096416050d37cba02522b78d5..14cb01a6001978667dbf6299da10736489dfa2f3 100644 (file)
@@ -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)) ||