svn commit: r306379 - in releng/11.0: contrib/libarchive contrib/libarchive/libarchive contrib/libarchive/libarchive/test lib/libarchive lib/libarchive/tests usr.bin/bsdiff/bspatch usr.sbin/portsna...

Ed Maste emaste at FreeBSD.org
Tue Sep 27 19:36:15 UTC 2016


Author: emaste
Date: Tue Sep 27 19:36:12 2016
New Revision: 306379
URL: https://svnweb.freebsd.org/changeset/base/306379

Log:
  Merge from stable/11 bspatch, portsnap, and libarchive fixes:
  
  === bspatch ===
  
  MFS r306213: bspatch Capsicumization, sanity checks, and other improvements
  
  r304691: bspatch: apply style(9)
  
  Make style changes (and trivial refactoring of open calls) now in order
  to reduce noise in diffs for future capsicum changes.
  
  r304807 (allanjude): Capsicumize bspatch
  
  Move all of the fopen() and open() calls to the top of main()
  
  Restrict each FD to least privilege (read/seek only, write only, etc)
  
  cap_enter(), and make all except the output FD read/seek only.
  
  r304821: bspatch: remove output file in the case of error
  
  r305486: bspatch: add sanity checks on sizes to avoid integer overflow
  
  Note that this introduces an explicit 2GB limit, but this was already
  implicit in variable and function argument types.
  
  This is based on the "non-cryptanalytic attacks against freebsd
  update components" anonymous gist. Further refinement is planned.
  
  r305737: bspatch: remove superfluous newlines from errx strings
  
  r305822: bspatch: use #define for header size instead of magic number
  
  r306026: bspatch: Remove backwards-compatibility sys/capability.h support
  
  bspatch previously included sys/capability.h or sys/capsicum.h based
  on __FreeBSD_version, as FreeBSD is the upstream for bsdiff and we may
  see this file incorporated into other third-party software.
  
  The Capsicum header is now installed as sys/capsicum.h in stable/10 and
  FreeBSD 10.3, so we can just use sys/capsicum.h and simplify the logic.
  
  With this change, bspatch is identical between head, stable/11 and releng/11.0.
  
  === portsnap ===
  
  MFS r305648 (delphij): MFC r305469:
  
  Ensure that we always open only files that is named by explicitly
  using shell redirections instead of having gzip(1) to decide what
  file to open.
  
  Issue reported in the "non-cryptanalytic attacks against freebsd
  update components" anonymous gist.
  
  === libarchive ===
  
  MFS r305754 (mm): MFC r305422:
  
  Sync libarchive with vendor
  
  Vendor issues fixed:
  PR #777: Multiple bugfixes for setup_acls()
  
  This includes a bugfix for a bug that caused ACLs not to be read properly
  for files and directories inside subdirectories and as a result not being
  stored or being incorrectly stored in tar archives.
  
  MFS r306321 (mm): MFC r305819:
  
  Sync libarchive with vendor including important security fixes.
  
  Issues fixed (FreeBSD):
  PR #778: ACL error handling
  Issue #745: Symlink check prefix optimization is too aggressive
  Issue #746: Hard links with data can evade sandboxing restrictions
  
  This update fixes the vulnerability #3 and vulnerability #4 as reported in
  "non-cryptanalytic attacks against FreeBSD update components".
  https://gist.github.com/anonymous/e48209b03f1dd9625a992717e7b89c4f
  
  Fix for vulnerability #2 has already been merged.
  
  Approved by:	re (gjb), so (glebius)

Added:
  releng/11.0/contrib/libarchive/README.md
     - copied unchanged from r305754, stable/11/contrib/libarchive/README.md
Deleted:
  releng/11.0/contrib/libarchive/README
Modified:
  releng/11.0/contrib/libarchive/libarchive/archive_acl.c
  releng/11.0/contrib/libarchive/libarchive/archive_platform.h
  releng/11.0/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
  releng/11.0/contrib/libarchive/libarchive/archive_read_disk_posix.c
  releng/11.0/contrib/libarchive/libarchive/archive_read_support_format_tar.c
  releng/11.0/contrib/libarchive/libarchive/archive_write_disk_acl.c
  releng/11.0/contrib/libarchive/libarchive/archive_write_disk_posix.c
  releng/11.0/contrib/libarchive/libarchive/test/test_acl_freebsd_posix1e.c
  releng/11.0/contrib/libarchive/libarchive/test/test_write_disk_secure745.c
  releng/11.0/contrib/libarchive/libarchive/test/test_write_disk_secure746.c
  releng/11.0/contrib/libarchive/libarchive/test/test_write_format_gnutar_filenames.c
  releng/11.0/lib/libarchive/config_freebsd.h
  releng/11.0/lib/libarchive/tests/Makefile
  releng/11.0/usr.bin/bsdiff/bspatch/bspatch.c
  releng/11.0/usr.sbin/portsnap/portsnap/portsnap.sh
Directory Properties:
  releng/11.0/   (props changed)

Copied: releng/11.0/contrib/libarchive/README.md (from r305754, stable/11/contrib/libarchive/README.md)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ releng/11.0/contrib/libarchive/README.md	Tue Sep 27 19:36:12 2016	(r306379, copy of r305754, stable/11/contrib/libarchive/README.md)
@@ -0,0 +1,222 @@
+# Welcome to libarchive!
+
+The libarchive project develops a portable, efficient C library that
+can read and write streaming archives in a variety of formats.  It
+also includes implementations of the common `tar`, `cpio`, and `zcat`
+command-line tools that use the libarchive library.
+
+## Questions?  Issues?
+
+* http://www.libarchive.org is the home for ongoing
+  libarchive development, including documentation,
+  and links to the libarchive mailing lists.
+* To report an issue, use the issue tracker at
+  https://github.com/libarchive/libarchive/issues
+* To submit an enhancement to libarchive, please
+  submit a pull request via GitHub: https://github.com/libarchive/libarchive/pulls
+
+## Contents of the Distribution
+
+This distribution bundle includes the following major components:
+
+* **libarchive**: a library for reading and writing streaming archives
+* **tar**: the 'bsdtar' program is a full-featured 'tar' implementation built on libarchive
+* **cpio**: the 'bsdcpio' program is a different interface to essentially the same functionality
+* **cat**: the 'bsdcat' program is a simple replacement tool for zcat, bzcat, xzcat, and such
+* **examples**: Some small example programs that you may find useful.
+* **examples/minitar**: a compact sample demonstrating use of libarchive.
+* **contrib**:  Various items sent to me by third parties; please contact the authors with any questions.
+
+The top-level directory contains the following information files:
+
+* **NEWS** - highlights of recent changes
+* **COPYING** - what you can do with this
+* **INSTALL** - installation instructions
+* **README** - this file
+* **CMakeLists.txt** - input for "cmake" build tool, see INSTALL
+* **configure** - configuration script, see INSTALL for details.  If your copy of the source lacks a `configure` script, you can try to construct it by running the script in `build/autogen.sh` (or use `cmake`).
+
+The following files in the top-level directory are used by the 'configure' script:
+* `Makefile.am`, `aclocal.m4`, `configure.ac` - used to build this distribution, only needed by maintainers
+* `Makefile.in`, `config.h.in` - templates used by configure script
+
+## Documentation
+
+In addition to the informational articles and documentation
+in the online [libarchive Wiki](https://github.com/libarchive/libarchive/wiki),
+the distribution also includes a number of manual pages:
+
+ * bsdtar.1 explains the use of the bsdtar program
+ * bsdcpio.1 explains the use of the bsdcpio program
+ * bsdcat.1 explains the use of the bsdcat program
+ * libarchive.3 gives an overview of the library as a whole
+ * archive_read.3, archive_write.3, archive_write_disk.3, and
+   archive_read_disk.3 provide detailed calling sequences for the read
+   and write APIs
+ * archive_entry.3 details the "struct archive_entry" utility class
+ * archive_internals.3 provides some insight into libarchive's
+   internal structure and operation.
+ * libarchive-formats.5 documents the file formats supported by the library
+ * cpio.5, mtree.5, and tar.5 provide detailed information about these
+   popular archive formats, including hard-to-find details about
+   modern cpio and tar variants.
+
+The manual pages above are provided in the 'doc' directory in
+a number of different formats.
+
+You should also read the copious comments in `archive.h` and the
+source code for the sample programs for more details.  Please let us
+know about any errors or omissions you find.
+
+## Supported Formats
+
+Currently, the library automatically detects and reads the following fomats:
+  * Old V7 tar archives
+  * POSIX ustar
+  * GNU tar format (including GNU long filenames, long link names, and sparse files)
+  * Solaris 9 extended tar format (including ACLs)
+  * POSIX pax interchange format
+  * POSIX octet-oriented cpio
+  * SVR4 ASCII cpio
+  * POSIX octet-oriented cpio
+  * Binary cpio (big-endian or little-endian)
+  * ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
+  * ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
+  * GNU and BSD 'ar' archives
+  * 'mtree' format
+  * 7-Zip archives
+  * Microsoft CAB format
+  * LHA and LZH archives
+  * RAR archives (with some limitations due to RAR's proprietary status)
+  * XAR archives
+
+The library also detects and handles any of the following before evaluating the archive:
+  * uuencoded files
+  * files with RPM wrapper
+  * gzip compression
+  * bzip2 compression
+  * compress/LZW compression
+  * lzma, lzip, and xz compression
+  * lz4 compression
+  * lzop compression
+
+The library can create archives in any of the following formats:
+  * POSIX ustar
+  * POSIX pax interchange format
+  * "restricted" pax format, which will create ustar archives except for
+    entries that require pax extensions (for long filenames, ACLs, etc).
+  * Old GNU tar format
+  * Old V7 tar format
+  * POSIX octet-oriented cpio
+  * SVR4 "newc" cpio
+  * shar archives
+  * ZIP archives (with uncompressed or "deflate" compressed entries)
+  * GNU and BSD 'ar' archives
+  * 'mtree' format
+  * ISO9660 format
+  * 7-Zip archives
+  * XAR archives
+
+When creating archives, the result can be filtered with any of the following:
+  * uuencode
+  * gzip compression
+  * bzip2 compression
+  * compress/LZW compression
+  * lzma, lzip, and xz compression
+  * lz4 compression
+  * lzop compression
+
+## Notes about the Library Design
+
+The following notes address many of the most common
+questions we are asked about libarchive:
+
+* This is a heavily stream-oriented system.  That means that
+  it is optimized to read or write the archive in a single
+  pass from beginning to end.  For example, this allows
+  libarchive to process archives too large to store on disk
+  by processing them on-the-fly as they are read from or
+  written to a network or tape drive.  This also makes
+  libarchive useful for tools that need to produce
+  archives on-the-fly (such as webservers that provide
+  archived contents of a users account).
+
+* In-place modification and random access to the contents
+  of an archive are not directly supported.  For some formats,
+  this is not an issue: For example, tar.gz archives are not
+  designed for random access.  In some other cases, libarchive
+  can re-open an archive and scan it from the beginning quickly
+  enough to provide the needed abilities even without true
+  random access.  Of course, some applications do require true
+  random access; those applications should consider alternatives
+  to libarchive.
+
+* The library is designed to be extended with new compression and
+  archive formats.  The only requirement is that the format be
+  readable or writable as a stream and that each archive entry be
+  independent.  There are articles on the libarchive Wiki explaining
+  how to extend libarchive.
+
+* On read, compression and format are always detected automatically.
+
+* The same API is used for all formats; in particular, it's very
+  easy for software using libarchive to transparently handle
+  any of libarchive's archiving formats.
+
+* Libarchive's automatic support for decompression can be used
+  without archiving by explicitly selecting the "raw" and "empty"
+  formats.
+
+* I've attempted to minimize static link pollution.  If you don't
+  explicitly invoke a particular feature (such as support for a
+  particular compression or format), it won't get pulled in to
+  statically-linked programs.  In particular, if you don't explicitly
+  enable a particular compression or decompression support, you won't
+  need to link against the corresponding compression or decompression
+  libraries.  This also reduces the size of statically-linked
+  binaries in environments where that matters.
+
+* The library is generally _thread safe_ depending on the platform:
+  it does not define any global variables of its own.  However, some
+  platforms do not provide fully thread-safe versions of key C library
+  functions.  On those platforms, libarchive will use the non-thread-safe
+  functions.  Patches to improve this are of great interest to us.
+
+* In particular, libarchive's modules to read or write a directory
+  tree do use `chdir()` to optimize the directory traversals.  This
+  can cause problems for programs that expect to do disk access from
+  multiple threads.  Of course, those modules are completely
+  optional and you can use the rest of libarchive without them.
+
+* The library is _not_ thread aware, however.  It does no locking
+  or thread management of any kind.  If you create a libarchive
+  object and need to access it from multiple threads, you will
+  need to provide your own locking.
+
+* On read, the library accepts whatever blocks you hand it.
+  Your read callback is free to pass the library a byte at a time
+  or mmap the entire archive and give it to the library at once.
+  On write, the library always produces correctly-blocked output.
+
+* The object-style approach allows you to have multiple archive streams
+  open at once.  bsdtar uses this in its "@archive" extension.
+
+* The archive itself is read/written using callback functions.
+  You can read an archive directly from an in-memory buffer or
+  write it to a socket, if you wish.  There are some utility
+  functions to provide easy-to-use "open file," etc, capabilities.
+
+* The read/write APIs are designed to allow individual entries
+  to be read or written to any data source:  You can create
+  a block of data in memory and add it to a tar archive without
+  first writing a temporary file.  You can also read an entry from
+  an archive and write the data directly to a socket.  If you want
+  to read/write entries to disk, there are convenience functions to
+  make this especially easy.
+
+* Note: The "pax interchange format" is a POSIX standard extended tar
+  format that should be used when the older _ustar_ format is not
+  appropriate.  It has many advantages over other tar formats
+  (including the legacy GNU tar format) and is widely supported by
+  current tar implementations.
+

Modified: releng/11.0/contrib/libarchive/libarchive/archive_acl.c
==============================================================================
--- releng/11.0/contrib/libarchive/libarchive/archive_acl.c	Tue Sep 27 19:00:22 2016	(r306378)
+++ releng/11.0/contrib/libarchive/libarchive/archive_acl.c	Tue Sep 27 19:36:12 2016	(r306379)
@@ -707,10 +707,11 @@ archive_acl_text_l(struct archive_acl *a
 			if (r != 0)
 				return (-1);
 			*p++ = separator;
-			if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+			if (name == NULL || (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) {
 				id = ap->id;
-			else
+			} else {
 				id = -1;
+			}
 			append_entry(&p, NULL, ap->tag, name,
 			    ap->permset, id);
 			count++;

Modified: releng/11.0/contrib/libarchive/libarchive/archive_platform.h
==============================================================================
--- releng/11.0/contrib/libarchive/libarchive/archive_platform.h	Tue Sep 27 19:00:22 2016	(r306378)
+++ releng/11.0/contrib/libarchive/libarchive/archive_platform.h	Tue Sep 27 19:36:12 2016	(r306379)
@@ -159,6 +159,15 @@
 #define	CAN_RESTORE_METADATA_FD
 #endif
 
+/*
+ * glibc 2.24 deprecates readdir_r
+ */
+#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
+#define	USE_READDIR_R	1
+#else
+#undef	USE_READDIR_R
+#endif
+
 /* Set up defaults for internal error codes. */
 #ifndef ARCHIVE_ERRNO_FILE_FORMAT
 #if HAVE_EFTYPE

Modified: releng/11.0/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
==============================================================================
--- releng/11.0/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c	Tue Sep 27 19:00:22 2016	(r306378)
+++ releng/11.0/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c	Tue Sep 27 19:36:12 2016	(r306379)
@@ -411,20 +411,38 @@ setup_acls(struct archive_read_disk *a,
 {
 	const char	*accpath;
 	acl_t		 acl;
-#if HAVE_ACL_IS_TRIVIAL_NP
 	int		r;
-#endif
 
 	accpath = archive_entry_sourcepath(entry);
 	if (accpath == NULL)
 		accpath = archive_entry_pathname(entry);
 
+	if (*fd < 0 && a->tree != NULL) {
+		if (a->follow_symlinks ||
+		    archive_entry_filetype(entry) != AE_IFLNK)
+			*fd = a->open_on_current_dir(a->tree,
+			    accpath, O_RDONLY | O_NONBLOCK);
+		if (*fd < 0) {
+			if (a->tree_enter_working_dir(a->tree) != 0) {
+				archive_set_error(&a->archive, errno,
+				    "Couldn't access %s", accpath);
+				return (ARCHIVE_FAILED);
+			}
+		}
+	}
+
 	archive_entry_acl_clear(entry);
 
+	acl = NULL;
+
 #ifdef ACL_TYPE_NFS4
 	/* Try NFS4 ACL first. */
 	if (*fd >= 0)
+#if HAVE_ACL_GET_FD_NP
+		acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
+#else
 		acl = acl_get_fd(*fd);
+#endif
 #if HAVE_ACL_GET_LINK_NP
 	else if (!a->follow_symlinks)
 		acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
@@ -437,20 +455,31 @@ setup_acls(struct archive_read_disk *a,
 #endif
 	else
 		acl = acl_get_file(accpath, ACL_TYPE_NFS4);
+
 #if HAVE_ACL_IS_TRIVIAL_NP
-	/* Ignore "trivial" ACLs that just mirror the file mode. */
-	acl_is_trivial_np(acl, &r);
-	if (r) {
-		acl_free(acl);
-		acl = NULL;
+	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
+		/* Ignore "trivial" ACLs that just mirror the file mode. */
+		if (r) {
+			acl_free(acl);
+			acl = NULL;
+			/*
+			 * Simultaneous NFSv4 and POSIX.1e ACLs for the same
+			 * entry are not allowed, so we should return here
+			 */
+			return (ARCHIVE_OK);
+		}
 	}
 #endif
 	if (acl != NULL) {
-		translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
 		acl_free(acl);
-		return (ARCHIVE_OK);
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, errno,
+			    "Couldn't translate NFSv4 ACLs: %s", accpath);
+		}
+		return (r);
 	}
-#endif
+#endif	/* ACL_TYPE_NFS4 */
 
 	/* Retrieve access ACL from file. */
 	if (*fd >= 0)
@@ -467,19 +496,42 @@ setup_acls(struct archive_read_disk *a,
 #endif
 	else
 		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
+
+#if HAVE_ACL_IS_TRIVIAL_NP
+	/* Ignore "trivial" ACLs that just mirror the file mode. */
+	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
+		if (r) {
+			acl_free(acl);
+			acl = NULL;
+		}
+	}
+#endif
+
 	if (acl != NULL) {
-		translate_acl(a, entry, acl,
+		r = translate_acl(a, entry, acl,
 		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
 		acl_free(acl);
+		acl = NULL;
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, errno,
+			    "Couldn't translate access ACLs: %s", accpath);
+			return (r);
+		}
 	}
 
 	/* Only directories can have default ACLs. */
 	if (S_ISDIR(archive_entry_mode(entry))) {
 		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
 		if (acl != NULL) {
-			translate_acl(a, entry, acl,
+			r = translate_acl(a, entry, acl,
 			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
 			acl_free(acl);
+			if (r != ARCHIVE_OK) {
+				archive_set_error(&a->archive, errno,
+				    "Couldn't translate default ACLs: %s",
+				    accpath);
+				return (r);
+			}
 		}
 	}
 	return (ARCHIVE_OK);
@@ -535,19 +587,23 @@ translate_acl(struct archive_read_disk *
 #ifdef ACL_TYPE_NFS4
 	acl_entry_type_t acl_type;
 	acl_flagset_t	 acl_flagset;
-	int brand, r;
+	int brand;
 #endif
 	acl_entry_t	 acl_entry;
 	acl_permset_t	 acl_permset;
 	int		 i, entry_acl_type;
-	int		 s, ae_id, ae_tag, ae_perm;
+	int		 r, s, ae_id, ae_tag, ae_perm;
 	const char	*ae_name;
 
 #ifdef ACL_TYPE_NFS4
 	// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
 	// Make sure the "brand" on this ACL is consistent
 	// with the default_entry_acl_type bits provided.
-	acl_get_brand_np(acl, &brand);
+	if (acl_get_brand_np(acl, &brand) != 0) {
+		archive_set_error(&a->archive, errno,
+		    "Failed to read ACL brand");
+		return (ARCHIVE_WARN);
+	}
 	switch (brand) {
 	case ACL_BRAND_POSIX:
 		switch (default_entry_acl_type) {
@@ -555,31 +611,43 @@ translate_acl(struct archive_read_disk *
 		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
 			break;
 		default:
-			// XXX set warning message?
-			return ARCHIVE_FAILED;
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Invalid ACL entry type for POSIX.1e ACL");
+			return (ARCHIVE_WARN);
 		}
 		break;
 	case ACL_BRAND_NFS4:
 		if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			// XXX set warning message?
-			return ARCHIVE_FAILED;
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Invalid ACL entry type for NFSv4 ACL");
+			return (ARCHIVE_WARN);
 		}
 		break;
 	default:
-		// XXX set warning message?
-		return ARCHIVE_FAILED;
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+		    "Unknown ACL brand");
+		return (ARCHIVE_WARN);
 		break;
 	}
 #endif
 
 
 	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
+	if (s == -1) {
+		archive_set_error(&a->archive, errno,
+		    "Failed to get first ACL entry");
+		return (ARCHIVE_WARN);
+	}
 	while (s == 1) {
 		ae_id = -1;
 		ae_name = NULL;
 		ae_perm = 0;
 
-		acl_get_tag_type(acl_entry, &acl_tag);
+		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
+			archive_set_error(&a->archive, errno,
+			    "Failed to get ACL tag type");
+			return (ARCHIVE_WARN);
+		}
 		switch (acl_tag) {
 		case ACL_USER:
 			ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
@@ -614,13 +682,18 @@ translate_acl(struct archive_read_disk *
 			continue;
 		}
 
-		// XXX acl type maps to allow/deny/audit/YYYY bits
-		// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
-		// non-NFSv4 ACLs
+		// XXX acl_type maps to allow/deny/audit/YYYY bits
 		entry_acl_type = default_entry_acl_type;
 #ifdef ACL_TYPE_NFS4
-		r = acl_get_entry_type_np(acl_entry, &acl_type);
-		if (r == 0) {
+		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			/*
+			 * acl_get_entry_type_np() falis with non-NFSv4 ACLs
+			 */
+			if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
+				archive_set_error(&a->archive, errno, "Failed "
+				    "to get ACL type from a NFSv4 ACL entry");
+				return (ARCHIVE_WARN);
+			}
 			switch (acl_type) {
 			case ACL_ENTRY_TYPE_ALLOW:
 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
@@ -634,32 +707,53 @@ translate_acl(struct archive_read_disk *
 			case ACL_ENTRY_TYPE_ALARM:
 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
 				break;
+			default:
+				archive_set_error(&a->archive, errno,
+				    "Invalid NFSv4 ACL entry type");
+				return (ARCHIVE_WARN);
 			}
-		}
 
-		/*
-		 * Libarchive stores "flag" (NFSv4 inheritance bits)
-		 * in the ae_perm bitmap.
-		 */
-		// 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) {
+			/*
+			 * Libarchive stores "flag" (NFSv4 inheritance bits)
+			 * in the ae_perm bitmap.
+			 *
+			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
+			 */
+			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+				archive_set_error(&a->archive, errno,
+				    "Failed to get flagset from a NFSv4 ACL entry");
+				return (ARCHIVE_WARN);
+			}
 	                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))
+				r = acl_get_flag_np(acl_flagset,
+				    acl_inherit_map[i].platform_inherit);
+				if (r == -1) {
+					archive_set_error(&a->archive, errno,
+					    "Failed to check flag in a NFSv4 "
+					    "ACL flagset");
+					return (ARCHIVE_WARN);
+				} else if (r)
 					ae_perm |= acl_inherit_map[i].archive_inherit;
                 	}
 		}
 #endif
 
-		acl_get_permset(acl_entry, &acl_permset);
+		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+			archive_set_error(&a->archive, errno,
+			    "Failed to get ACL permission set");
+			return (ARCHIVE_WARN);
+		}
 		for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
 			/*
 			 * acl_get_perm() is spelled differently on different
 			 * platforms; see above.
 			 */
-			if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
+			r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
+			if (r == -1) {
+				archive_set_error(&a->archive, errno,
+				    "Failed to check permission in an ACL permission set");
+				return (ARCHIVE_WARN);
+			} else if (r)
 				ae_perm |= acl_perm_map[i].archive_perm;
 		}
 
@@ -668,6 +762,11 @@ translate_acl(struct archive_read_disk *
 					    ae_id, ae_name);
 
 		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+		if (s == -1) {
+			archive_set_error(&a->archive, errno,
+			    "Failed to get next ACL entry");
+			return (ARCHIVE_WARN);
+		}
 	}
 	return (ARCHIVE_OK);
 }

Modified: releng/11.0/contrib/libarchive/libarchive/archive_read_disk_posix.c
==============================================================================
--- releng/11.0/contrib/libarchive/libarchive/archive_read_disk_posix.c	Tue Sep 27 19:00:22 2016	(r306378)
+++ releng/11.0/contrib/libarchive/libarchive/archive_read_disk_posix.c	Tue Sep 27 19:36:12 2016	(r306379)
@@ -165,7 +165,7 @@ struct filesystem {
 	int		synthetic;
 	int		remote;
 	int		noatime;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	size_t		name_max;
 #endif
 	long		incr_xfer_size;
@@ -200,7 +200,7 @@ struct tree {
 	DIR			*d;
 #define	INVALID_DIR_HANDLE NULL
 	struct dirent		*de;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	struct dirent		*dirent;
 	size_t			 dirent_allocated;
 #endif
@@ -1504,10 +1504,19 @@ setup_current_filesystem(struct archive_
 	struct tree *t = a->tree;
 	struct statfs sfs;
 #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
-#  if defined(HAVE_STRUCT_VFSCONF)
-	struct vfsconf vfc;
-#  else
+/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
+ * this accurate; some platforms have both and we need the one that's
+ * used by getvfsbyname()
+ *
+ * Then the following would become:
+ *  #if defined(GETVFSBYNAME_ARG_TYPE)
+ *   GETVFSBYNAME_ARG_TYPE vfc;
+ *  #endif
+ */
+#  if defined(HAVE_STRUCT_XVFSCONF)
 	struct xvfsconf vfc;
+#  else
+	struct vfsconf vfc;
 #  endif
 #endif
 	int r, xr = 0;
@@ -1583,7 +1592,7 @@ setup_current_filesystem(struct archive_
 #endif
 		t->current_filesystem->noatime = 0;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
 	t->current_filesystem->name_max = sfs.f_namemax;
@@ -1606,7 +1615,7 @@ setup_current_filesystem(struct archive_
 	else
 		t->current_filesystem->name_max = nm;
 #endif
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
 	return (ARCHIVE_OK);
 }
 
@@ -1808,7 +1817,7 @@ setup_current_filesystem(struct archive_
 #endif
 		t->current_filesystem->noatime = 0;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 	t->current_filesystem->name_max = sfs.f_namelen;
 #endif
@@ -1892,7 +1901,7 @@ setup_current_filesystem(struct archive_
 #endif
 		t->current_filesystem->noatime = 0;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 	t->current_filesystem->name_max = sfs.f_namemax;
 #endif
@@ -1909,7 +1918,7 @@ static int
 setup_current_filesystem(struct archive_read_disk *a)
 {
 	struct tree *t = a->tree;
-#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R)
+#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
 	long nm;
 #endif
 	t->current_filesystem->synthetic = -1;/* Not supported */
@@ -1921,7 +1930,7 @@ setup_current_filesystem(struct archive_
 	t->current_filesystem->min_xfer_size = -1;
 	t->current_filesystem->incr_xfer_size = -1;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 #  if defined(_PC_NAME_MAX)
 	if (tree_current_is_symblic_link_target(t)) {
@@ -1949,7 +1958,7 @@ setup_current_filesystem(struct archive_
 	else
 		t->current_filesystem->name_max = nm;
 #  endif /* _PC_NAME_MAX */
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
 	return (ARCHIVE_OK);
 }
 
@@ -2357,7 +2366,7 @@ tree_dir_next_posix(struct tree *t)
 	size_t namelen;
 
 	if (t->d == NULL) {
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 		size_t dirent_size;
 #endif
 
@@ -2378,7 +2387,7 @@ tree_dir_next_posix(struct tree *t)
 			t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
 			return (t->visit_type);
 		}
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 		dirent_size = offsetof(struct dirent, d_name) +
 		  t->filesystem_table[t->current->filesystem_id].name_max + 1;
 		if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
@@ -2395,11 +2404,11 @@ tree_dir_next_posix(struct tree *t)
 			}
 			t->dirent_allocated = dirent_size;
 		}
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
 	}
 	for (;;) {
 		errno = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 		r = readdir_r(t->d, t->dirent, &t->de);
 #ifdef _AIX
 		/* Note: According to the man page, return value 9 indicates
@@ -2651,7 +2660,7 @@ tree_free(struct tree *t)
 	if (t == NULL)
 		return;
 	archive_string_free(&t->path);
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	free(t->dirent);
 #endif
 	free(t->sparse_list);

Modified: releng/11.0/contrib/libarchive/libarchive/archive_read_support_format_tar.c
==============================================================================
--- releng/11.0/contrib/libarchive/libarchive/archive_read_support_format_tar.c	Tue Sep 27 19:00:22 2016	(r306378)
+++ releng/11.0/contrib/libarchive/libarchive/archive_read_support_format_tar.c	Tue Sep 27 19:36:12 2016	(r306379)
@@ -136,6 +136,7 @@ struct tar {
 	int64_t			 entry_padding;
 	int64_t 		 entry_bytes_unconsumed;
 	int64_t			 realsize;
+	int			 sparse_allowed;
 	struct sparse_block	*sparse_list;
 	struct sparse_block	*sparse_last;
 	int64_t			 sparse_offset;
@@ -1271,6 +1272,14 @@ header_common(struct archive_read *a, st
 		 * sparse information in the extended area.
 		 */
 		/* FALLTHROUGH */
+	case '0':
+		/*
+		 * Enable sparse file "read" support only for regular
+		 * files and explicit GNU sparse files.  However, we
+		 * don't allow non-standard file types to be sparse.
+		 */
+		tar->sparse_allowed = 1;
+		/* FALLTHROUGH */
 	default: /* Regular file  and non-standard types */
 		/*
 		 * Per POSIX: non-recognized types should always be
@@ -1730,6 +1739,14 @@ pax_attribute(struct archive_read *a, st
 #endif
 	switch (key[0]) {
 	case 'G':
+		/* Reject GNU.sparse.* headers on non-regular files. */
+		if (strncmp(key, "GNU.sparse", 10) == 0 &&
+		    !tar->sparse_allowed) {
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Non-regular file cannot be sparse");
+			return (ARCHIVE_FATAL);
+		}
+
 		/* GNU "0.0" sparse pax format. */
 		if (strcmp(key, "GNU.sparse.numblocks") == 0) {
 			tar->sparse_offset = -1;

Modified: releng/11.0/contrib/libarchive/libarchive/archive_write_disk_acl.c
==============================================================================
--- releng/11.0/contrib/libarchive/libarchive/archive_write_disk_acl.c	Tue Sep 27 19:00:22 2016	(r306378)
+++ releng/11.0/contrib/libarchive/libarchive/archive_write_disk_acl.c	Tue Sep 27 19:36:12 2016	(r306379)
@@ -153,9 +153,19 @@ set_acl(struct archive *a, int fd, const
 	if (entries == 0)
 		return (ARCHIVE_OK);
 	acl = acl_init(entries);
+	if (acl == (acl_t)NULL) {
+		archive_set_error(a, errno,
+		    "Failed to initialize ACL working storage");
+		return (ARCHIVE_FAILED);
+	}
 	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
 		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
-		acl_create_entry(&acl, &acl_entry);
+		if (acl_create_entry(&acl, &acl_entry) != 0) {
+			archive_set_error(a, errno,
+			    "Failed to create a new ACL entry");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
 
 		switch (ae_tag) {
 		case ARCHIVE_ENTRY_ACL_USER:
@@ -186,53 +196,96 @@ set_acl(struct archive *a, int fd, const
 			break;
 #endif
 		default:
-			/* XXX */
-			break;
+			archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			    "Unknown ACL tag");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
 		}
 
 #ifdef ACL_TYPE_NFS4
+		r = 0;
 		switch (ae_type) {
 		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
 		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
 			// These don't translate directly into the system ACL.
 			break;
 		default:
-			// XXX error handling here.
-			break;
+			archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			    "Unknown ACL entry type");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
+		if (r != 0) {
+			archive_set_error(a, errno,
+			    "Failed to set ACL entry type");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
 		}
 #endif
 
-		acl_get_permset(acl_entry, &acl_permset);
-		acl_clear_perms(acl_permset);
+		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+			archive_set_error(a, errno,
+			    "Failed to get ACL permission set");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
+		if (acl_clear_perms(acl_permset) != 0) {
+			archive_set_error(a, errno,
+			    "Failed to clear ACL permissions");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
 
 		for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
 			if (ae_permset & acl_perm_map[i].archive_perm)
-				acl_add_perm(acl_permset,
-					     acl_perm_map[i].platform_perm);
+				if (acl_add_perm(acl_permset,
+				    acl_perm_map[i].platform_perm) != 0) {
+					archive_set_error(a, errno,
+					    "Failed to add ACL permission");
+					ret = ARCHIVE_FAILED;
+					goto exit_free;
+				}
 		}
 
 #ifdef ACL_TYPE_NFS4
-		// 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);
+		if (acl_type == ACL_TYPE_NFS4) {
+			/*
+			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
+			 */
+			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+				archive_set_error(a, errno,
+				    "Failed to get flagset from an NFSv4 ACL entry");
+				ret = ARCHIVE_FAILED;
+				goto exit_free;
+			}
+			if (acl_clear_flags_np(acl_flagset) != 0) {
+				archive_set_error(a, errno,
+				    "Failed to clear flags from an NFSv4 ACL flagset");
+				ret = ARCHIVE_FAILED;
+				goto exit_free;
+			}
 			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);
+				if (ae_permset & acl_inherit_map[i].archive_inherit) {
+					if (acl_add_flag_np(acl_flagset,
+							acl_inherit_map[i].platform_inherit) != 0) {
+						archive_set_error(a, errno,
+						    "Failed to add flag to NFSv4 ACL flagset");
+						ret = ARCHIVE_FAILED;
+						goto exit_free;
+					}
+				}
 			}
 		}
 #endif
@@ -262,6 +315,7 @@ set_acl(struct archive *a, int fd, const
 		ret = ARCHIVE_WARN;
 	}
 #endif
+exit_free:
 	acl_free(acl);
 	return (ret);
 }

Modified: releng/11.0/contrib/libarchive/libarchive/archive_write_disk_posix.c
==============================================================================
--- releng/11.0/contrib/libarchive/libarchive/archive_write_disk_posix.c	Tue Sep 27 19:00:22 2016	(r306378)
+++ releng/11.0/contrib/libarchive/libarchive/archive_write_disk_posix.c	Tue Sep 27 19:36:12 2016	(r306379)
@@ -140,7 +140,17 @@ __FBSDID("$FreeBSD$");
 #define O_BINARY 0
 #endif
 #ifndef O_CLOEXEC
-#define O_CLOEXEC	0
+#define O_CLOEXEC 0
+#endif
+
+/* Ignore non-int O_NOFOLLOW constant. */
+/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
+#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
+#undef O_NOFOLLOW
+#endif
+
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
 #endif
 
 struct fixup_entry {
@@ -326,12 +336,14 @@ struct archive_write_disk {
 
 #define HFS_BLOCKS(s)	((s) >> 12)
 
+static int	check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
 static int	check_symlinks(struct archive_write_disk *);
 static int	create_filesystem_object(struct archive_write_disk *);
 static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
 #if defined(HAVE_FCHDIR) && defined(PATH_MAX)
 static void	edit_deep_directories(struct archive_write_disk *ad);
 #endif
+static int	cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
 static int	cleanup_pathname(struct archive_write_disk *);
 static int	create_dir(struct archive_write_disk *, char *);
 static int	create_parent_dir(struct archive_write_disk *, char *);
@@ -2014,6 +2026,10 @@ create_filesystem_object(struct archive_
 	const char *linkname;
 	mode_t final_mode, mode;
 	int r;
+	/* these for check_symlinks_fsobj */
+	char *linkname_copy;	/* non-const copy of linkname */
+	struct archive_string error_string;
+	int error_number;
 
 	/* We identify hard/symlinks according to the link names. */
 	/* Since link(2) and symlink(2) don't handle modes, we're done here. */
@@ -2022,6 +2038,27 @@ create_filesystem_object(struct archive_
 #if !HAVE_LINK
 		return (EPERM);
 #else
+		archive_string_init(&error_string);
+		linkname_copy = strdup(linkname);
+		if (linkname_copy == NULL) {
+		    return (EPERM);
+		}
+		/* TODO: consider using the cleaned-up path as the link target? */
+		r = cleanup_pathname_fsobj(linkname_copy, &error_number, &error_string, a->flags);
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, error_number, "%s", error_string.s);
+			free(linkname_copy);
+			/* EPERM is more appropriate than error_number for our callers */
+			return (EPERM);
+		}
+		r = check_symlinks_fsobj(linkname_copy, &error_number, &error_string, a->flags);
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, error_number, "%s", error_string.s);
+			free(linkname_copy);
+			/* EPERM is more appropriate than error_number for our callers */
+			return (EPERM);
+		}
+		free(linkname_copy);
 		r = link(linkname, a->name) ? errno : 0;
 		/*
 		 * New cpio and pax formats allow hardlink entries
@@ -2040,7 +2077,7 @@ create_filesystem_object(struct archive_
 			a->deferred = 0;
 		} else if (r == 0 && a->filesize > 0) {
 			a->fd = open(a->name,
-				     O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
+				     O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC | O_NOFOLLOW);
 			__archive_ensure_cloexec_flag(a->fd);
 			if (a->fd < 0)
 				r = errno;
@@ -2351,126 +2388,233 @@ current_fixup(struct archive_write_disk 
 	return (a->current_fixup);
 }
 
-/* TODO: Make this work. */
-/*
- * TODO: The deep-directory support bypasses this; disable deep directory
- * support if we're doing symlink checks.
- */
 /*
  * TODO: Someday, integrate this with the deep dir support; they both
  * scan the path and both can be optimized by comparing against other
  * recent paths.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list