From owner-svn-src-stable-10@freebsd.org Thu Sep 1 12:01:28 2016 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 40BD7BC92D9; Thu, 1 Sep 2016 12:01:28 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E71521AF; Thu, 1 Sep 2016 12:01:27 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u81C1RJJ048866; Thu, 1 Sep 2016 12:01:27 GMT (envelope-from mm@FreeBSD.org) Received: (from mm@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u81C1OLc048836; Thu, 1 Sep 2016 12:01:24 GMT (envelope-from mm@FreeBSD.org) Message-Id: <201609011201.u81C1OLc048836@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mm set sender to mm@FreeBSD.org using -f From: Martin Matuska Date: Thu, 1 Sep 2016 12:01:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r305192 - in stable/10: contrib/libarchive/cat/test contrib/libarchive/cpio contrib/libarchive/cpio/test contrib/libarchive/libarchive contrib/libarchive/libarchive/test contrib/libarch... X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 01 Sep 2016 12:01:28 -0000 Author: mm Date: Thu Sep 1 12:01:23 2016 New Revision: 305192 URL: https://svnweb.freebsd.org/changeset/base/305192 Log: MFC r304075,r304989: Sync libarchive with vendor including security fixes Vendor issues fixed: Issue #731: Reject tar entries >= INT64_MAX Issue #744: Very long pathnames evade symlink checks Issue #748: libarchive can compress, but cannot decompress zip some files PR #750: ustar: fix out of bounds read on empty string ("") filename PR #755: fix use of acl_get_flagset_np() on FreeBSD Issue #767: Buffer overflow printing a filename Issue #770: Zip read: be more careful about extra_length MFC r304874: Temporarily disable two libarchive tests that have not yet been fixed by vendor. Tests will be re-enabled after a fix has been merged. Added: stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c - copied unchanged from r304075, head/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.zip.uu - copied unchanged from r304075, head/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.zip.uu stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure744.c - copied unchanged from r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure744.c stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure745.c - copied unchanged from r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure745.c stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure746.c - copied unchanged from r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure746.c Modified: stable/10/contrib/libarchive/cat/test/test_version.c stable/10/contrib/libarchive/cpio/cmdline.c stable/10/contrib/libarchive/cpio/test/test_option_version.c stable/10/contrib/libarchive/libarchive/archive_match.c stable/10/contrib/libarchive/libarchive/archive_ppmd7_private.h stable/10/contrib/libarchive/libarchive/archive_read_add_passphrase.c stable/10/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c stable/10/contrib/libarchive/libarchive/archive_read_disk_posix.c stable/10/contrib/libarchive/libarchive/archive_read_private.h stable/10/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_lha.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_tar.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_warc.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_zip.c stable/10/contrib/libarchive/libarchive/archive_util.c stable/10/contrib/libarchive/libarchive/archive_write_disk_acl.c stable/10/contrib/libarchive/libarchive/archive_write_disk_posix.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_ustar.c stable/10/contrib/libarchive/libarchive/test/main.c stable/10/contrib/libarchive/libarchive/test/test.h stable/10/contrib/libarchive/libarchive/test/test_archive_string_conversion.c stable/10/contrib/libarchive/libarchive/test/test_fuzz.c stable/10/contrib/libarchive/libarchive/test/test_read_format_rar.c stable/10/contrib/libarchive/tar/cmdline.c stable/10/contrib/libarchive/tar/test/test_version.c stable/10/contrib/libarchive/tar/util.c stable/10/lib/libarchive/tests/Makefile Directory Properties: stable/10/ (props changed) Modified: stable/10/contrib/libarchive/cat/test/test_version.c ============================================================================== --- stable/10/contrib/libarchive/cat/test/test_version.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/cat/test/test_version.c Thu Sep 1 12:01:23 2016 (r305192) @@ -83,7 +83,7 @@ DEFINE_TEST(test_version) if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd') ++q; /* Skip arbitrary third-party version numbers. */ - while (s > 0 && (*q == ' ' || *q == '/' || *q == '.' || isalnum(*q))) { + while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || isalnum(*q))) { ++q; --s; } Modified: stable/10/contrib/libarchive/cpio/cmdline.c ============================================================================== --- stable/10/contrib/libarchive/cpio/cmdline.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/cpio/cmdline.c Thu Sep 1 12:01:23 2016 (r305192) @@ -63,6 +63,7 @@ static const struct option { } cpio_longopts[] = { { "b64encode", 0, OPTION_B64ENCODE }, { "create", 0, 'o' }, + { "dereference", 0, 'L' }, { "dot", 0, 'V' }, { "extract", 0, 'i' }, { "file", 1, 'F' }, Modified: stable/10/contrib/libarchive/cpio/test/test_option_version.c ============================================================================== --- stable/10/contrib/libarchive/cpio/test/test_option_version.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/cpio/test/test_option_version.c Thu Sep 1 12:01:23 2016 (r305192) @@ -75,7 +75,7 @@ verify(const char *p, size_t s) if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd') ++q; /* Skip arbitrary third-party version numbers. */ - while (s > 0 && (*q == ' ' || *q == '/' || *q == '.' || isalnum(*q))) { + while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || isalnum(*q))) { ++q; --s; } Modified: stable/10/contrib/libarchive/libarchive/archive_match.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_match.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_match.c Thu Sep 1 12:01:23 2016 (r305192) @@ -655,7 +655,7 @@ add_pattern_from_file(struct archive_mat } } - /* If something error happend, report it immediately. */ + /* If an error occurred, report it immediately. */ if (r < ARCHIVE_OK) { archive_copy_error(&(a->archive), ar); archive_read_free(ar); Modified: stable/10/contrib/libarchive/libarchive/archive_ppmd7_private.h ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_ppmd7_private.h Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_ppmd7_private.h Thu Sep 1 12:01:23 2016 (r305192) @@ -19,7 +19,7 @@ If you need the compatibility with origi #define PPMD7_MAX_ORDER 64 #define PPMD7_MIN_MEM_SIZE (1 << 11) -#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) +#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3) struct CPpmd7_Context_; Modified: stable/10/contrib/libarchive/libarchive/archive_read_add_passphrase.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_add_passphrase.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_add_passphrase.c Thu Sep 1 12:01:23 2016 (r305192) @@ -125,7 +125,7 @@ void __archive_read_reset_passphrase(struct archive_read *a) { - a->passphrases.candiate = -1; + a->passphrases.candidate = -1; } /* @@ -137,31 +137,31 @@ __archive_read_next_passphrase(struct ar struct archive_read_passphrase *p; const char *passphrase; - if (a->passphrases.candiate < 0) { + if (a->passphrases.candidate < 0) { /* Count out how many passphrases we have. */ int cnt = 0; for (p = a->passphrases.first; p != NULL; p = p->next) cnt++; - a->passphrases.candiate = cnt; + a->passphrases.candidate = cnt; p = a->passphrases.first; - } else if (a->passphrases.candiate > 1) { + } else if (a->passphrases.candidate > 1) { /* Rotate a passphrase list. */ - a->passphrases.candiate--; + a->passphrases.candidate--; p = remove_passphrases_from_head(a); add_passphrase_to_tail(a, p); - /* Pick a new passphrase candiate up. */ + /* Pick a new passphrase candidate up. */ p = a->passphrases.first; - } else if (a->passphrases.candiate == 1) { - /* This case is that all cadiates failed to decryption. */ - a->passphrases.candiate = 0; + } else if (a->passphrases.candidate == 1) { + /* This case is that all candidates failed to decrypt. */ + a->passphrases.candidate = 0; if (a->passphrases.first->next != NULL) { /* Rotate a passphrase list. */ p = remove_passphrases_from_head(a); add_passphrase_to_tail(a, p); } p = NULL; - } else /* There is no passphrase candaite. */ + } else /* There is no passphrase candidate. */ p = NULL; if (p != NULL) @@ -177,7 +177,7 @@ __archive_read_next_passphrase(struct ar if (p == NULL) return (NULL); insert_passphrase_to_head(a, p); - a->passphrases.candiate = 1; + a->passphrases.candidate = 1; } } else passphrase = NULL; Modified: stable/10/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c Thu Sep 1 12:01:23 2016 (r305192) @@ -641,13 +641,16 @@ translate_acl(struct archive_read_disk * * Libarchive stores "flag" (NFSv4 inheritance bits) * in the ae_perm bitmap. */ - acl_get_flagset_np(acl_entry, &acl_flagset); - for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - if (acl_get_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit)) - ae_perm |= acl_inherit_map[i].archive_inherit; - - } + // XXX acl_get_flagset_np on FreeBSD returns EINVAL for + // non-NFSv4 ACLs + r = acl_get_flagset_np(acl_entry, &acl_flagset); + if (r == 0) { + for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { + if (acl_get_flag_np(acl_flagset, + acl_inherit_map[i].platform_inherit)) + ae_perm |= acl_inherit_map[i].archive_inherit; + } + } #endif acl_get_permset(acl_entry, &acl_permset); Modified: stable/10/contrib/libarchive/libarchive/archive_read_disk_posix.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_disk_posix.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_disk_posix.c Thu Sep 1 12:01:23 2016 (r305192) @@ -938,7 +938,7 @@ next_entry(struct archive_read_disk *a, r = archive_match_path_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1041,7 +1041,7 @@ next_entry(struct archive_read_disk *a, r = archive_match_time_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1067,7 +1067,7 @@ next_entry(struct archive_read_disk *a, r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { Modified: stable/10/contrib/libarchive/libarchive/archive_read_private.h ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_private.h Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_private.h Thu Sep 1 12:01:23 2016 (r305192) @@ -221,7 +221,7 @@ struct archive_read { struct { struct archive_read_passphrase *first; struct archive_read_passphrase **last; - int candiate; + int candidate; archive_passphrase_callback *callback; void *client_data; } passphrases; Modified: stable/10/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c Thu Sep 1 12:01:23 2016 (r305192) @@ -595,7 +595,7 @@ lz4_filter_read_data_block(struct archiv #endif } - /* Check if an error happend in decompression process. */ + /* Check if an error occurred in the decompression process. */ if (uncompressed_size < 0) { archive_set_error(&(self->archive->archive), ARCHIVE_ERRNO_MISC, "lz4 decompression failed"); Modified: stable/10/contrib/libarchive/libarchive/archive_read_support_format_lha.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_support_format_lha.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_support_format_lha.c Thu Sep 1 12:01:23 2016 (r305192) @@ -1715,8 +1715,11 @@ lha_crc16(uint16_t crc, const void *pp, #undef bswap16 #if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */ # define bswap16(x) _byteswap_ushort(x) -#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \ - || defined(__clang__) +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) +/* GCC 4.8 and later has __builtin_bswap16() */ +# define bswap16(x) __builtin_bswap16(x) +#elif defined(__clang__) +/* All clang versions have __builtin_bswap16() */ # define bswap16(x) __builtin_bswap16(x) #else # define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8)) Modified: stable/10/contrib/libarchive/libarchive/archive_read_support_format_tar.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_support_format_tar.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_support_format_tar.c Thu Sep 1 12:01:23 2016 (r305192) @@ -1128,8 +1128,15 @@ header_common(struct archive_read *a, st if (tar->entry_bytes_remaining < 0) { tar->entry_bytes_remaining = 0; archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Tar entry has negative size?"); - err = ARCHIVE_WARN; + "Tar entry has negative size"); + return (ARCHIVE_FATAL); + } + if (tar->entry_bytes_remaining == INT64_MAX) { + /* Note: tar_atol returns INT64_MAX on overflow */ + tar->entry_bytes_remaining = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Tar entry size overflow"); + return (ARCHIVE_FATAL); } tar->realsize = tar->entry_bytes_remaining; archive_entry_set_size(entry, tar->entry_bytes_remaining); Modified: stable/10/contrib/libarchive/libarchive/archive_read_support_format_warc.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_support_format_warc.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_support_format_warc.c Thu Sep 1 12:01:23 2016 (r305192) @@ -318,7 +318,7 @@ start_over: } memcpy(w->pool.str, fnam.str, fnam.len); w->pool.str[fnam.len] = '\0'; - /* let noone else know about the pool, it's a secret, shhh */ + /* let no one else know about the pool, it's a secret, shhh */ fnam.str = w->pool.str; /* snarf mtime or deduce from rtime Modified: stable/10/contrib/libarchive/libarchive/archive_read_support_format_zip.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_read_support_format_zip.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_read_support_format_zip.c Thu Sep 1 12:01:23 2016 (r305192) @@ -418,18 +418,30 @@ zip_time(const char *p) * id1+size1+data1 + id2+size2+data2 ... * triplets. id and size are 2 bytes each. */ -static void -process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) +static int +process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry) { unsigned offset = 0; - while (offset < extra_length - 4) { + if (extra_length == 0) { + return ARCHIVE_OK; + } + + if (extra_length < 4) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length); + return ARCHIVE_FAILED; + } + while (offset <= extra_length - 4) { unsigned short headerid = archive_le16dec(p + offset); unsigned short datasize = archive_le16dec(p + offset + 2); offset += 4; if (offset + datasize > extra_length) { - break; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Extra data overflow: Need %d bytes but only found %d bytes", + (int)datasize, (int)(extra_length - offset)); + return ARCHIVE_FAILED; } #ifdef DEBUG fprintf(stderr, "Header id 0x%04x, length %d\n", @@ -715,13 +727,13 @@ process_extra(const char *p, size_t extr } offset += datasize; } -#ifdef DEBUG - if (offset != extra_length) - { - fprintf(stderr, - "Extra data field contents do not match reported size!\n"); + if (offset != extra_length) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed extra data: Consumed %d bytes of %d bytes", + (int)offset, (int)extra_length); + return ARCHIVE_FAILED; } -#endif + return ARCHIVE_OK; } /* @@ -840,7 +852,9 @@ zip_read_local_file_header(struct archiv return (ARCHIVE_FATAL); } - process_extra(h, extra_length, zip_entry); + if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) { + return ARCHIVE_FATAL; + } __archive_read_consume(a, extra_length); /* Work around a bug in Info-Zip: When reading from a pipe, it @@ -1293,7 +1307,7 @@ zip_read_data_deflate(struct archive_rea && bytes_avail > zip->entry_bytes_remaining) { bytes_avail = (ssize_t)zip->entry_bytes_remaining; } - if (bytes_avail <= 0) { + if (bytes_avail < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file body"); return (ARCHIVE_FATAL); @@ -2691,7 +2705,9 @@ slurp_central_directory(struct archive_r "Truncated ZIP file header"); return ARCHIVE_FATAL; } - process_extra(p + filename_length, extra_length, zip_entry); + if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) { + return ARCHIVE_FATAL; + } /* * Mac resource fork files are stored under the Modified: stable/10/contrib/libarchive/libarchive/archive_util.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_util.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_util.c Thu Sep 1 12:01:23 2016 (r305192) @@ -580,7 +580,7 @@ void __archive_ensure_cloexec_flag(int fd) { #if defined(_WIN32) && !defined(__CYGWIN__) - (void)fd; /* UNSED */ + (void)fd; /* UNUSED */ #else int flags; Modified: stable/10/contrib/libarchive/libarchive/archive_write_disk_acl.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_write_disk_acl.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_write_disk_acl.c Thu Sep 1 12:01:23 2016 (r305192) @@ -138,6 +138,7 @@ set_acl(struct archive *a, int fd, const acl_permset_t acl_permset; #ifdef ACL_TYPE_NFS4 acl_flagset_t acl_flagset; + int r; #endif int ret; int ae_type, ae_permset, ae_tag, ae_id; @@ -223,12 +224,16 @@ set_acl(struct archive *a, int fd, const } #ifdef ACL_TYPE_NFS4 - acl_get_flagset_np(acl_entry, &acl_flagset); - acl_clear_flags_np(acl_flagset); - for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - if (ae_permset & acl_inherit_map[i].archive_inherit) - acl_add_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit); + // XXX acl_get_flagset_np on FreeBSD returns EINVAL for + // non-NFSv4 ACLs + r = acl_get_flagset_np(acl_entry, &acl_flagset); + if (r == 0) { + acl_clear_flags_np(acl_flagset); + for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { + if (ae_permset & acl_inherit_map[i].archive_inherit) + acl_add_flag_np(acl_flagset, + acl_inherit_map[i].platform_inherit); + } } #endif } Modified: stable/10/contrib/libarchive/libarchive/archive_write_disk_posix.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_write_disk_posix.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_write_disk_posix.c Thu Sep 1 12:01:23 2016 (r305192) @@ -1796,7 +1796,7 @@ edit_deep_directories(struct archive_wri char *tail = a->name; /* If path is short, avoid the open() below. */ - if (strlen(tail) <= PATH_MAX) + if (strlen(tail) < PATH_MAX) return; /* Try to record our starting dir. */ @@ -1806,7 +1806,7 @@ edit_deep_directories(struct archive_wri return; /* As long as the path is too long... */ - while (strlen(tail) > PATH_MAX) { + while (strlen(tail) >= PATH_MAX) { /* Locate a dir prefix shorter than PATH_MAX. */ tail += PATH_MAX - 8; while (tail > a->name && *tail != '/') @@ -2401,8 +2401,18 @@ check_symlinks(struct archive_write_disk r = lstat(a->name, &st); if (r != 0) { /* We've hit a dir that doesn't exist; stop now. */ - if (errno == ENOENT) + if (errno == ENOENT) { break; + } else { + /* Note: This effectively disables deep directory + * support when security checks are enabled. + * Otherwise, very long pathnames that trigger + * an error here could evade the sandbox. + * TODO: We could do better, but it would probably + * require merging the symlink checks with the + * deep-directory editing. */ + return (ARCHIVE_FAILED); + } } else if (S_ISLNK(st.st_mode)) { if (c == '\0') { /* Modified: stable/10/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c Thu Sep 1 12:01:23 2016 (r305192) @@ -436,7 +436,7 @@ struct iso_option { * Type : string * Default: Auto detect * : We check a size of boot image; - * : If ths size is just 1.22M/1.44M/2.88M, + * : If the size is just 1.22M/1.44M/2.88M, * : we assume boot_type is 'fd'; * : otherwise boot_type is 'no-emulation'. * COMPAT : Modified: stable/10/contrib/libarchive/libarchive/archive_write_set_format_ustar.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_write_set_format_ustar.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/archive_write_set_format_ustar.c Thu Sep 1 12:01:23 2016 (r305192) @@ -307,7 +307,7 @@ archive_write_ustar_header(struct archiv * case getting WCS failed. On POSIX, this is a * normal operation. */ - if (p != NULL && p[strlen(p) - 1] != '/') { + if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { struct archive_string as; archive_string_init(&as); Modified: stable/10/contrib/libarchive/libarchive/test/main.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/test/main.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/test/main.c Thu Sep 1 12:01:23 2016 (r305192) @@ -1440,6 +1440,31 @@ assertion_file_size(const char *file, in return (0); } +/* Verify mode of 'pathname'. */ +int +assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode) +{ + int mode; + int r; + + assertion_count(file, line); +#if defined(_WIN32) && !defined(__CYGWIN__) + failure_start(file, line, "assertFileMode not yet implemented for Windows"); +#else + { + struct stat st; + r = lstat(pathname, &st); + mode = (int)(st.st_mode & 0777); + } + if (r == 0 && mode == expected_mode) + return (1); + failure_start(file, line, "File %s has mode %o, expected %o", + pathname, mode, expected_mode); +#endif + failure_finish(NULL); + return (0); +} + /* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */ int assertion_is_dir(const char *file, int line, const char *pathname, int mode) Modified: stable/10/contrib/libarchive/libarchive/test/test.h ============================================================================== --- stable/10/contrib/libarchive/libarchive/test/test.h Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/test/test.h Thu Sep 1 12:01:23 2016 (r305192) @@ -182,6 +182,8 @@ assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks) #define assertFileSize(pathname, size) \ assertion_file_size(__FILE__, __LINE__, pathname, size) +#define assertFileMode(pathname, mode) \ + assertion_file_mode(__FILE__, __LINE__, pathname, mode) #define assertTextFileContents(text, pathname) \ assertion_text_file_contents(__FILE__, __LINE__, text, pathname) #define assertFileContainsLinesAnyOrder(pathname, lines) \ @@ -246,6 +248,7 @@ int assertion_file_mtime_recent(const ch int assertion_file_nlinks(const char *, int, const char *, int); int assertion_file_not_exists(const char *, int, const char *); int assertion_file_size(const char *, int, const char *, long); +int assertion_file_mode(const char *, int, const char *, int); int assertion_is_dir(const char *, int, const char *, int); int assertion_is_hardlink(const char *, int, const char *, const char *); int assertion_is_not_hardlink(const char *, int, const char *, const char *); Modified: stable/10/contrib/libarchive/libarchive/test/test_archive_string_conversion.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/test/test_archive_string_conversion.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/test/test_archive_string_conversion.c Thu Sep 1 12:01:23 2016 (r305192) @@ -800,8 +800,8 @@ DEFINE_TEST(test_archive_string_conversi assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assert((fp = fopen(testdata, "w")) != NULL); while ((size = archive_read_data(a, buff, 512)) > 0) - fwrite(buff, 1, size, fp); - fclose(fp); + assertEqualInt(size, fwrite(buff, 1, size, fp)); + assertEqualInt(0, fclose(fp)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); test_archive_string_normalization_nfc(testdata); Modified: stable/10/contrib/libarchive/libarchive/test/test_fuzz.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/test/test_fuzz.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/test/test_fuzz.c Thu Sep 1 12:01:23 2016 (r305192) @@ -110,13 +110,17 @@ test_fuzz(const struct files *filesets) for (i = 0; filesets[n].names[i] != NULL; ++i) { tmp = slurpfile(&size, filesets[n].names[i]); - rawimage = (char *)realloc(rawimage, oldsize + size); + char *newraw = (char *)realloc(rawimage, oldsize + size); + if (!assert(newraw != NULL)) + { + free(rawimage); + continue; + } + rawimage = newraw; memcpy(rawimage + oldsize, tmp, size); oldsize += size; size = oldsize; free(tmp); - if (!assert(rawimage != NULL)) - continue; } } if (size == 0) Modified: stable/10/contrib/libarchive/libarchive/test/test_read_format_rar.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/test/test_read_format_rar.c Thu Sep 1 10:26:06 2016 (r305191) +++ stable/10/contrib/libarchive/libarchive/test/test_read_format_rar.c Thu Sep 1 12:01:23 2016 (r305192) @@ -3603,7 +3603,7 @@ DEFINE_TEST(test_read_format_rar_multivo assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); /* - * Eigth header. + * Eighth header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("testdir/testsymlink6", archive_entry_pathname(ae)); Copied: stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c (from r304075, head/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c Thu Sep 1 12:01:23 2016 (r305192, copy of r304075, head/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.c) @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 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"); + +#include + + +/* + * Github Issue 748 reported problems with end-of-entry handling + * with highly-compressible data. This resulted in the end of the + * data being truncated (extracted as zero bytes). + */ + +/* + * Extract the specific test archive that was used to diagnose + * Issue 748: + */ +DEFINE_TEST(test_read_format_zip_high_compression) +{ + const char *refname = "test_read_format_zip_high_compression.zip"; + char *p; + size_t archive_size; + struct archive *a; + struct archive_entry *entry; + + const void *pv; + size_t s; + int64_t o; + + extract_reference_file(refname); + p = slurpfile(&archive_size, refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, archive_size, 16 * 1024)); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &entry)); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(262144, s); + assertEqualInt(0, o); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(160, s); + assertEqualInt(262144, o); + + assertEqualInt(ARCHIVE_EOF, archive_read_data_block(a, &pv, &s, &o)); + + assertEqualInt(ARCHIVE_OK, archive_free(a)); + free(p); +} + +/* + * Synthesize a lot of varying inputs that are highly compressible. + */ +DEFINE_TEST(test_read_format_zip_high_compression2) +{ + const size_t body_size = 1024 * 1024; + const size_t buff_size = 2 * 1024 * 1024; + char *body, *body_read, *buff; + int n; + + assert((body = malloc(body_size)) != NULL); + assert((body_read = malloc(body_size)) != NULL); + assert((buff = malloc(buff_size)) != NULL); + + /* Highly-compressible data: all bytes 255, except for a + * single 1 byte. + * The body is always 256k + 6 bytes long (the internal deflation + * buffer is exactly 256k). + */ + + for(n = 1024; n < (int)body_size; n += 1024) { + struct archive *a; + struct archive_entry *entry; + size_t used = 0; + const void *pv; + size_t s; + int64_t o; + + memset(body, 255, body_size); + body[n] = 1; + + /* Write an archive with a single entry of n bytes. */ + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, buff_size, &used)); + + entry = archive_entry_new2(a); + archive_entry_set_pathname(entry, "test"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 262150); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); + archive_entry_free(entry); + assertEqualInt(262150, archive_write_data(a, body, 262150)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Read back the entry and verify the contents. */ + 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, read_open_memory(a, buff, used, 17)); + assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &entry)); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(262144, s); + assertEqualInt(0, o); + + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &pv, &s, &o)); + assertEqualInt(6, s); + assertEqualInt(262144, o); + + assertEqualInt(ARCHIVE_EOF, archive_read_data_block(a, &pv, &s, &o)); + + assertEqualInt(ARCHIVE_OK, archive_free(a)); + } + + free(body); + free(body_read); + free(buff); +} Copied: stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.zip.uu (from r304075, head/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.zip.uu) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.zip.uu Thu Sep 1 12:01:23 2016 (r305192, copy of r304075, head/contrib/libarchive/libarchive/test/test_read_format_zip_high_compression.zip.uu) @@ -0,0 +1,18 @@ +begin 644 test_read_format_zip_high_compression.zip +M4$L#!!0`"``(`*=Y]4@``````````*``!``(`"``8VAA +MD5>>))%7GB215W5X"P`!!/8!```$%````.W=06K#,!`%T&E)P8LL?*2XC@N% +M)#5QO>AM@9WDJ6!%\6$K/Q6T3LAX]N/GQ'Z9G&KA^*K1'S +M.`[GOIM*[TP_Q_>O0[G_:3X.Y\^^V/X2<>))%7=7@+``$$]@$```04````4$L%!@`````!``$`5@````L"```` +!```` +` +end Copied: stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure744.c (from r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure744.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure744.c Thu Sep 1 12:01:23 2016 (r305192, copy of r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure744.c) @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2003-2007,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 UMASK 022 + +/* + * Github Issue #744 describes a bug in the sandboxing code that + * causes very long pathnames to not get checked for symlinks. + */ + +DEFINE_TEST(test_write_disk_secure744) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + size_t buff_size = 8192; + char *buff = malloc(buff_size); + char *p = buff; + int n = 0; + int t; + + assert(buff != NULL); + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + + while (p + 500 < buff + buff_size) { + memset(p, 'x', 100); + p += 100; + p[0] = '\0'; + + buff[0] = ((n / 1000) % 10) + '0'; + buff[1] = ((n / 100) % 10)+ '0'; + buff[2] = ((n / 10) % 10)+ '0'; + buff[3] = ((n / 1) % 10)+ '0'; + buff[4] = '_'; + ++n; + + /* Create a symlink pointing to the testworkdir */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, buff); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_copy_symlink(ae, testworkdir); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + *p++ = '/'; + sprintf(p, "target%d", n); + + /* Try to create a file through the symlink, should fail. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, buff); + archive_entry_set_mode(ae, S_IFDIR | 0777); + + t = archive_write_header(a, ae); + archive_entry_free(ae); + failure("Attempt to create target%d via %d-character symlink should have failed", n, (int)strlen(buff)); + if(!assertEqualInt(ARCHIVE_FAILED, t)) { + break; + } + } + archive_free(a); + free(buff); +#endif +} Copied: stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure745.c (from r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure745.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure745.c Thu Sep 1 12:01:23 2016 (r305192, copy of r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure745.c) @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2003-2007,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 UMASK 022 + +/* + * Github Issue #745 describes a bug in the sandboxing code that + * allows one to use a symlink to edit the permissions on a file or + * directory outside of the sandbox. + */ + +DEFINE_TEST(test_write_disk_secure745) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + + /* The target dir: The one we're going to try to change permission on */ + assertMakeDir("target", 0700); + + /* The sandbox dir we're going to run inside of. */ + assertMakeDir("sandbox", 0700); + assertChdir("sandbox"); + + /* Create a symlink pointing to the target directory */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "sym"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_copy_symlink(ae, "../target"); + assert(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Try to alter the target dir through the symlink; this should fail. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "sym"); + archive_entry_set_mode(ae, S_IFDIR | 0777); + assert(0 == archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Permission of target dir should not have changed. */ + assertFileMode("../target", 0700); +#endif +} Copied: stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure746.c (from r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure746.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure746.c Thu Sep 1 12:01:23 2016 (r305192, copy of r304075, head/contrib/libarchive/libarchive/test/test_write_disk_secure746.c) @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2003-2007,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 UMASK 022 + +/* + * Github Issue #746 describes a problem in which hardlink targets are + * not adequately checked and can be used to modify entries outside of + * the sandbox. + */ + +/* + * Verify that ARCHIVE_EXTRACT_SECURE_NODOTDOT disallows '..' in hardlink + * targets. + */ +DEFINE_TEST(test_write_disk_secure746a) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* The target directory we're going to try to affect. */ + assertMakeDir("target", 0700); + assertMakeFile("target/foo", 0700, "unmodified"); + + /* The sandbox dir we're going to work within. */ + assertMakeDir("sandbox", 0700); + assertChdir("sandbox"); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_NODOTDOT); + + /* Attempt to hardlink to the target directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "bar"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_size(ae, 8); + archive_entry_copy_hardlink(ae, "../target/foo"); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_FAILED, archive_write_data(a, "modified", 8)); + archive_entry_free(ae); + + /* Verify that target file contents are unchanged. */ + assertTextFileContents("unmodified", "../target/foo"); +#endif +} + +/* + * Verify that ARCHIVE_EXTRACT_SECURE_NOSYMLINK disallows symlinks in hardlink + * targets. + */ +DEFINE_TEST(test_write_disk_secure746b) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + skipping("archive_write_disk security checks not supported on Windows"); +#else + struct archive *a; + struct archive_entry *ae; + + /* Start with a known umask. */ + assertUmask(UMASK); + + /* The target directory we're going to try to affect. */ + assertMakeDir("target", 0700); + assertMakeFile("target/foo", 0700, "unmodified"); + + /* The sandbox dir we're going to work within. */ + assertMakeDir("sandbox", 0700); + assertChdir("sandbox"); + + /* Create an archive_write_disk object. */ + assert((a = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS); + + /* Create a symlink to the target directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "symlink"); + archive_entry_copy_symlink(ae, "../target"); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Attempt to hardlink to the target directory via the symlink. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "bar"); + archive_entry_set_mode(ae, S_IFREG | 0777); + archive_entry_set_size(ae, 8); + archive_entry_copy_hardlink(ae, "symlink/foo"); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + assertEqualInt(ARCHIVE_FAILED, archive_write_data(a, "modified", 8)); + archive_entry_free(ae); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***