...
 
Commits (13)
libarchive (3.1.2-11+deb8u2) UNRELEASED; urgency=high
* Targeting jessie-security
* Non-maintainer upload by the Security Team.
[ Petter Reinholdtsen ]
* CVE-2015-8915: Added Issue-502+503-CVE-2015-8915.patch based
on issue502.patch from Ubuntu. Fixes implicit cast in
libarchive/archive_read_support_format_cpio.c, rejecting
attempts to move the file pointer by a negative amount in
libarchive/archive_read.c to avoid denial of service via malformed
cpio archive.
* CVE-2015-8930: Added debian/patches/Issue-522-Fix-CVE-2015-8930.patch
to make sure ISO 9660 file systems with a directory loop do not
smash the stack.
* CVE-2015-8931: Added Issue-539-Fix-CVE-2015-8931.patch removing
possible integer overflow issue when opening any mtree file.
* CVE-2015-8932: Added Issue-547-Fix-CVE-2015-8932.patch to fix
problems with compress bidder.
* CVE-2015-8934: Added Issue-521-Fix-CVE-2015-8934.patch from
upstream to properly check reading from lzss decompression buffer.
* CVE-2016-4300: Added debian/patches/Issue-718-Fix-CVE-2016-4300.patch
avoiding integer overflow in 7-zip parsing.
* CVE-2016-4302: Added Issue-719-Fix-CVE-2016-4302.patch from upstream
to reject invalid RAR file with zero dictionary size.
* CVE-2016-4809: Added debian/patches/Issue-705-Fix-CVE-2016-4809.patch
rejecting cpio symlinks > 1MiB.
* CVE-2016-5844: Added Issue-717-Fix-CVE-2016-5844.patch fixing integer
overflow when computing location of volume descriptor for iso9660 file
systems.
-- Petter Reinholdtsen <pere@debian.org> Mon, 27 Jun 2016 22:32:38 +0200
libarchive (3.1.2-11+deb8u1) jessie-security; urgency=high
* Non-maintainer upload by the Security Team.
* CVE-2016-1541: heap-based buffer overflow due to improper input
validation (Closes: #823893)
-- Salvatore Bonaccorso <carnil@debian.org> Tue, 10 May 2016 07:00:10 +0200
libarchive (3.1.2-11) unstable; urgency=medium
* Add d/p/Add-ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS-option.patch
......
[DEFAULT]
debian-branch = debian-jessie
upstream-branch = upstream
pristine-tar = True
sign-tags = True
Description: fix denial of service via malformed cpio archive
CVE-2015-8915
Origin: upstream, https://github.com/libarchive/libarchive/commit/3865cf2bcb0eebc1baef28a7841b1cadae6e0f7c
Origin: upstream, https://github.com/libarchive/libarchive/commit/e6c9668f3202215ddb71617b41c19b6f05acf008
Bug: https://github.com/libarchive/libarchive/issues/502
Bug: https://github.com/libarchive/libarchive/issues/503
Debian-Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=784213
Index: libarchive-3.1.2/libarchive/archive_read.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read.c 2013-02-07 22:24:42.000000000 -0500
+++ libarchive-3.1.2/libarchive/archive_read.c 2016-05-13 09:24:42.063300882 -0400
@@ -1394,6 +1394,8 @@
{
int64_t skipped;
+ if (request < 0)
+ return ARCHIVE_FATAL;
if (request == 0)
return 0;
Index: libarchive-3.1.2/libarchive/archive_read_support_format_cpio.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read_support_format_cpio.c 2013-01-13 20:43:45.000000000 -0500
+++ libarchive-3.1.2/libarchive/archive_read_support_format_cpio.c 2016-05-13 09:24:39.343272889 -0400
@@ -198,7 +198,7 @@
static int archive_read_format_cpio_read_header(struct archive_read *,
struct archive_entry *);
static int archive_read_format_cpio_skip(struct archive_read *);
-static int be4(const unsigned char *);
+static int64_t be4(const unsigned char *);
static int find_odc_header(struct archive_read *);
static int find_newc_header(struct archive_read *);
static int header_bin_be(struct archive_read *, struct cpio *,
@@ -213,7 +213,7 @@
struct archive_entry *, size_t *, size_t *);
static int is_octal(const char *, size_t);
static int is_hex(const char *, size_t);
-static int le4(const unsigned char *);
+static int64_t le4(const unsigned char *);
static int record_hardlink(struct archive_read *a,
struct cpio *cpio, struct archive_entry *entry);
@@ -944,17 +944,17 @@
return (ARCHIVE_OK);
}
-static int
+static int64_t
le4(const unsigned char *p)
{
- return ((p[0]<<16) + (p[1]<<24) + (p[2]<<0) + (p[3]<<8));
+ return ((p[0] << 16) + (((int64_t)p[1]) << 24) + (p[2] << 0) + (p[3] << 8));
}
-static int
+static int64_t
be4(const unsigned char *p)
{
- return ((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + (p[3]));
+ return ((((int64_t)p[0]) << 24) + (p[1] << 16) + (p[2] << 8) + (p[3]));
}
/*
Description: Solve CVE-2015-8934
commit 603454ec03040c29bd051fcc749e3c1433c11a8e
Author: Tim Kientzle <kientzle@acm.org>
Date: Sun Jun 19 15:31:46 2016 -0700
Issue 521: Properly check reading from lzss decompression buffer
Prior code could be tricked into trying to copy data
from beyond the end of the internal decompression buffer.
Thanks to Hanno Böck for his ongoing fuzz-testing work with libarchive.
Index: libarchive/Makefile.am
===================================================================
--- libarchive.orig/Makefile.am 2016-06-27 23:25:47.831554070 +0200
+++ libarchive/Makefile.am 2016-06-27 23:27:24.644368778 +0200
@@ -411,6 +411,7 @@
libarchive/test/test_read_format_lha_filename.c \
libarchive/test/test_read_format_mtree.c \
libarchive/test/test_read_format_pax_bz2.c \
+ libarchive/test/test_read_format_rar_invalid1.c \
libarchive/test/test_read_format_rar.c \
libarchive/test/test_read_format_raw.c \
libarchive/test/test_read_format_tar.c \
Index: libarchive/libarchive/archive_read_support_format_rar.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_format_rar.c 2016-06-27 23:25:47.831554070 +0200
+++ libarchive/libarchive/archive_read_support_format_rar.c 2016-06-27 23:25:47.831554070 +0200
@@ -2798,11 +2798,10 @@
}
windowoffs = lzss_offset_for_position(&rar->lzss, startpos);
- if(windowoffs + length <= lzss_size(&rar->lzss))
+ if(windowoffs + length <= lzss_size(&rar->lzss)) {
memcpy(&rar->unp_buffer[rar->unp_offset], &rar->lzss.window[windowoffs],
length);
- else
- {
+ } else if (length <= lzss_size(&rar->lzss)) {
firstpart = lzss_size(&rar->lzss) - windowoffs;
if (firstpart < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -2814,9 +2813,14 @@
&rar->lzss.window[windowoffs], firstpart);
memcpy(&rar->unp_buffer[rar->unp_offset + firstpart],
&rar->lzss.window[0], length - firstpart);
- } else
+ } else {
memcpy(&rar->unp_buffer[rar->unp_offset],
&rar->lzss.window[windowoffs], length);
+ }
+ } else {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Bad RAR file data");
+ return (ARCHIVE_FATAL);
}
rar->unp_offset += length;
if (rar->unp_offset >= rar->unp_buffer_size)
diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt
index d2eb2c2..a001fb3 100644
--- a/libarchive/test/CMakeLists.txt
+++ b/libarchive/test/CMakeLists.txt
@@ -127,6 +127,7 @@ IF(ENABLE_TEST)
test_read_format_mtree.c
test_read_format_pax_bz2.c
test_read_format_rar.c
+ test_read_format_rar_invalid1.c
test_read_format_raw.c
test_read_format_tar.c
test_read_format_tar_empty_filename.c
Index: libarchive/libarchive/test/test_read_format_rar_invalid1.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libarchive/libarchive/test/test_read_format_rar_invalid1.c 2016-06-27 23:25:47.831554070 +0200
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2003-2016 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_read_format_rar_invalid1)
+{
+ const char *refname = "test_read_format_rar_invalid1.rar";
+ struct archive *a;
+ struct archive_entry *ae;
+ char *buff[100];
+
+ extract_reference_file(refname);
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, 99));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
Index: libarchive/libarchive/test/test_read_format_rar_invalid1.rar.uu
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libarchive/libarchive/test/test_read_format_rar_invalid1.rar.uu 2016-06-27 23:25:47.831554070 +0200
@@ -0,0 +1,5 @@
+begin 644 test_read_format_rar_invalid1.rar
+M4F%R(1H'`,^0<P``#0````````"9SG0@D"8`#`````,````#+7,'\(^>B$4=
+2,P0`I($``'1E<W0`P/\````)
+`
+end
Description:
Two upstream commits merged into one.
commit 39fc59391b7cf2a007bffce280c1e3e66674258f
Author: Tim Kientzle <kientzle@acm.org>
Date: Sat Apr 11 22:44:12 2015 -0700
Issue #522: Dir loop in malformed ISO causes segfault
Github Issue #522 revealed that we could blow the stack
when recursing to assemble ISO paths. I saw this happen
at 130,000 dir levels. This patch addresses this by limiting
the directory recursion to 1,000 elements.
TODO: It would be even better to track and detect the dir loop
directly.
commit 01cfbca4fdae1492a8a09c001b61bbca46f869f2
Author: Tim Kientzle <kientzle@acm.org>
Date: Sat Apr 11 22:57:58 2015 -0700
Github Issue #522: Detect cycles in the ISO directory tree
Index: libarchive/libarchive/archive_read_support_format_iso9660.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_format_iso9660.c 2016-06-28 22:38:08.509715140 +0200
+++ libarchive/libarchive/archive_read_support_format_iso9660.c 2016-06-28 22:38:08.505715109 +0200
@@ -387,7 +387,7 @@
static int archive_read_format_iso9660_read_data_skip(struct archive_read *);
static int archive_read_format_iso9660_read_header(struct archive_read *,
struct archive_entry *);
-static const char *build_pathname(struct archive_string *, struct file_info *);
+static const char *build_pathname(struct archive_string *, struct file_info *, int);
static int build_pathname_utf16be(unsigned char *, size_t, size_t *,
struct file_info *);
#if DEBUG
@@ -1223,6 +1223,7 @@
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Pathname is too long");
+ return (ARCHIVE_FATAL);
}
r = archive_entry_copy_pathname_l(entry,
@@ -1245,9 +1246,16 @@
rd_r = ARCHIVE_WARN;
}
} else {
- archive_string_empty(&iso9660->pathname);
- archive_entry_set_pathname(entry,
- build_pathname(&iso9660->pathname, file));
+ const char *path = build_pathname(&iso9660->pathname, file, 0);
+ if (path == NULL) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Pathname is too long");
+ return (ARCHIVE_FATAL);
+ } else {
+ archive_string_empty(&iso9660->pathname);
+ archive_entry_set_pathname(entry, path);
+ }
}
iso9660->entry_bytes_remaining = file->size;
@@ -1742,12 +1750,12 @@
const unsigned char *isodirrec)
{
struct iso9660 *iso9660;
- struct file_info *file;
+ struct file_info *file, *filep;
size_t name_len;
const unsigned char *rr_start, *rr_end;
const unsigned char *p;
size_t dr_len;
- uint64_t fsize;
+ uint64_t fsize, offset;
int32_t location;
int flags;
@@ -1791,6 +1799,16 @@
return (NULL);
}
+ /* Sanity check that this entry does not create a cycle. */
+ offset = iso9660->logical_block_size * (uint64_t)location;
+ for (filep = parent; filep != NULL; filep = filep->parent) {
+ if (filep->offset == offset) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Directory structure contains loop");
+ return (NULL);
+ }
+ }
+
/* Create a new file entry and copy data from the ISO dir record. */
file = (struct file_info *)calloc(1, sizeof(*file));
if (file == NULL) {
@@ -1799,7 +1817,7 @@
return (NULL);
}
file->parent = parent;
- file->offset = iso9660->logical_block_size * (uint64_t)location;
+ file->offset = offset;
file->size = fsize;
file->mtime = isodate7(isodirrec + DR_date_offset);
file->ctime = file->atime = file->mtime;
@@ -3164,10 +3182,17 @@
}
static const char *
-build_pathname(struct archive_string *as, struct file_info *file)
+build_pathname(struct archive_string *as, struct file_info *file, int depth)
{
+ // Plain ISO9660 only allows 8 dir levels; if we get
+ // to 1000, then something is very, very wrong.
+ if (depth > 1000) {
+ return NULL;
+ }
if (file->parent != NULL && archive_strlen(&file->parent->name) > 0) {
- build_pathname(as, file->parent);
+ if (build_pathname(as, file->parent, depth + 1) == NULL) {
+ return NULL;
+ }
archive_strcat(as, "/");
}
if (archive_strlen(&file->name) == 0)
Description:
Merged two commits from upstream related to the same issue. The ns=0
change was not mentioned in the commit messages, but seem sensible
enough to keep.
commit b31744df71084a8734f97199e42418f55d08c6c5
Author: Tim Kientzle <kientzle@acm.org>
Date: Sat May 16 12:16:28 2015 -0700
Issue #539: Try a different way to compute max/min time_t values.
commit c0c52e9aaafb0860c4151c5374372051e9354301
Author: Tim Kientzle <kientzle@gmail.com>
Date: Thu Oct 22 21:43:07 2015 -0700
Don't try to be smart about probing the min/max tim_t values.
Just assume that a signed time_t is really a 64-bit or 32-bit integer.
Index: libarchive/libarchive/archive_read_support_format_mtree.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_format_mtree.c 2016-06-29 11:57:34.022187010 +0200
+++ libarchive/libarchive/archive_read_support_format_mtree.c 2016-06-29 11:57:34.018186975 +0200
@@ -137,16 +137,22 @@
#if defined(TIME_T_MAX)
return TIME_T_MAX;
#else
- static time_t t;
- time_t a;
- if (t == 0) {
- a = 1;
- while (a > t) {
- t = a;
- a = a * 2 + 1;
+ /* ISO C allows time_t to be a floating-point type,
+ but POSIX requires an integer type. The following
+ should work on any system that follows the POSIX
+ conventions. */
+ if (((time_t)0) < ((time_t)-1)) {
+ /* Time_t is unsigned */
+ return (~(time_t)0);
+ } else {
+ /* Time_t is signed. */
+ /* Assume it's the same as int64_t or int32_t */
+ if (sizeof(time_t) == sizeof(int64_t)) {
+ return (time_t)INT64_MAX;
+ } else {
+ return (time_t)INT32_MAX;
}
}
- return t;
#endif
}
@@ -156,20 +162,17 @@
#if defined(TIME_T_MIN)
return TIME_T_MIN;
#else
- /* 't' will hold the minimum value, which will be zero (if
- * time_t is unsigned) or -2^n (if time_t is signed). */
- static int computed;
- static time_t t;
- time_t a;
- if (computed == 0) {
- a = (time_t)-1;
- while (a < t) {
- t = a;
- a = a * 2;
- }
- computed = 1;
+ if (((time_t)0) < ((time_t)-1)) {
+ /* Time_t is unsigned */
+ return (time_t)0;
+ } else {
+ /* Time_t is signed. */
+ if (sizeof(time_t) == sizeof(int64_t)) {
+ return (time_t)INT64_MIN;
+ } else {
+ return (time_t)INT32_MIN;
+ }
}
- return t;
#endif
}
@@ -1455,7 +1458,7 @@
int64_t m;
int64_t my_time_t_max = get_time_t_max();
int64_t my_time_t_min = get_time_t_min();
- long ns;
+ long ns = 0;
*parsed_kws |= MTREE_HAS_MTIME;
m = mtree_atol10(&val);
Description:
The fix is in commit f0b1dbbc325a2d922015eee402b72edd422cb9ea, while
activating the test code is in part of
618618c8a6be453f79e0bdbdeab6e1dd8bf429b3 and
55ce98e829eda3a4356c2be64a778d8740c2cf6c. This patch include all of
the former and the relevant part of the last two.
commit f0b1dbbc325a2d922015eee402b72edd422cb9ea
Author: Tim Kientzle <kientzle@acm.org>
Date: Sat Aug 8 21:47:43 2015 -0700
Issue 547: problems with compress bidder
The code previously was not very careful about verifying the
compression parameters. This led to cases where it failed to
reject invalid compressed data at the beginning. The invalid
left shift was one symptom of this.
The code is now more careful: It verifies that the compression
parameter byte exists and verifies that the maximum code size
is <= 16 bits.
This also includes some new tests to verify that truncated or
otherwise invalid compressed data is rejected.
commit 618618c8a6be453f79e0bdbdeab6e1dd8bf429b3
Author: Graham Percival <gperciva@tarsnap.com>
Date: Wed Sep 2 19:09:06 2015 -0700
add missing tests to automake
commit 55ce98e829eda3a4356c2be64a778d8740c2cf6c
Author: Tim Kientzle <kientzle@gmail.com>
Date: Thu Nov 19 21:09:08 2015 -0800
Add in two missing test cases.
Index: libarchive/libarchive/archive_read_support_filter_compress.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_filter_compress.c 2016-06-29 12:30:59.292332397 +0200
+++ libarchive/libarchive/archive_read_support_filter_compress.c 2016-06-29 12:30:59.288332360 +0200
@@ -185,19 +185,22 @@
(void)self; /* UNUSED */
- buffer = __archive_read_filter_ahead(filter, 2, &avail);
+ /* Shortest valid compress file is 3 bytes. */
+ buffer = __archive_read_filter_ahead(filter, 3, &avail);
if (buffer == NULL)
return (0);
bits_checked = 0;
+ /* First two bytes are the magic value */
if (buffer[0] != 0x1F || buffer[1] != 0x9D)
return (0);
- bits_checked += 16;
-
- /*
- * TODO: Verify more.
- */
+ /* Third byte holds compression parameters. */
+ if (buffer[2] & 0x20) /* Reserved bit, must be zero. */
+ return (0);
+ if (buffer[2] & 0x40) /* Reserved bit, must be zero. */
+ return (0);
+ bits_checked += 18;
return (bits_checked);
}
@@ -239,7 +242,13 @@
(void)getbits(self, 8); /* Skip first signature byte. */
(void)getbits(self, 8); /* Skip second signature byte. */
+ /* Get compression parameters. */
code = getbits(self, 8);
+ if ((code & 0x1f) > 16) {
+ archive_set_error(&self->archive->archive, -1,
+ "Invalid compressed data");
+ return (ARCHIVE_FATAL);
+ }
state->maxcode_bits = code & 0x1f;
state->maxcode = (1 << state->maxcode_bits);
state->use_reset_code = code & 0x80;
Index: libarchive/libarchive/test/test_read_filter_compress.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libarchive/libarchive/test/test_read_filter_compress.c 2016-06-29 12:30:59.288332360 +0200
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 2003-2008 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+DEFINE_TEST(test_read_filter_compress_truncated)
+{
+ const char data[] = {0x1f, 0x9d};
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_FATAL,
+ archive_read_open_memory(a, data, sizeof(data)));
+
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+
+DEFINE_TEST(test_read_filter_compress_empty2)
+{
+ const char data[] = {0x1f, 0x9d, 0x10};
+ struct archive *a;
+ struct archive_entry *ae;
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_memory(a, data, sizeof(data)));
+
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify that the format detection worked. */
+ assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS);
+ assertEqualString(archive_filter_name(a, 0), "compress (.Z)");
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_EMPTY);
+
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+
+DEFINE_TEST(test_read_filter_compress_invalid)
+{
+ const char data[] = {0x1f, 0x9d, 0x11};
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_FATAL,
+ archive_read_open_memory(a, data, sizeof(data)));
+
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
Index: libarchive/libarchive/test/CMakeLists.txt
===================================================================
--- libarchive.orig/libarchive/test/CMakeLists.txt 2016-06-29 12:30:59.292332397 +0200
+++ libarchive/libarchive/test/CMakeLists.txt 2016-06-29 12:30:59.288332360 +0200
@@ -79,6 +79,7 @@
test_read_disk_entry_from_file.c
test_read_extract.c
test_read_file_nonexistent.c
+ test_read_filter_compress.c
test_read_filter_grzip.c
test_read_filter_lrzip.c
test_read_filter_lzop.c
diff --git a/Makefile.am b/Makefile.am
index 3fa2d22..01bd97f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -364,6 +364,7 @@ libarchive_test_SOURCES= \
libarchive/test/test_read_disk_entry_from_file.c \
libarchive/test/test_read_extract.c \
libarchive/test/test_read_file_nonexistent.c \
+ libarchive/test/test_read_filter_compress.c \
libarchive/test/test_read_filter_grzip.c \
libarchive/test/test_read_filter_lrzip.c \
libarchive/test/test_read_filter_lzop.c \
From d0331e8e5b05b475f20b1f3101fe1ad772d7e7e7 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <kientzle@acm.org>
Date: Sun, 24 Apr 2016 17:13:45 -0700
Subject: [PATCH] Issue #656: Fix CVE-2016-1541, VU#862384
When reading OS X metadata entries in Zip archives that were stored
without compression, libarchive would use the uncompressed entry size
to allocate a buffer but would use the compressed entry size to limit
the amount of data copied into that buffer. Since the compressed
and uncompressed sizes are provided by data in the archive itself,
an attacker could manipulate these values to write data beyond
the end of the allocated buffer.
This fix provides three new checks to guard against such
manipulation and to make libarchive generally more robust when
handling this type of entry:
1. If an OS X metadata entry is stored without compression,
abort the entire archive if the compressed and uncompressed
data sizes do not match.
2. When sanity-checking the size of an OS X metadata entry,
abort this entry if either the compressed or uncompressed
size is larger than 4MB.
3. When copying data into the allocated buffer, check the copy
size against both the compressed entry size and uncompressed
entry size.
---
libarchive/archive_read_support_format_zip.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/libarchive/archive_read_support_format_zip.c
+++ b/libarchive/archive_read_support_format_zip.c
@@ -560,6 +560,11 @@ zip_read_mac_metadata(struct archive_rea
switch(rsrc->compression) {
case 0: /* No compression. */
+ if (rsrc->uncompressed_size != rsrc->compressed_size) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed OS X metadata entry: inconsistent size");
+ return (ARCHIVE_FATAL);
+ }
#ifdef HAVE_ZLIB_H
case 8: /* Deflate compression. */
#endif
@@ -580,6 +585,12 @@ zip_read_mac_metadata(struct archive_rea
(intmax_t)rsrc->uncompressed_size);
return (ARCHIVE_WARN);
}
+ if (rsrc->compressed_size > (4 * 1024 * 1024)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Mac metadata is too large: %jd > 4M bytes",
+ (intmax_t)rsrc->compressed_size);
+ return (ARCHIVE_WARN);
+ }
metadata = malloc((size_t)rsrc->uncompressed_size);
if (metadata == NULL) {
@@ -619,6 +630,8 @@ zip_read_mac_metadata(struct archive_rea
bytes_avail = remaining_bytes;
switch(rsrc->compression) {
case 0: /* No compression. */
+ if ((size_t)bytes_avail > metadata_bytes)
+ bytes_avail = metadata_bytes;
memcpy(mp, p, bytes_avail);
bytes_used = (size_t)bytes_avail;
metadata_bytes -= bytes_used;
commit fd7e0c02e272913a0a8b6d492c7260dfca0b1408
Author: Tim Kientzle <kientzle@acm.org>
Date: Sat May 14 12:37:37 2016 -0700
Reject cpio symlinks that exceed 1MB
Index: libarchive/libarchive/archive_read_support_format_cpio.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_format_cpio.c 2016-06-28 16:05:06.815182299 +0200
+++ libarchive/libarchive/archive_read_support_format_cpio.c 2016-06-28 16:05:06.811182274 +0200
@@ -399,6 +399,11 @@
/* If this is a symlink, read the link contents. */
if (archive_entry_filetype(entry) == AE_IFLNK) {
+ if (cpio->entry_bytes_remaining > 1024 * 1024) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Rejecting malformed cpio archive: symlink contents exceed 1 megabyte");
+ return (ARCHIVE_FATAL);
+ }
h = __archive_read_ahead(a,
(size_t)cpio->entry_bytes_remaining, NULL);
if (h == NULL)
commit 3ad08e01b4d253c66ae56414886089684155af22
Author: Tim Kientzle <kientzle@acm.org>
Date: Sun Jun 19 14:34:37 2016 -0700
Issue 717: Fix integer overflow when computing location of volume descriptor
The multiplication here defaulted to 'int' but calculations
of file positions should always use int64_t. A simple cast
suffices to fix this since the base location is always 32 bits
for ISO, so multiplying by the sector size will never overflow
a 64-bit integer.
Index: libarchive/libarchive/archive_read_support_format_iso9660.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_format_iso9660.c 2016-06-28 16:12:14.158146733 +0200
+++ libarchive/libarchive/archive_read_support_format_iso9660.c 2016-06-28 16:12:14.154146705 +0200
@@ -1089,7 +1089,7 @@
/* This condition is unlikely; by way of caution. */
vd = &(iso9660->joliet);
- skipsize = LOGICAL_BLOCK_SIZE * vd->location;
+ skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location;
skipsize = __archive_read_consume(a, skipsize);
if (skipsize < 0)
return ((int)skipsize);
@@ -1127,7 +1127,7 @@
&& iso9660->seenJoliet) {
/* Switch reading data from primary to joliet. */
vd = &(iso9660->joliet);
- skipsize = LOGICAL_BLOCK_SIZE * vd->location;
+ skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location;
skipsize -= iso9660->current_position;
skipsize = __archive_read_consume(a, skipsize);
if (skipsize < 0)
Description:
This patch was fetched from upstream, and the UMAX_ENTRY constant
introduced after version 3.1.2 was replaced by the 1000000 constant
used in the 3.1.2 code base.
commit e79ef306afe332faf22e9b442a2c6b59cb175573
Author: Tim Kientzle <kientzle@acm.org>
Date: Sun Jun 19 14:14:09 2016 -0700
Issue #718: Fix TALOS-CAN-152
If a 7-Zip archive declares a rediculously large number of substreams,
it can overflow an internal counter, leading a subsequent memory
allocation to be too small for the substream data.
Thanks to the Open Source and Threat Intelligence project at Cisco
for reporting this issue.
Index: libarchive/libarchive/archive_read_support_format_7zip.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_format_7zip.c 2016-06-28 10:40:28.745037206 +0200
+++ libarchive/libarchive/archive_read_support_format_7zip.c 2016-06-28 10:40:28.745037206 +0200
@@ -2045,6 +2045,9 @@
return (-1);
if (1000000 < f[i].numUnpackStreams)
return (-1);
+ if (unpack_streams > SIZE_MAX - 1000000) {
+ return (-1);
+ }
unpack_streams += (size_t)f[i].numUnpackStreams;
}
if ((p = header_bytes(a, 1)) == NULL)
commit 05caadc7eedbef471ac9610809ba683f0c698700
Author: Tim Kientzle <kientzle@acm.org>
Date: Sun Jun 19 14:21:42 2016 -0700
Issue 719: Fix for TALOS-CAN-154
A RAR file with an invalid zero dictionary size was not being
rejected, leading to a zero-sized allocation for the dictionary
storage which was then overwritten during the dictionary initialization.
Thanks to the Open Source and Threat Intelligence project at Cisco for
reporting this.
Index: libarchive/libarchive/archive_read_support_format_rar.c
===================================================================
--- libarchive.orig/libarchive/archive_read_support_format_rar.c 2016-06-28 10:25:37.580471607 +0200
+++ libarchive/libarchive/archive_read_support_format_rar.c 2016-06-28 10:25:37.580471607 +0200
@@ -2049,6 +2049,12 @@
rar->range_dec.Stream = &rar->bytein;
__archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
+ if (rar->dictionary_size == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid zero dictionary size");
+ return (ARCHIVE_FATAL);
+ }
+
if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
rar->dictionary_size, &g_szalloc))
{
......@@ -8,3 +8,13 @@ Fix-test_archive_write_add_filter_by_name_lrzip-test.patch
fix-CVE-2013-0211.patch
Do-not-overwrite-file-size-if-the-local-file-header-.patch
Add-ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS-option.patch
Issue-656-Fix-CVE-2016-1541-VU-862384.patch
Issue-502+503-CVE-2015-8915.patch
Issue-521-Fix-CVE-2015-8934.patch
Issue-522-Fix-CVE-2015-8930.patch
Issue-539-Fix-CVE-2015-8931.patch
Issue-547-Fix-CVE-2015-8932.patch
Issue-718-Fix-CVE-2016-4300.patch
Issue-719-Fix-CVE-2016-4302.patch
Issue-705-Fix-CVE-2016-4809.patch
Issue-717-Fix-CVE-2016-5844.patch