Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Oct 2016 18:34:40 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r307229 - in user/cperciva/freebsd-update-build/patches: 10.1-RELEASE 10.2-RELEASE 10.3-RELEASE 11.0-RELEASE 9.3-RELEASE
Message-ID:  <201610131834.u9DIYesr070630@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Thu Oct 13 18:34:39 2016
New Revision: 307229
URL: https://svnweb.freebsd.org/changeset/base/307229

Log:
  Save the latest patch queue.

Added:
  user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:29.bspatch
  user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:30.portsnap
  user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:31.libarchive
  user/cperciva/freebsd-update-build/patches/10.2-RELEASE/23-SA-16:29.bspatch
  user/cperciva/freebsd-update-build/patches/10.2-RELEASE/23-SA-16:30.portsnap
  user/cperciva/freebsd-update-build/patches/10.2-RELEASE/23-SA-16:31.libarchive
  user/cperciva/freebsd-update-build/patches/10.3-RELEASE/10-SA-16:29.bspatch
  user/cperciva/freebsd-update-build/patches/10.3-RELEASE/10-SA-16:30.portsnap
  user/cperciva/freebsd-update-build/patches/10.3-RELEASE/10-SA-16:31.libarchive
  user/cperciva/freebsd-update-build/patches/11.0-RELEASE/
  user/cperciva/freebsd-update-build/patches/11.0-RELEASE/0-EN-16:99.newvers
  user/cperciva/freebsd-update-build/patches/9.3-RELEASE/48-SA-16:28.bind
  user/cperciva/freebsd-update-build/patches/9.3-RELEASE/48-SA-16:29.bspatch
  user/cperciva/freebsd-update-build/patches/9.3-RELEASE/48-SA-16:30.portsnap

Added: user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:29.bspatch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:29.bspatch	Thu Oct 13 18:34:39 2016	(r307229)
@@ -0,0 +1,325 @@
+--- usr.bin/bsdiff/bspatch/bspatch.c.orig
++++ usr.bin/bsdiff/bspatch/bspatch.c
+@@ -27,56 +27,133 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD$");
+ 
++#if defined(__FreeBSD__)
++#include <sys/param.h>
++#if __FreeBSD_version >= 1001511
++#include <sys/capsicum.h>
++#define HAVE_CAPSICUM
++#endif
++#endif
++
+ #include <bzlib.h>
+-#include <stdlib.h>
++#include <err.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <libgen.h>
++#include <limits.h>
++#include <stdint.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <string.h>
+-#include <err.h>
+ #include <unistd.h>
+-#include <fcntl.h>
+ 
+ #ifndef O_BINARY
+ #define O_BINARY 0
+ #endif
++#define HEADER_SIZE 32
++
++static char *newfile;
++static int dirfd = -1;
++
++static void
++exit_cleanup(void)
++{
++
++	if (dirfd != -1 && newfile != NULL)
++		if (unlinkat(dirfd, newfile, 0))
++			warn("unlinkat");
++}
+ 
+ static off_t offtin(u_char *buf)
+ {
+ 	off_t y;
+ 
+-	y=buf[7]&0x7F;
+-	y=y*256;y+=buf[6];
+-	y=y*256;y+=buf[5];
+-	y=y*256;y+=buf[4];
+-	y=y*256;y+=buf[3];
+-	y=y*256;y+=buf[2];
+-	y=y*256;y+=buf[1];
+-	y=y*256;y+=buf[0];
++	y = buf[7] & 0x7F;
++	y = y * 256; y += buf[6];
++	y = y * 256; y += buf[5];
++	y = y * 256; y += buf[4];
++	y = y * 256; y += buf[3];
++	y = y * 256; y += buf[2];
++	y = y * 256; y += buf[1];
++	y = y * 256; y += buf[0];
+ 
+-	if(buf[7]&0x80) y=-y;
++	if (buf[7] & 0x80)
++		y = -y;
+ 
+-	return y;
++	return (y);
+ }
+ 
+-int main(int argc,char * argv[])
++int main(int argc, char *argv[])
+ {
+-	FILE * f, * cpf, * dpf, * epf;
+-	BZFILE * cpfbz2, * dpfbz2, * epfbz2;
++	FILE *f, *cpf, *dpf, *epf;
++	BZFILE *cpfbz2, *dpfbz2, *epfbz2;
++	char *directory, *namebuf;
+ 	int cbz2err, dbz2err, ebz2err;
+-	int fd;
+-	ssize_t oldsize,newsize;
+-	ssize_t bzctrllen,bzdatalen;
+-	u_char header[32],buf[8];
++	int newfd, oldfd;
++	off_t oldsize, newsize;
++	off_t bzctrllen, bzdatalen;
++	u_char header[HEADER_SIZE], buf[8];
+ 	u_char *old, *new;
+-	off_t oldpos,newpos;
++	off_t oldpos, newpos;
+ 	off_t ctrl[3];
+-	off_t lenread;
+-	off_t i;
++	off_t i, lenread, offset;
++#ifdef HAVE_CAPSICUM
++	cap_rights_t rights_dir, rights_ro, rights_wr;
++#endif
+ 
+ 	if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+ 
+ 	/* Open patch file */
+ 	if ((f = fopen(argv[3], "rb")) == NULL)
+ 		err(1, "fopen(%s)", argv[3]);
++	/* Open patch file for control block */
++	if ((cpf = fopen(argv[3], "rb")) == NULL)
++		err(1, "fopen(%s)", argv[3]);
++	/* open patch file for diff block */
++	if ((dpf = fopen(argv[3], "rb")) == NULL)
++		err(1, "fopen(%s)", argv[3]);
++	/* open patch file for extra block */
++	if ((epf = fopen(argv[3], "rb")) == NULL)
++		err(1, "fopen(%s)", argv[3]);
++	/* open oldfile */
++	if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0)
++		err(1, "open(%s)", argv[1]);
++	/* open directory where we'll write newfile */
++	if ((namebuf = strdup(argv[2])) == NULL ||
++	    (directory = dirname(namebuf)) == NULL ||
++	    (dirfd = open(directory, O_DIRECTORY)) < 0)
++		err(1, "open %s", argv[2]);
++	free(namebuf);
++	if ((newfile = basename(argv[2])) == NULL)
++		err(1, "basename");
++	/* open newfile */
++	if ((newfd = openat(dirfd, newfile,
++	    O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0)
++		err(1, "open(%s)", argv[2]);
++	atexit(exit_cleanup);
++
++#ifdef HAVE_CAPSICUM
++	if (cap_enter() < 0) {
++		/* Failed to sandbox, fatal if CAPABILITY_MODE enabled */
++		if (errno != ENOSYS)
++			err(1, "failed to enter security sandbox");
++	} else {
++		/* Capsicum Available */
++		cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK);
++		cap_rights_init(&rights_wr, CAP_WRITE);
++		cap_rights_init(&rights_dir, CAP_UNLINKAT);
++
++		if (cap_rights_limit(fileno(f), &rights_ro) < 0 ||
++		    cap_rights_limit(fileno(cpf), &rights_ro) < 0 ||
++		    cap_rights_limit(fileno(dpf), &rights_ro) < 0 ||
++		    cap_rights_limit(fileno(epf), &rights_ro) < 0 ||
++		    cap_rights_limit(oldfd, &rights_ro) < 0 ||
++		    cap_rights_limit(newfd, &rights_wr) < 0 ||
++		    cap_rights_limit(dirfd, &rights_dir) < 0)
++			err(1, "cap_rights_limit() failed, could not restrict"
++			    " capabilities");
++	}
++#endif
+ 
+ 	/*
+ 	File format:
+@@ -93,99 +170,99 @@
+ 	*/
+ 
+ 	/* Read header */
+-	if (fread(header, 1, 32, f) < 32) {
++	if (fread(header, 1, HEADER_SIZE, f) < HEADER_SIZE) {
+ 		if (feof(f))
+-			errx(1, "Corrupt patch\n");
++			errx(1, "Corrupt patch");
+ 		err(1, "fread(%s)", argv[3]);
+ 	}
+ 
+ 	/* Check for appropriate magic */
+ 	if (memcmp(header, "BSDIFF40", 8) != 0)
+-		errx(1, "Corrupt patch\n");
++		errx(1, "Corrupt patch");
+ 
+ 	/* Read lengths from header */
+-	bzctrllen=offtin(header+8);
+-	bzdatalen=offtin(header+16);
+-	newsize=offtin(header+24);
+-	if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
+-		errx(1,"Corrupt patch\n");
++	bzctrllen = offtin(header + 8);
++	bzdatalen = offtin(header + 16);
++	newsize = offtin(header + 24);
++	if (bzctrllen < 0 || bzctrllen > OFF_MAX - HEADER_SIZE ||
++	    bzdatalen < 0 || bzctrllen + HEADER_SIZE > OFF_MAX - bzdatalen ||
++	    newsize < 0 || newsize > SSIZE_MAX)
++		errx(1, "Corrupt patch");
+ 
+ 	/* Close patch file and re-open it via libbzip2 at the right places */
+ 	if (fclose(f))
+ 		err(1, "fclose(%s)", argv[3]);
+-	if ((cpf = fopen(argv[3], "rb")) == NULL)
+-		err(1, "fopen(%s)", argv[3]);
+-	if (fseeko(cpf, 32, SEEK_SET))
+-		err(1, "fseeko(%s, %lld)", argv[3],
+-		    (long long)32);
++	offset = HEADER_SIZE;
++	if (fseeko(cpf, offset, SEEK_SET))
++		err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ 	if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
+ 		errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
+-	if ((dpf = fopen(argv[3], "rb")) == NULL)
+-		err(1, "fopen(%s)", argv[3]);
+-	if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
+-		err(1, "fseeko(%s, %lld)", argv[3],
+-		    (long long)(32 + bzctrllen));
++	offset += bzctrllen;
++	if (fseeko(dpf, offset, SEEK_SET))
++		err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ 	if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
+ 		errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
+-	if ((epf = fopen(argv[3], "rb")) == NULL)
+-		err(1, "fopen(%s)", argv[3]);
+-	if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
+-		err(1, "fseeko(%s, %lld)", argv[3],
+-		    (long long)(32 + bzctrllen + bzdatalen));
++	offset += bzdatalen;
++	if (fseeko(epf, offset, SEEK_SET))
++		err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ 	if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
+ 		errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
+ 
+-	if(((fd=open(argv[1],O_RDONLY|O_BINARY,0))<0) ||
+-		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+-		((old=malloc(oldsize+1))==NULL) ||
+-		(lseek(fd,0,SEEK_SET)!=0) ||
+-		(read(fd,old,oldsize)!=oldsize) ||
+-		(close(fd)==-1)) err(1,"%s",argv[1]);
+-	if((new=malloc(newsize+1))==NULL) err(1,NULL);
++	if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 ||
++	    oldsize > SSIZE_MAX ||
++	    (old = malloc(oldsize)) == NULL ||
++	    lseek(oldfd, 0, SEEK_SET) != 0 ||
++	    read(oldfd, old, oldsize) != oldsize ||
++	    close(oldfd) == -1)
++		err(1, "%s", argv[1]);
++	if ((new = malloc(newsize)) == NULL)
++		err(1, NULL);
+ 
+-	oldpos=0;newpos=0;
+-	while(newpos<newsize) {
++	oldpos = 0;
++	newpos = 0;
++	while (newpos < newsize) {
+ 		/* Read control data */
+-		for(i=0;i<=2;i++) {
++		for (i = 0; i <= 2; i++) {
+ 			lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
+ 			if ((lenread < 8) || ((cbz2err != BZ_OK) &&
+ 			    (cbz2err != BZ_STREAM_END)))
+-				errx(1, "Corrupt patch\n");
+-			ctrl[i]=offtin(buf);
++				errx(1, "Corrupt patch");
++			ctrl[i] = offtin(buf);
+ 		};
+ 
+ 		/* Sanity-check */
+-		if ((ctrl[0] < 0) || (ctrl[1] < 0))
+-			errx(1,"Corrupt patch\n");
++		if (ctrl[0] < 0 || ctrl[0] > INT_MAX ||
++		    ctrl[1] < 0 || ctrl[1] > INT_MAX)
++			errx(1, "Corrupt patch");
+ 
+ 		/* Sanity-check */
+-		if(newpos+ctrl[0]>newsize)
+-			errx(1,"Corrupt patch\n");
++		if (newpos + ctrl[0] > newsize)
++			errx(1, "Corrupt patch");
+ 
+ 		/* Read diff string */
+ 		lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
+ 		if ((lenread < ctrl[0]) ||
+ 		    ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
+-			errx(1, "Corrupt patch\n");
++			errx(1, "Corrupt patch");
+ 
+ 		/* Add old data to diff string */
+-		for(i=0;i<ctrl[0];i++)
+-			if((oldpos+i>=0) && (oldpos+i<oldsize))
+-				new[newpos+i]+=old[oldpos+i];
++		for (i = 0; i < ctrl[0]; i++)
++			if ((oldpos + i >= 0) && (oldpos + i < oldsize))
++				new[newpos + i] += old[oldpos + i];
+ 
+ 		/* Adjust pointers */
+-		newpos+=ctrl[0];
+-		oldpos+=ctrl[0];
++		newpos += ctrl[0];
++		oldpos += ctrl[0];
+ 
+ 		/* Sanity-check */
+-		if(newpos+ctrl[1]>newsize)
+-			errx(1,"Corrupt patch\n");
++		if (newpos + ctrl[1] > newsize)
++			errx(1, "Corrupt patch");
+ 
+ 		/* Read extra string */
+ 		lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
+ 		if ((lenread < ctrl[1]) ||
+ 		    ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
+-			errx(1, "Corrupt patch\n");
++			errx(1, "Corrupt patch");
+ 
+ 		/* Adjust pointers */
+ 		newpos+=ctrl[1];
+@@ -200,12 +277,13 @@
+ 		err(1, "fclose(%s)", argv[3]);
+ 
+ 	/* Write the new file */
+-	if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))<0) ||
+-		(write(fd,new,newsize)!=newsize) || (close(fd)==-1))
+-		err(1,"%s",argv[2]);
++	if (write(newfd, new, newsize) != newsize || close(newfd) == -1)
++		err(1, "%s", argv[2]);
++	/* Disable atexit cleanup */
++	newfile = NULL;
+ 
+ 	free(new);
+ 	free(old);
+ 
+-	return 0;
++	return (0);
+ }

Added: user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:30.portsnap
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:30.portsnap	Thu Oct 13 18:34:39 2016	(r307229)
@@ -0,0 +1,49 @@
+--- usr.sbin/portsnap/portsnap/portsnap.sh.orig
++++ usr.sbin/portsnap/portsnap/portsnap.sh
+@@ -646,7 +646,7 @@
+ # Verify a list of files
+ fetch_snapshot_verify() {
+ 	while read F; do
+-		if [ "`gunzip -c snap/${F} | ${SHA256} -q`" != ${F} ]; then
++		if [ "`gunzip -c < snap/${F}.gz | ${SHA256} -q`" != ${F} ]; then
+ 			echo "snapshot corrupt."
+ 			return 1
+ 		fi
+@@ -681,11 +681,18 @@
+ 	cut -f 2 -d '|' tINDEX.new | fetch_snapshot_verify || return 1
+ # Extract the index
+ 	rm -f INDEX.new
+-	gunzip -c snap/`look INDEX tINDEX.new |
++	gunzip -c < snap/`look INDEX tINDEX.new |
+ 	    cut -f 2 -d '|'`.gz > INDEX.new
+ 	fetch_index_sanity || return 1
+ # Verify the snapshot contents
+ 	cut -f 2 -d '|' INDEX.new | fetch_snapshot_verify || return 1
++	cut -f 2 -d '|' tINDEX.new INDEX.new | sort -u > files.expected
++	find snap -mindepth 1 | sed -E 's^snap/(.*)\.gz^\1^' | sort > files.snap
++	if ! cmp -s files.expected files.snap; then
++		echo "unexpected files in snapshot."
++		return 1
++	fi
++	rm files.expected files.snap
+ 	echo "done."
+ 
+ # Move files into their proper locations
+@@ -777,7 +784,7 @@
+ 
+ # Extract the index
+ 	echo -n "Extracting index... " 1>${QUIETREDIR}
+-	gunzip -c files/`look INDEX tINDEX.new |
++	gunzip -c < files/`look INDEX tINDEX.new |
+ 	    cut -f 2 -d '|'`.gz > INDEX.new
+ 	fetch_index_sanity || return 1
+ 
+@@ -897,7 +904,7 @@
+ 		echo -n "$1 not provided by portsnap server; "
+ 		echo "$2 not being generated."
+ 	else
+-	gunzip -c "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX |
++	gunzip -c < "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX |
+ 	    cut -f 2 -d '|'`.gz" |
+ 	    cat - ${LOCALDESC} |
+ 	    ${MKINDEX} /dev/stdin > ${PORTSDIR}/$2

Added: user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:31.libarchive
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:31.libarchive	Thu Oct 13 18:34:39 2016	(r307229)
@@ -0,0 +1,1270 @@
+--- contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c.orig
++++ contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
+@@ -409,9 +409,7 @@
+ {
+ 	const char	*accpath;
+ 	acl_t		 acl;
+-#if HAVE_ACL_IS_TRIVIAL_NP
+ 	int		r;
+-#endif
+ 
+ 	accpath = archive_entry_sourcepath(entry);
+ 	if (accpath == NULL)
+@@ -443,9 +441,13 @@
+ 	}
+ #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);
+ 	}
+ 
+ 	/* Retrieve access ACL from file. */
+@@ -464,18 +466,29 @@
+ 	else
+ 		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
+ 	if (acl != NULL) {
+-		translate_acl(a, entry, acl,
++		r = translate_acl(a, entry, acl,
+ 		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ 		acl_free(acl);
++		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);
+@@ -536,7 +549,11 @@
+ 	// 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) {
+@@ -544,30 +561,42 @@
+ 		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;
+ 	}
+ 
+ 
+ 	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);
+@@ -600,12 +629,17 @@
+ 			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;
+-		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;
+@@ -619,28 +653,52 @@
+ 			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.
+-		 */
+-		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;
+ 
+-                }
++			/*
++			 * 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) {
++				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;
++                	}
++		}
+ 
+-		acl_get_permset(acl_entry, &acl_permset);
+-                for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
++		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;
+ 		}
+ 
+@@ -649,6 +707,11 @@
+ 					    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);
+ }
+--- contrib/libarchive/libarchive/archive_read_support_format_tar.c.orig
++++ contrib/libarchive/libarchive/archive_read_support_format_tar.c
+@@ -136,6 +136,7 @@
+ 	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;
+@@ -1216,6 +1217,14 @@
+ 		 * 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
+@@ -1675,6 +1684,14 @@
+ #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;
+--- contrib/libarchive/libarchive/archive_write_disk_acl.c.orig
++++ contrib/libarchive/libarchive/archive_write_disk_acl.c
+@@ -131,6 +131,7 @@
+ 	acl_entry_t	 acl_entry;
+ 	acl_permset_t	 acl_permset;
+ 	acl_flagset_t	 acl_flagset;
++	int		 r;
+ 	int		 ret;
+ 	int		 ae_type, ae_permset, ae_tag, ae_id;
+ 	uid_t		 ae_uid;
+@@ -144,9 +145,19 @@
+ 	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:
+@@ -175,47 +186,95 @@
+ 			acl_set_tag_type(acl_entry, ACL_EVERYONE);
+ 			break;
+ 		default:
+-			/* XXX */
+-			break;
++			archive_set_error(a, ARCHIVE_ERRNO_MISC,
++			    "Unknown ACL tag");
++			ret = ARCHIVE_FAILED;
++			goto exit_free;
+ 		}
+ 
++		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;
+ 		}
+ 
+-		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;
++				}
+ 		}
+ 
+ 		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);
++		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) {
++					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;
++					}
++				}
++			}
+ 		}
+ 	}
+ 
+@@ -243,6 +302,7 @@
+ 		ret = ARCHIVE_WARN;
+ 	}
+ #endif
++exit_free:
+ 	acl_free(acl);
+ 	return (ret);
+ }
+--- contrib/libarchive/libarchive/archive_write_disk_posix.c.orig
++++ contrib/libarchive/libarchive/archive_write_disk_posix.c
+@@ -140,7 +140,17 @@
+ #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 @@
+ 
+ #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 *);
+@@ -1791,7 +1803,7 @@
+ 	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. */
+@@ -1801,7 +1813,7 @@
+ 		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 != '/')
+@@ -1996,6 +2008,10 @@
+ 	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. */
+@@ -2004,6 +2020,27 @@
+ #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
+@@ -2022,7 +2059,7 @@
+ 			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;
+@@ -2332,110 +2369,233 @@
+ 	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.
+  */
+ /* TODO: Extend this to support symlinks on Windows Vista and later. */
++
++/*
++ * Checks the given path to see if any elements along it are symlinks.  Returns
++ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
++ */
+ static int
+-check_symlinks(struct archive_write_disk *a)
++check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags)
+ {
+ #if !defined(HAVE_LSTAT)
+ 	/* Platform doesn't have lstat, so we can't look for symlinks. */
+-	(void)a; /* UNUSED */
++	(void)path; /* UNUSED */
++	(void)error_number; /* UNUSED */
++	(void)error_string; /* UNUSED */
++	(void)flags; /* UNUSED */
+ 	return (ARCHIVE_OK);
+ #else
+-	char *pn;
++	int res = ARCHIVE_OK;
++	char *tail;
++	char *head;
++	int last;
+ 	char c;
+ 	int r;
+ 	struct stat st;
++	int restore_pwd;
++
++	/* Nothing to do here if name is empty */
++	if(path[0] == '\0')
++	    return (ARCHIVE_OK);
+ 
+ 	/*
+ 	 * Guard against symlink tricks.  Reject any archive entry whose
+ 	 * destination would be altered by a symlink.
++	 *
++	 * Walk the filename in chunks separated by '/'.  For each segment:
++	 *  - if it doesn't exist, continue
++	 *  - if it's symlink, abort or remove it
++	 *  - if it's a directory and it's not the last chunk, cd into it
++	 * As we go:
++	 *  head points to the current (relative) path
++	 *  tail points to the temporary \0 terminating the segment we're currently examining
++	 *  c holds what used to be in *tail
++	 *  last is 1 if this is the last tail
++	 */
++	restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
++	__archive_ensure_cloexec_flag(restore_pwd);
++	if (restore_pwd < 0)
++		return (ARCHIVE_FATAL);
++	head = path;
++	tail = path;
++	last = 0;
++	/* TODO: reintroduce a safe cache here? */
++	/* Skip the root directory if the path is absolute. */
++	if(tail == path && tail[0] == '/')
++		++tail;
++	/* Keep going until we've checked the entire name.
++	 * head, tail, path all alias the same string, which is
++	 * temporarily zeroed at tail, so be careful restoring the
++	 * stashed (c=tail[0]) for error messages.
++	 * Exiting the loop with break is okay; continue is not.
+ 	 */
+-	/* Whatever we checked last time doesn't need to be re-checked. */
+-	pn = a->name;
+-	if (archive_strlen(&(a->path_safe)) > 0) {
+-		char *p = a->path_safe.s;
+-		while ((*pn != '\0') && (*p == *pn))
+-			++p, ++pn;
+-	}
+-	c = pn[0];
+-	/* Keep going until we've checked the entire name. */
+-	while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
++	while (!last) {
++		/* Skip the separator we just consumed, plus any adjacent ones */
++		while (*tail == '/')
++		    ++tail;
+ 		/* Skip the next path element. */
+-		while (*pn != '\0' && *pn != '/')
+-			++pn;
+-		c = pn[0];
+-		pn[0] = '\0';

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610131834.u9DIYesr070630>