From c118cad47751588a5bdbe6b7d2bda1a77b9aea6f9ca0265a66efb6b589b94d7b Mon Sep 17 00:00:00 2001 From: Martin Pluskal Date: Fri, 4 Jan 2019 08:14:08 +0000 Subject: [PATCH] Accepting request 662692 from home:kbabioch:branches:Archiving - Added patches: * CVE-2018-1000877.patch, which fixes a double free vulnerability in RAR decoder (CVE-2018-1000877 bsc#1120653) * CVE-2018-1000878.patch, which fixes a Use-After-Free vulnerability in RAR decoder (CVE-2018-1000878 bsc#1120654) * CVE-2018-1000879.patch, which fixes a NULL Pointer Dereference vulnerability in ACL parser (CVE-2018-1000879 bsc#1120656) * CVE-2018-1000880.patch, which fixes an improper input validation vulnerability in WARC parser (CVE-2018-1000880 bsc#1120659) - Make use of %license macro - Applied spec-cleaner OBS-URL: https://build.opensuse.org/request/show/662692 OBS-URL: https://build.opensuse.org/package/show/Archiving/libarchive?expand=0&rev=80 --- CVE-2018-1000877.patch | 31 ++++++++++++++++++ CVE-2018-1000878.patch | 72 ++++++++++++++++++++++++++++++++++++++++++ CVE-2018-1000879.patch | 43 +++++++++++++++++++++++++ CVE-2018-1000880.patch | 37 ++++++++++++++++++++++ libarchive.changes | 15 +++++++++ libarchive.spec | 49 ++++++++++++++-------------- 6 files changed, 223 insertions(+), 24 deletions(-) create mode 100644 CVE-2018-1000877.patch create mode 100644 CVE-2018-1000878.patch create mode 100644 CVE-2018-1000879.patch create mode 100644 CVE-2018-1000880.patch diff --git a/CVE-2018-1000877.patch b/CVE-2018-1000877.patch new file mode 100644 index 0000000..147979c --- /dev/null +++ b/CVE-2018-1000877.patch @@ -0,0 +1,31 @@ +From 021efa522ad729ff0f5806c4ce53e4a6cc1daa31 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 20 Nov 2018 17:56:29 +1100 +Subject: [PATCH] Avoid a double-free when a window size of 0 is specified + +new_size can be 0 with a malicious or corrupted RAR archive. + +realloc(area, 0) is equivalent to free(area), so the region would +be free()d here and the free()d again in the cleanup function. + +Found with a setup running AFL, afl-rb, and qsym. +--- + libarchive/archive_read_support_format_rar.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c +index 234522229..6f419c270 100644 +--- a/libarchive/archive_read_support_format_rar.c ++++ b/libarchive/archive_read_support_format_rar.c +@@ -2300,6 +2300,11 @@ parse_codes(struct archive_read *a) + new_size = DICTIONARY_MAX_SIZE; + else + new_size = rar_fls((unsigned int)rar->unp_size) << 1; ++ if (new_size == 0) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Zero window size is invalid."); ++ return (ARCHIVE_FATAL); ++ } + new_window = realloc(rar->lzss.window, new_size); + if (new_window == NULL) { + archive_set_error(&a->archive, ENOMEM, diff --git a/CVE-2018-1000878.patch b/CVE-2018-1000878.patch new file mode 100644 index 0000000..0c615d5 --- /dev/null +++ b/CVE-2018-1000878.patch @@ -0,0 +1,72 @@ +From bfcfe6f04ed20db2504db8a254d1f40a1d84eb28 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 4 Dec 2018 00:55:22 +1100 +Subject: [PATCH] rar: file split across multi-part archives must match + +Fuzzing uncovered some UAF and memory overrun bugs where a file in a +single file archive reported that it was split across multiple +volumes. This was caused by ppmd7 operations calling +rar_br_fillup. This would invoke rar_read_ahead, which would in some +situations invoke archive_read_format_rar_read_header. That would +check the new file name against the old file name, and if they didn't +match up it would free the ppmd7 buffer and allocate a new +one. However, because the ppmd7 decoder wasn't actually done with the +buffer, it would continue to used the freed buffer. Both reads and +writes to the freed region can be observed. + +This is quite tricky to solve: once the buffer has been freed it is +too late, as the ppmd7 decoder functions almost universally assume +success - there's no way for ppmd_read to signal error, nor are there +good ways for functions like Range_Normalise to propagate them. So we +can't detect after the fact that we're in an invalid state - e.g. by +checking rar->cursor, we have to prevent ourselves from ever ending up +there. So, when we are in the dangerous part or rar_read_ahead that +assumes a valid split, we set a flag force read_header to either go +down the path for split files or bail. This means that the ppmd7 +decoder keeps a valid buffer and just runs out of data. + +Found with a combination of AFL, afl-rb and qsym. +--- + libarchive/archive_read_support_format_rar.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c +index 6f419c270..a8cc5c94d 100644 +--- a/libarchive/archive_read_support_format_rar.c ++++ b/libarchive/archive_read_support_format_rar.c +@@ -258,6 +258,7 @@ struct rar + struct data_block_offsets *dbo; + unsigned int cursor; + unsigned int nodes; ++ char filename_must_match; + + /* LZSS members */ + struct huffman_code maincode; +@@ -1560,6 +1561,12 @@ read_header(struct archive_read *a, struct archive_entry *entry, + } + return ret; + } ++ else if (rar->filename_must_match) ++ { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Mismatch of file parts split across multi-volume archive"); ++ return (ARCHIVE_FATAL); ++ } + + rar->filename_save = (char*)realloc(rar->filename_save, + filename_size + 1); +@@ -2933,12 +2940,14 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) + else if (*avail == 0 && rar->main_flags & MHD_VOLUME && + rar->file_flags & FHD_SPLIT_AFTER) + { ++ rar->filename_must_match = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + { + rar->has_endarc_header = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + } ++ rar->filename_must_match = 0; + if (ret != (ARCHIVE_OK)) + return NULL; + return rar_read_ahead(a, min, avail); diff --git a/CVE-2018-1000879.patch b/CVE-2018-1000879.patch new file mode 100644 index 0000000..3e535aa --- /dev/null +++ b/CVE-2018-1000879.patch @@ -0,0 +1,43 @@ +From 15bf44fd2c1ad0e3fd87048b3fcc90c4dcff1175 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 4 Dec 2018 14:29:42 +1100 +Subject: [PATCH] Skip 0-length ACL fields + +Currently, it is possible to create an archive that crashes bsdtar +with a malformed ACL: + +Program received signal SIGSEGV, Segmentation fault. +archive_acl_from_text_l (acl=, text=0x7e2e92 "", want_type=, sc=) at libarchive/archive_acl.c:1726 +1726 switch (*s) { +(gdb) p n +$1 = 1 +(gdb) p field[n] +$2 = {start = 0x0, end = 0x0} + +Stop this by checking that the length is not zero before beginning +the switch statement. + +I am pretty sure this is the bug mentioned in the qsym paper [1], +and I was able to replicate it with a qsym + AFL + afl-rb setup. + +[1] https://www.usenix.org/conference/usenixsecurity18/presentation/yun +--- + libarchive/archive_acl.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c +index 512beee1f..7beeee86e 100644 +--- a/libarchive/archive_acl.c ++++ b/libarchive/archive_acl.c +@@ -1723,6 +1723,11 @@ archive_acl_from_text_l(struct archive_acl *acl, const char *text, + st = field[n].start + 1; + len = field[n].end - field[n].start; + ++ if (len == 0) { ++ ret = ARCHIVE_WARN; ++ continue; ++ } ++ + switch (*s) { + case 'u': + if (len == 1 || (len == 4 diff --git a/CVE-2018-1000880.patch b/CVE-2018-1000880.patch new file mode 100644 index 0000000..99c64db --- /dev/null +++ b/CVE-2018-1000880.patch @@ -0,0 +1,37 @@ +From 9c84b7426660c09c18cc349f6d70b5f8168b5680 Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Tue, 4 Dec 2018 16:33:42 +1100 +Subject: [PATCH] warc: consume data once read + +The warc decoder only used read ahead, it wouldn't actually consume +data that had previously been printed. This means that if you specify +an invalid content length, it will just reprint the same data over +and over and over again until it hits the desired length. + +This means that a WARC resource with e.g. +Content-Length: 666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665 +but only a few hundred bytes of data, causes a quasi-infinite loop. + +Consume data in subsequent calls to _warc_read. + +Found with an AFL + afl-rb + qsym setup. +--- + libarchive/archive_read_support_format_warc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c +index e8753853f..e8fc8428b 100644 +--- a/libarchive/archive_read_support_format_warc.c ++++ b/libarchive/archive_read_support_format_warc.c +@@ -386,6 +386,11 @@ _warc_read(struct archive_read *a, const void **buf, size_t *bsz, int64_t *off) + return (ARCHIVE_EOF); + } + ++ if (w->unconsumed) { ++ __archive_read_consume(a, w->unconsumed); ++ w->unconsumed = 0U; ++ } ++ + rab = __archive_read_ahead(a, 1U, &nrd); + if (nrd < 0) { + *bsz = 0U; diff --git a/libarchive.changes b/libarchive.changes index a82cf4c..b42da68 100644 --- a/libarchive.changes +++ b/libarchive.changes @@ -1,3 +1,18 @@ +------------------------------------------------------------------- +Thu Jan 3 15:26:58 UTC 2019 - Karol Babioch + +- Added patches: + * CVE-2018-1000877.patch, which fixes a double free vulnerability in RAR + decoder (CVE-2018-1000877 bsc#1120653) + * CVE-2018-1000878.patch, which fixes a Use-After-Free vulnerability in RAR + decoder (CVE-2018-1000878 bsc#1120654) + * CVE-2018-1000879.patch, which fixes a NULL Pointer Dereference + vulnerability in ACL parser (CVE-2018-1000879 bsc#1120656) + * CVE-2018-1000880.patch, which fixes an improper input validation + vulnerability in WARC parser (CVE-2018-1000880 bsc#1120659) +- Make use of %license macro +- Applied spec-cleaner + ------------------------------------------------------------------- Tue Sep 18 07:08:54 UTC 2018 - Jan Engelhardt diff --git a/libarchive.spec b/libarchive.spec index 48db16c..5524e0a 100644 --- a/libarchive.spec +++ b/libarchive.spec @@ -1,7 +1,7 @@ # # spec file for package libarchive # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,45 +16,46 @@ # +%define somajor 13 +%define libname libarchive%{somajor} %if 0%{?centos_version} || 0%{?rhel_version} %if 0%{?centos_version} <= 600 || 0%{?rhel_version <= 700} +%define skip_autoreconf 1 %bcond_without static_libs %bcond_with openssl %bcond_with ext2fs -%define skip_autoreconf 1 %endif %else %bcond_with static_libs %bcond_without openssl %bcond_without ext2fs %endif - -%define somajor 13 -%define libname libarchive%{somajor} - Name: libarchive Version: 3.3.3 Release: 0 Summary: Utility and C library to create and read several different streaming archive formats License: BSD-2-Clause Group: Productivity/Archiving/Compression -Url: http://www.libarchive.org/ +URL: http://www.libarchive.org/ Source0: http://www.libarchive.org/downloads/libarchive-%{version}.tar.gz Source1: baselibs.conf -BuildRoot: %{_tmppath}/%{name}-%{version}-build +Patch0: CVE-2018-1000877.patch +Patch1: CVE-2018-1000878.patch +Patch2: CVE-2018-1000879.patch +Patch3: CVE-2018-1000880.patch BuildRequires: libacl-devel BuildRequires: libbz2-devel +BuildRequires: libtool +BuildRequires: libxml2-devel +BuildRequires: pkgconfig +BuildRequires: xz-devel +BuildRequires: zlib-devel %if %{with ext2fs} BuildRequires: libext2fs-devel %endif %if %{with openssl} BuildRequires: libopenssl-devel %endif -BuildRequires: libtool -BuildRequires: libxml2-devel -BuildRequires: pkg-config -BuildRequires: xz-devel -BuildRequires: zlib-devel %description Libarchive is a programming library that can create and read several @@ -68,9 +69,9 @@ and 6. This package contains the bsdtar cmdline utility. %package -n bsdtar -Requires: %{libname} >= %{version} Summary: Utility to read several different streaming archive formats Group: Productivity/Archiving/Compression +Requires: %{libname} >= %{version} %description -n bsdtar This package contains the bsdtar cmdline utility. @@ -133,10 +134,10 @@ I/O. It should be very easy to add new formats, new compression methods, or new ways of reading/writing archives. %package -n libarchive-devel -Requires: %{libname} = %{version} -Requires: glibc-devel Summary: Development files for libarchive Group: Development/Libraries/C and C++ +Requires: %{libname} = %{version} +Requires: glibc-devel %description -n libarchive-devel Libarchive is a programming library that can create and read several @@ -150,15 +151,19 @@ and 6. This package contains the development files. %package static-devel -Requires: %{name}-devel = %{version} Summary: Static library for libarchive Group: Development/Libraries/C and C++ +Requires: %{name}-devel = %{version} %description static-devel Static library for libarchive %prep %setup -q +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 %build %if !0%{?skip_autoreconf} @@ -184,16 +189,14 @@ make check || make check || make check %install %make_install -find %{buildroot} -name '*.la' -type f -delete -print +find %{buildroot} -type f -name "*.la" -delete -print rm "%{buildroot}%{_mandir}/man5/"{tar,cpio,mtree}.5* sed -i -e '/Libs.private/d' %{buildroot}%{_libdir}/pkgconfig/libarchive.pc %post -n %{libname} -p /sbin/ldconfig - %postun -n %{libname} -p /sbin/ldconfig %files -n bsdtar -%defattr(-,root,root) %{_bindir}/bsdcat %{_bindir}/bsdcpio %{_bindir}/bsdtar @@ -201,12 +204,11 @@ sed -i -e '/Libs.private/d' %{buildroot}%{_libdir}/pkgconfig/libarchive.pc %{_mandir}/man5/* %files -n %{libname} -%defattr(-,root,root) -%doc COPYING NEWS +%license COPYING +%doc NEWS %{_libdir}/libarchive.so.* %files -n libarchive-devel -%defattr(-,root,root) %doc examples/ %{_mandir}/man3/* %{_libdir}/libarchive.so @@ -215,7 +217,6 @@ sed -i -e '/Libs.private/d' %{buildroot}%{_libdir}/pkgconfig/libarchive.pc %if %{with static_libs} %files static-devel -%defattr(-,root,root) %{_libdir}/%{name}.a %endif