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 <locale.h>
+
+
+/*
+ * 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<BYB:6Y55`T`!\L>
+MD5>>))%7GB215W5X"P`!!/8!```$%````.W=06K#,!`%T&E)P8LL?*2XC@N%
+M)#5QO>AM<K0<+2=0:!OBP>@9WDJ6!%\6$K/Q6T3LAX]N/GQ'Z9G&KA^*K1'S
+M.`[GOIM*[TP_Q_>O0[G_:3X.Y\^^V/X2<<GT&IM=$]OK?[71_LJ],3;1+*(T
+M_U)99\T+````````````````````````````````````````L`:E?]*S#FVT
+MJY:='SPB>_]DR\X?`("_R:X_U"Y[_:F;;Q``ZN+L!P"H3W;]$_5G`&!9V?</
+M````X/FRZP_9LO,'@`S9YR^0P_Z'NF7?/P``````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+MJ%L3VVM-LO,&8/UN4$L'"!<='%^U`0``H``$`%!+`0(4`Q0`"``(`*=Y]4@7
+M'1Q?M0$``*``!``(`"````````````"D@0````!C:&%R+F)I;E54#0`'RQZ1
+M5YXDD5>>))%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 ***
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to