libarchive: fix CVE-2020-9308

This commit is contained in:
Vchanger 2020-04-20 11:33:06 +08:00
parent 066e6fb76c
commit a697354826
2 changed files with 127 additions and 1 deletions

119
CVE-2020-9308.patch Normal file
View File

@ -0,0 +1,119 @@
From 09a14a16d91b6326cda53df117f012f890219ed8 Mon Sep 17 00:00:00 2001
From: Grzegorz Antoniak <ga@anadoxin.org>
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

View File

@ -2,7 +2,7 @@
Name: libarchive Name: libarchive
Version: 3.4.1 Version: 3.4.1
Release: 2 Release: 3
Summary: Multi-format archive and compression library Summary: Multi-format archive and compression library
License: BSD License: BSD
@ -17,6 +17,7 @@ Provides: bsdtar bsdcpio bsdcat
Obsoletes: bsdtar bsdcpio bsdcat Obsoletes: bsdtar bsdcpio bsdcat
Patch6001: libarchive-uninitialized-value.patch Patch6001: libarchive-uninitialized-value.patch
Patch6002: CVE-2020-9308.patch
%description %description
%{name} is an open-source BSD-licensed C programming library that %{name} is an open-source BSD-licensed C programming library that
@ -147,6 +148,12 @@ run_testsuite
%{_mandir}/man5/* %{_mandir}/man5/*
%changelog %changelog
* Mon Apr 20 2020 openEuler Buildteam <buildteam@openeuler.org> - 3.4.1-3
- Type:cves
- ID:CVE-2020-9308
- SUG:NA
- DESC:fix CVE-2020-9308
* Tue Mar 10 2020 songnannan <songnannan2@huawei.com> - 3.4.1-2 * Tue Mar 10 2020 songnannan <songnannan2@huawei.com> - 3.4.1-2
- bugfix about uninitialized value - bugfix about uninitialized value