Author: delphij
Date: Mon Oct 10 07:19:16 2016
New Revision: 306942
URL: https://svnweb.freebsd.org/changeset/base/306942

Log:
  Fix BIND remote Denial of Service vulnerability. [SA-16:28]
  
  Fix bspatch heap overflow vulnerability. [SA-16:29]
  
  Fix multiple portsnap vulnerabilities. [SA-16:30]
  
  Approved by:  so

Modified:
  releng/9.3/UPDATING
  releng/9.3/contrib/bind9/lib/dns/message.c
  releng/9.3/sys/conf/newvers.sh
  releng/9.3/usr.bin/bsdiff/bspatch/bspatch.c
  releng/9.3/usr.sbin/portsnap/portsnap/portsnap.sh

Modified: releng/9.3/UPDATING
==============================================================================
--- releng/9.3/UPDATING Mon Oct 10 07:18:54 2016        (r306941)
+++ releng/9.3/UPDATING Mon Oct 10 07:19:16 2016        (r306942)
@@ -11,6 +11,16 @@ handbook:
 Items affecting the ports and packages system can be found in
 /usr/ports/UPDATING.  Please read that file before running portupgrade.
 
+20161010       p48     FreeBSD-SA-16:28.bind
+                       FreeBSD-SA-16:29.bspatch
+                       FreeBSD-SA-16:30.portsnap
+
+       Fix BIND remote Denial of Service vulnerability. [SA-16:28]
+
+       Fix bspatch heap overflow vulnerability. [SA-16:29]
+
+       Fix multiple portsnap vulnerabilities. [SA-16:30]
+
 20160926       p47     FreeBSD-SA-16:26.openssl [revised]
 
        Fix OpenSSL regression introduced in SA-16:26.

Modified: releng/9.3/contrib/bind9/lib/dns/message.c
==============================================================================
--- releng/9.3/contrib/bind9/lib/dns/message.c  Mon Oct 10 07:18:54 2016        
(r306941)
+++ releng/9.3/contrib/bind9/lib/dns/message.c  Mon Oct 10 07:19:16 2016        
(r306942)
@@ -1736,7 +1736,7 @@ dns_message_renderbegin(dns_message_t *m
        if (r.length < DNS_MESSAGE_HEADERLEN)
                return (ISC_R_NOSPACE);
 
-       if (r.length < msg->reserved)
+       if (r.length - DNS_MESSAGE_HEADERLEN < msg->reserved)
                return (ISC_R_NOSPACE);
 
        /*
@@ -1863,8 +1863,29 @@ norender_rdataset(const dns_rdataset_t *
 
        return (ISC_TRUE);
 }
-
 #endif
+
+static isc_result_t
+renderset(dns_rdataset_t *rdataset, dns_name_t *owner_name,
+         dns_compress_t *cctx, isc_buffer_t *target,
+         unsigned int reserved, unsigned int options, unsigned int *countp)
+{
+       isc_result_t result;
+
+       /*
+        * Shrink the space in the buffer by the reserved amount.
+        */
+       if (target->length - target->used < reserved)
+               return (ISC_R_NOSPACE);
+
+       target->length -= reserved;
+       result = dns_rdataset_towire(rdataset, owner_name,
+                                    cctx, target, options, countp);
+       target->length += reserved;
+
+       return (result);
+}
+
 isc_result_t
 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
                          unsigned int options)
@@ -1907,6 +1928,8 @@ dns_message_rendersection(dns_message_t 
        /*
         * Shrink the space in the buffer by the reserved amount.
         */
+       if (msg->buffer->length - msg->buffer->used < msg->reserved)
+               return (ISC_R_NOSPACE);
        msg->buffer->length -= msg->reserved;
 
        total = 0;
@@ -2183,9 +2206,8 @@ dns_message_renderend(dns_message_t *msg
                 * Render.
                 */
                count = 0;
-               result = dns_rdataset_towire(msg->opt, dns_rootname,
-                                            msg->cctx, msg->buffer, 0,
-                                            &count);
+               result = renderset(msg->opt, dns_rootname, msg->cctx,
+                                  msg->buffer, msg->reserved, 0, &count);
                msg->counts[DNS_SECTION_ADDITIONAL] += count;
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -2201,9 +2223,8 @@ dns_message_renderend(dns_message_t *msg
                if (result != ISC_R_SUCCESS)
                        return (result);
                count = 0;
-               result = dns_rdataset_towire(msg->tsig, msg->tsigname,
-                                            msg->cctx, msg->buffer, 0,
-                                            &count);
+               result = renderset(msg->tsig, msg->tsigname, msg->cctx,
+                                  msg->buffer, msg->reserved, 0, &count);
                msg->counts[DNS_SECTION_ADDITIONAL] += count;
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -2224,9 +2245,8 @@ dns_message_renderend(dns_message_t *msg
                 * the owner name of a SIG(0) is irrelevant, and will not
                 * be set in a message being rendered.
                 */
-               result = dns_rdataset_towire(msg->sig0, dns_rootname,
-                                            msg->cctx, msg->buffer, 0,
-                                            &count);
+               result = renderset(msg->sig0, dns_rootname, msg->cctx,
+                                  msg->buffer, msg->reserved, 0, &count);
                msg->counts[DNS_SECTION_ADDITIONAL] += count;
                if (result != ISC_R_SUCCESS)
                        return (result);

Modified: releng/9.3/sys/conf/newvers.sh
==============================================================================
--- releng/9.3/sys/conf/newvers.sh      Mon Oct 10 07:18:54 2016        
(r306941)
+++ releng/9.3/sys/conf/newvers.sh      Mon Oct 10 07:19:16 2016        
(r306942)
@@ -32,7 +32,7 @@
 
 TYPE="FreeBSD"
 REVISION="9.3"
-BRANCH="RELEASE-p47"
+BRANCH="RELEASE-p48"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
        BRANCH=${BRANCH_OVERRIDE}
 fi

Modified: releng/9.3/usr.bin/bsdiff/bspatch/bspatch.c
==============================================================================
--- releng/9.3/usr.bin/bsdiff/bspatch/bspatch.c Mon Oct 10 07:18:54 2016        
(r306941)
+++ releng/9.3/usr.bin/bsdiff/bspatch/bspatch.c Mon Oct 10 07:19:16 2016        
(r306942)
@@ -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 @@ int main(int argc,char * argv[])
        */
 
        /* 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);
-
-       oldpos=0;newpos=0;
-       while(newpos<newsize) {
+       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) {
                /* 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 @@ int main(int argc,char * argv[])
                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);
 }

Modified: releng/9.3/usr.sbin/portsnap/portsnap/portsnap.sh
==============================================================================
--- releng/9.3/usr.sbin/portsnap/portsnap/portsnap.sh   Mon Oct 10 07:18:54 
2016        (r306941)
+++ releng/9.3/usr.sbin/portsnap/portsnap/portsnap.sh   Mon Oct 10 07:19:16 
2016        (r306942)
@@ -609,7 +609,7 @@ fetch_index_sanity() {
 # 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
@@ -644,11 +644,18 @@ fetch_snapshot() {
        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
@@ -737,7 +744,7 @@ fetch_update() {
        echo "done."
 
 # Extract the index
-       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
 
@@ -842,7 +849,7 @@ extract_make_index() {
                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
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to