Blame SOURCES/libarchive-3.3.2-CVE-2018-1000878.patch

87e122
From d00ccaf8c20efbd009964e3e2697d26907d14163 Mon Sep 17 00:00:00 2001
87e122
From: Ondrej Dubaj <odubaj@redhat.com>
87e122
Date: Tue, 30 Apr 2019 11:36:08 +0200
87e122
Subject: [PATCH] rar: file split across multi-part archives must match
87e122
87e122
Fuzzing uncovered some UAF and memory overrun bugs where a file in a
87e122
single file archive reported that it was split across multiple
87e122
volumes. This was caused by ppmd7 operations calling
87e122
rar_br_fillup. This would invoke rar_read_ahead, which would in some
87e122
situations invoke archive_read_format_rar_read_header.  That would
87e122
check the new file name against the old file name, and if they didn't
87e122
match up it would free the ppmd7 buffer and allocate a new
87e122
one. However, because the ppmd7 decoder wasn't actually done with the
87e122
buffer, it would continue to used the freed buffer. Both reads and
87e122
writes to the freed region can be observed.
87e122
87e122
This is quite tricky to solve: once the buffer has been freed it is
87e122
too late, as the ppmd7 decoder functions almost universally assume
87e122
success - there's no way for ppmd_read to signal error, nor are there
87e122
good ways for functions like Range_Normalise to propagate them. So we
87e122
can't detect after the fact that we're in an invalid state - e.g. by
87e122
checking rar->cursor, we have to prevent ourselves from ever ending up
87e122
there. So, when we are in the dangerous part or rar_read_ahead that
87e122
assumes a valid split, we set a flag force read_header to either go
87e122
down the path for split files or bail. This means that the ppmd7
87e122
decoder keeps a valid buffer and just runs out of data.
87e122
87e122
Found with a combination of AFL, afl-rb and qsym.
87e122
---
87e122
 libarchive/archive_read_support_format_rar.c | 9 +++++++++
87e122
 1 file changed, 9 insertions(+)
87e122
87e122
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
87e122
index cbb14c3..c4a8278 100644
87e122
--- a/libarchive/archive_read_support_format_rar.c
87e122
+++ b/libarchive/archive_read_support_format_rar.c
87e122
@@ -258,6 +258,7 @@ struct rar
87e122
   struct data_block_offsets *dbo;
87e122
   unsigned int cursor;
87e122
   unsigned int nodes;
87e122
+  char filename_must_match;
87e122
 
87e122
   /* LZSS members */
87e122
   struct huffman_code maincode;
87e122
@@ -1570,6 +1571,12 @@ read_header(struct archive_read *a, struct archive_entry *entry,
87e122
     }
87e122
     return ret;
87e122
   }
87e122
+  else if (rar->filename_must_match)
87e122
+  {
87e122
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
87e122
+      "Mismatch of file parts split across multi-volume archive");
87e122
+    return (ARCHIVE_FATAL);
87e122
+  }
87e122
 
87e122
   rar->filename_save = (char*)realloc(rar->filename_save,
87e122
                                       filename_size + 1);
87e122
@@ -2938,12 +2945,14 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
87e122
     else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
87e122
       rar->file_flags & FHD_SPLIT_AFTER)
87e122
     {
87e122
+      rar->filename_must_match = 1;
87e122
       ret = archive_read_format_rar_read_header(a, a->entry);
87e122
       if (ret == (ARCHIVE_EOF))
87e122
       {
87e122
         rar->has_endarc_header = 1;
87e122
         ret = archive_read_format_rar_read_header(a, a->entry);
87e122
       }
87e122
+      rar->filename_must_match = 0;
87e122
       if (ret != (ARCHIVE_OK))
87e122
         return NULL;
87e122
       return rar_read_ahead(a, min, avail);
87e122
-- 
87e122
2.17.1
87e122