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

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