Date: Mon, 18 Jan 2016 23:51:28 +0000 (UTC) From: Jason Unovitch <junovitch@FreeBSD.org> To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r406624 - in head/archivers/libarchive: . files Message-ID: <201601182351.u0INpSXg055111@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: junovitch Date: Mon Jan 18 23:51:27 2016 New Revision: 406624 URL: https://svnweb.freebsd.org/changeset/ports/406624 Log: archivers/libarchive: apply patches for multiple security vulnerablities - Add patch for denial of service via unspecified vectors [1] - Add patch for directory traveral via absolute paths [2] - Add patch for crash/infinite loop on malformed CPIO archives (base r282932) [3] PR: 200176 [3] Reported by: Sevan Janiyan <venture37@geeklan.co.uk> Approved by: maintainer timeout (glewis, 8 months) Obtained from: https://github.com/libarchive/libarchive Commits 2253154 [1], 5935715 [2], 3865cf2, e6c9668, 24f5de6 [3] Security: CVE-2013-0211 [1] Security: CVE-2015-2304 [2] Security: https://vuxml.FreeBSD.org/freebsd/7c63775e-be31-11e5-b5fe-002590263bf5.html MFH: 2016Q1 Added: head/archivers/libarchive/files/ head/archivers/libarchive/files/patch-CVE-2013-0211 (contents, props changed) head/archivers/libarchive/files/patch-CVE-2015-2304 (contents, props changed) head/archivers/libarchive/files/patch-cpio1-3865cf2 (contents, props changed) head/archivers/libarchive/files/patch-cpio2-e6c9668 (contents, props changed) head/archivers/libarchive/files/patch-cpio3-24f5de6 (contents, props changed) Modified: head/archivers/libarchive/Makefile Modified: head/archivers/libarchive/Makefile ============================================================================== --- head/archivers/libarchive/Makefile Mon Jan 18 23:50:10 2016 (r406623) +++ head/archivers/libarchive/Makefile Mon Jan 18 23:51:27 2016 (r406624) @@ -2,7 +2,7 @@ PORTNAME= libarchive PORTVERSION= 3.1.2 -PORTREVISION= 4 +PORTREVISION= 5 PORTEPOCH= 1 CATEGORIES= archivers MASTER_SITES= http://libarchive.org/downloads/ Added: head/archivers/libarchive/files/patch-CVE-2013-0211 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/archivers/libarchive/files/patch-CVE-2013-0211 Mon Jan 18 23:51:27 2016 (r406624) @@ -0,0 +1,26 @@ +commit 22531545514043e04633e1c015c7540b9de9dbe4 +Author: Tim Kientzle <kientzle@acm.org> +Date: Fri Mar 22 23:48:41 2013 -0700 + + Limit write requests to at most INT_MAX. + This prevents a certain common programming error (passing -1 to write) + from leading to other problems deeper in the library. + +diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c +index eede5e0..be85621 100644 +--- libarchive/archive_write.c ++++ libarchive/archive_write.c +@@ -673,8 +673,13 @@ static ssize_t + _archive_write_data(struct archive *_a, const void *buff, size_t s) + { + struct archive_write *a = (struct archive_write *)_a; ++ const size_t max_write = INT_MAX; ++ + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data"); ++ /* In particular, this catches attempts to pass negative values. */ ++ if (s > max_write) ++ s = max_write; + archive_clear_error(&a->archive); + return ((a->format_write_data)(a, buff, s)); + } Added: head/archivers/libarchive/files/patch-CVE-2015-2304 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/archivers/libarchive/files/patch-CVE-2015-2304 Mon Jan 18 23:51:27 2016 (r406624) @@ -0,0 +1,136 @@ +commit 59357157706d47c365b2227739e17daba3607526 +Author: Alessandro Ghedini <alessandro@ghedini.me> +Date: Sun Mar 1 12:07:45 2015 +0100 + + Add ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS option + + This fixes a directory traversal in the cpio tool. + +diff --git a/cpio/bsdcpio.1 b/cpio/bsdcpio.1 +index f966aa0..e52546e 100644 +--- cpio/bsdcpio.1 ++++ cpio/bsdcpio.1 +@@ -156,7 +156,8 @@ See above for description. + .It Fl Fl insecure + (i and p mode only) + Disable security checks during extraction or copying. +-This allows extraction via symbolic links and path names containing ++This allows extraction via symbolic links, absolute paths, ++and path names containing + .Sq .. + in the name. + .It Fl J , Fl Fl xz +diff --git a/cpio/cpio.c b/cpio/cpio.c +index 0acde11..b267e9b 100644 +--- cpio/cpio.c ++++ cpio/cpio.c +@@ -171,6 +171,7 @@ main(int argc, char *argv[]) + cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS; + cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT; ++ cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; + cpio->extract_flags |= ARCHIVE_EXTRACT_PERM; + cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; + cpio->extract_flags |= ARCHIVE_EXTRACT_ACL; +@@ -256,6 +257,7 @@ main(int argc, char *argv[]) + case OPTION_INSECURE: + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS; + cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT; ++ cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; + break; + case 'L': /* GNU cpio */ + cpio->option_follow_links = 1; +diff --git a/libarchive/archive.h b/libarchive/archive.h +index 1f0fc38..ef635ac 100644 +--- libarchive/archive.h ++++ libarchive/archive.h +@@ -649,6 +649,8 @@ __LA_DECL int archive_read_set_passphrase_callback(struct archive *, + /* Default: Do not use HFS+ compression if it was not compressed. */ + /* This has no effect except on Mac OS v10.6 or later. */ + #define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000) ++/* Default: Do not reject entries with absolute paths */ ++#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000) + + __LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, + int flags); +diff --git a/libarchive/archive_write_disk.3 b/libarchive/archive_write_disk.3 +index fa925cc..a2e7afa 100644 +--- libarchive/archive_write_disk.3 ++++ libarchive/archive_write_disk.3 +@@ -177,6 +177,9 @@ The default is to not refuse such paths. + Note that paths ending in + .Pa .. + always cause an error, regardless of this flag. ++.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS ++Refuse to extract an absolute path. ++The default is to not refuse such paths. + .It Cm ARCHIVE_EXTRACT_SPARSE + Scan data for blocks of NUL bytes and try to recreate them with holes. + This results in sparse files, independent of whether the archive format +diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c +index ab3bdac..c1290eb 100644 +--- libarchive/archive_write_disk_posix.c ++++ libarchive/archive_write_disk_posix.c +@@ -2509,8 +2509,9 @@ cleanup_pathname_win(struct archive_write_disk *a) + /* + * Canonicalize the pathname. In particular, this strips duplicate + * '/' characters, '.' elements, and trailing '/'. It also raises an +- * error for an empty path, a trailing '..' or (if _SECURE_NODOTDOT is +- * set) any '..' in the path. ++ * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is ++ * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS ++ * is set) if the path is absolute. + */ + static int + cleanup_pathname(struct archive_write_disk *a) +@@ -2529,8 +2530,15 @@ cleanup_pathname(struct archive_write_disk *a) + cleanup_pathname_win(a); + #endif + /* Skip leading '/'. */ +- if (*src == '/') ++ if (*src == '/') { ++ if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, ++ "Path is absolute"); ++ return (ARCHIVE_FAILED); ++ } ++ + separator = *src++; ++ } + + /* Scan the pathname one element at a time. */ + for (;;) { +diff --git a/libarchive/test/test_write_disk_secure.c b/libarchive/test/test_write_disk_secure.c +index 31c5bfd..2c94206 100644 +--- libarchive/test/test_write_disk_secure.c ++++ libarchive/test/test_write_disk_secure.c +@@ -178,6 +178,29 @@ DEFINE_TEST(test_write_disk_secure) + assert(S_ISDIR(st.st_mode)); + archive_entry_free(ae); + ++ /* ++ * Without security checks, we should be able to ++ * extract an absolute path. ++ */ ++ assert((ae = archive_entry_new()) != NULL); ++ archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); ++ archive_entry_set_mode(ae, S_IFREG | 0777); ++ assert(0 == archive_write_header(a, ae)); ++ assert(0 == archive_write_finish_entry(a)); ++ assertFileExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); ++ assert(0 == unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp")); ++ ++ /* But with security checks enabled, this should fail. */ ++ assert(archive_entry_clear(ae) != NULL); ++ archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); ++ archive_entry_set_mode(ae, S_IFREG | 0777); ++ archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS); ++ failure("Extracting an absolute path should fail here."); ++ assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); ++ archive_entry_free(ae); ++ assert(0 == archive_write_finish_entry(a)); ++ assertFileNotExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"); ++ + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Test the entries on disk. */ Added: head/archivers/libarchive/files/patch-cpio1-3865cf2 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/archivers/libarchive/files/patch-cpio1-3865cf2 Mon Jan 18 23:51:27 2016 (r406624) @@ -0,0 +1,53 @@ +commit 3865cf2bcb0eebc1baef28a7841b1cadae6e0f7c +Author: Tim Kientzle <kientzle@acm.org> +Date: Fri Jan 30 23:54:19 2015 -0800 + + Issue 394: Segfault when reading malformed old-style cpio archives + + Root cause here was an implicit cast that resulted in + reading very large file sizes as negative numbers. + +diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c +index 0b69689..e7b3d0c 100644 +--- libarchive/archive_read_support_format_cpio.c ++++ libarchive/archive_read_support_format_cpio.c +@@ -198,7 +198,7 @@ static int archive_read_format_cpio_read_data(struct archive_read *, + 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 @@ static int header_afiol(struct archive_read *, struct cpio *, + 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); + +@@ -946,17 +946,17 @@ archive_read_format_cpio_cleanup(struct archive_read *a) + 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])); + } + + /* Added: head/archivers/libarchive/files/patch-cpio2-e6c9668 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/archivers/libarchive/files/patch-cpio2-e6c9668 Mon Jan 18 23:51:27 2016 (r406624) @@ -0,0 +1,23 @@ +commit e6c9668f3202215ddb71617b41c19b6f05acf008 +Author: Tim Kientzle <kientzle@acm.org> +Date: Fri Jan 30 23:57:03 2015 -0800 + + Add a check to archive_read_filter_consume to reject any + attempts to move the file pointer by a negative amount. + + Note: Either this or commit 3865cf2 provides a fix for + Issue 394. + +diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c +index 8f71a8b..d649e9a 100644 +--- libarchive/archive_read.c ++++ libarchive/archive_read.c +@@ -1471,6 +1471,8 @@ __archive_read_filter_consume(struct archive_read_filter * filter, + { + int64_t skipped; + ++ if (request < 0) ++ return ARCHIVE_FATAL; + if (request == 0) + return 0; + Added: head/archivers/libarchive/files/patch-cpio3-24f5de6 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/archivers/libarchive/files/patch-cpio3-24f5de6 Mon Jan 18 23:51:27 2016 (r406624) @@ -0,0 +1,40 @@ +commit 24f5de6560f31a67bfdf5ddec367e70ecfa9e440 +Author: Tim Kientzle <kientzle@acm.org> +Date: Fri Feb 6 22:07:16 2015 -0800 + + Set a proper error message if we hit end-of-file when + trying to read a cpio header. + + Suggested by Issue #395, although the actual problem there + seems to have been the same as Issue #394. + +diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c +index e7b3d0c..c2ca85b 100644 +--- libarchive/archive_read_support_format_cpio.c ++++ libarchive/archive_read_support_format_cpio.c +@@ -866,8 +866,11 @@ header_bin_le(struct archive_read *a, struct cpio *cpio, + + /* Read fixed-size portion of header. */ + h = __archive_read_ahead(a, bin_header_size, NULL); +- if (h == NULL) ++ if (h == NULL) { ++ archive_set_error(&a->archive, 0, ++ "End of file trying to read next cpio header"); + return (ARCHIVE_FATAL); ++ } + + /* Parse out binary fields. */ + header = (const unsigned char *)h; +@@ -902,8 +905,11 @@ header_bin_be(struct archive_read *a, struct cpio *cpio, + + /* Read fixed-size portion of header. */ + h = __archive_read_ahead(a, bin_header_size, NULL); +- if (h == NULL) ++ if (h == NULL) { ++ archive_set_error(&a->archive, 0, ++ "End of file trying to read next cpio header"); + return (ARCHIVE_FATAL); ++ } + + /* Parse out binary fields. */ + header = (const unsigned char *)h;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601182351.u0INpSXg055111>