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>