diff --git a/CVE-2020-9308.patch b/CVE-2020-9308.patch new file mode 100644 index 0000000000000000000000000000000000000000..b958d6682a662ad90e953be3f520fc28965a9a42 --- /dev/null +++ b/CVE-2020-9308.patch @@ -0,0 +1,119 @@ +From 09a14a16d91b6326cda53df117f012f890219ed8 Mon Sep 17 00:00:00 2001 +From: Grzegorz Antoniak +Date: Sun, 2 Feb 2020 08:04:41 +0100 +Subject: [PATCH] RAR5 reader: reject files that declare invalid header flags + +One of the fields in RAR5's base block structure is the size of the +header. Some invalid files declare a 0 header size setting, which can +confuse the unpacker. Minimum header size for RAR5 base blocks is 7 +bytes (4 bytes for CRC, and 3 bytes for the rest), so block size of 0 +bytes should be rejected at header parsing stage. + +The fix adds an error condition if header size of 0 bytes is detected. +In this case, the unpacker will not attempt to unpack the file, as the +header is corrupted. + +The commit also adds OSSFuzz #20459 sample to test further regressions +in this area. +--- + Makefile.am | 1 + + libarchive/archive_read_support_format_rar5.c | 17 +++++++++++++++-- + libarchive/test/test_read_format_rar5.c | 15 +++++++++++++++ + ...test_read_format_rar5_block_size_is_too_small.rar.uu | 8 ++++++++ + 4 files changed, 39 insertions(+), 2 deletions(-) + create mode 100644 libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu + +diff --git a/Makefile.am b/Makefile.am +index 781bbf7..c59466f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -876,6 +876,7 @@ libarchive_test_EXTRA_DIST=\ + libarchive/test/test_read_format_rar5_win32.rar.uu \ + libarchive/test/test_read_format_rar5_arm_filter_on_window_boundary.rar.uu \ + libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \ ++ libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \ + libarchive/test/test_read_format_raw.bufr.uu \ + libarchive/test/test_read_format_raw.data.gz.uu \ + libarchive/test/test_read_format_raw.data.Z.uu \ +diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c +index ce38b1f..970a924 100644 +--- a/libarchive/archive_read_support_format_rar5.c ++++ b/libarchive/archive_read_support_format_rar5.c +@@ -2080,6 +2080,8 @@ static int scan_for_signature(struct archive_read* a); + static int process_base_block(struct archive_read* a, + struct archive_entry* entry) + { ++ const size_t SMALLEST_RAR5_BLOCK_SIZE = 3; ++ + struct rar5* rar = get_context(a); + uint32_t hdr_crc, computed_crc; + size_t raw_hdr_size = 0, hdr_size_len, hdr_size; +@@ -2103,15 +2105,26 @@ static int process_base_block(struct archive_read* a, + return ARCHIVE_EOF; + } + ++ hdr_size = raw_hdr_size + hdr_size_len; ++ + /* Sanity check, maximum header size for RAR5 is 2MB. */ +- if(raw_hdr_size > (2 * 1024 * 1024)) { ++ if(hdr_size > (2 * 1024 * 1024)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Base block header is too large"); + + return ARCHIVE_FATAL; + } + +- hdr_size = raw_hdr_size + hdr_size_len; ++ /* Additional sanity checks to weed out invalid files. */ ++ if(raw_hdr_size == 0 || hdr_size_len == 0 || ++ hdr_size < SMALLEST_RAR5_BLOCK_SIZE) ++ { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Too small block encountered (%ld bytes)", ++ raw_hdr_size); ++ ++ return ARCHIVE_FATAL; ++ } + + /* Read the whole header data into memory, maximum memory use here is + * 2MB. */ +diff --git a/libarchive/test/test_read_format_rar5.c b/libarchive/test/test_read_format_rar5.c +index bb94d4e..f91521e 100644 +--- a/libarchive/test/test_read_format_rar5.c ++++ b/libarchive/test/test_read_format_rar5.c +@@ -1256,3 +1256,18 @@ DEFINE_TEST(test_read_format_rar5_different_winsize_on_merge) + + EPILOGUE(); + } ++ ++DEFINE_TEST(test_read_format_rar5_block_size_is_too_small) ++{ ++ char buf[4096]; ++ PROLOGUE("test_read_format_rar5_block_size_is_too_small.rar"); ++ ++ /* This file is damaged, so those functions should return failure. ++ * Additionally, SIGSEGV shouldn't be raised during execution ++ * of those functions. */ ++ ++ assertA(archive_read_next_header(a, &ae) != ARCHIVE_OK); ++ assertA(archive_read_data(a, buf, sizeof(buf)) <= 0); ++ ++ EPILOGUE(); ++} +diff --git a/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu b/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu +new file mode 100644 +index 0000000..5cad219 +--- /dev/null ++++ b/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu +@@ -0,0 +1,8 @@ ++begin 644 test_read_format_rar5_block_size_is_too_small.rar ++M4F%R(1H'`0"-[P+2``+'(!P,("`@N`,!`B`@("`@("`@("`@("`@("#_("`@ ++M("`@("`@("`@((:Q;2!4-'-^4B`!((WO`M(``O\@$/\@-R`@("`@("`@("`@ ++M``X@("`@("`@____("`@("`@(/\@("`@("`@("`@("#_(+6U,2"UM;6UM[CU ++M)B`@*(0G(`!.`#D\3R``(/__(,+_````-0#_($&%*/HE=C+N`"```"```"`D ++J`)$#("#_("#__P`@__\@_R#_("`@("`@("#_("#__R`@(/__("#__R`" ++` ++end +-- +1.8.3.1 + diff --git a/libarchive.spec b/libarchive.spec index 6b5944991f1df34ace602917c4456c510ed7f07a..88a9ef9ff9d88cd34b15b9d1c3c77e47575f236b 100644 --- a/libarchive.spec +++ b/libarchive.spec @@ -2,7 +2,7 @@ Name: libarchive Version: 3.4.1 -Release: 2 +Release: 3 Summary: Multi-format archive and compression library License: BSD @@ -17,6 +17,7 @@ Provides: bsdtar bsdcpio bsdcat Obsoletes: bsdtar bsdcpio bsdcat Patch6001: libarchive-uninitialized-value.patch +Patch6002: CVE-2020-9308.patch %description %{name} is an open-source BSD-licensed C programming library that @@ -147,6 +148,12 @@ run_testsuite %{_mandir}/man5/* %changelog +* Mon Apr 20 2020 openEuler Buildteam - 3.4.1-3 +- Type:cves +- ID:CVE-2020-9308 +- SUG:NA +- DESC:fix CVE-2020-9308 + * Tue Mar 10 2020 songnannan - 3.4.1-2 - bugfix about uninitialized value