From owner-svn-src-stable-9@freebsd.org Thu Sep 22 10:58:21 2016 Return-Path: Delivered-To: svn-src-stable-9@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id F405EBE5939; Thu, 22 Sep 2016 10:58:20 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C153D148A; Thu, 22 Sep 2016 10:58:20 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u8MAwJMx058467; Thu, 22 Sep 2016 10:58:19 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u8MAwJmu058466; Thu, 22 Sep 2016 10:58:19 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201609221058.u8MAwJmu058466@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Thu, 22 Sep 2016 10:58:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r306183 - stable/9/sys/ufs/ffs X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Sep 2016 10:58:21 -0000 Author: kib Date: Thu Sep 22 10:58:19 2016 New Revision: 306183 URL: https://svnweb.freebsd.org/changeset/base/306183 Log: MFC r305599: Do not leak transient ENOLCK error from flush_newblk_dep() loop. Modified: stable/9/sys/ufs/ffs/ffs_softdep.c Directory Properties: stable/9/ (props changed) stable/9/sys/ (props changed) Modified: stable/9/sys/ufs/ffs/ffs_softdep.c ============================================================================== --- stable/9/sys/ufs/ffs/ffs_softdep.c Thu Sep 22 10:54:30 2016 (r306182) +++ stable/9/sys/ufs/ffs/ffs_softdep.c Thu Sep 22 10:58:19 2016 (r306183) @@ -12577,6 +12577,7 @@ flush_newblk_dep(vp, mp, lbn) LK_INTERLOCK, BO_MTX(bo)); if (error == ENOLCK) { ACQUIRE_LOCK(&lk); + error = 0; continue; /* Slept, retry */ } if (error != 0) From owner-svn-src-stable-9@freebsd.org Thu Sep 22 21:23:29 2016 Return-Path: Delivered-To: svn-src-stable-9@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7F520BE51E1; Thu, 22 Sep 2016 21:23:29 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 37AE7DDB; Thu, 22 Sep 2016 21:23:29 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u8MLNSof001815; Thu, 22 Sep 2016 21:23:28 GMT (envelope-from emaste@FreeBSD.org) Received: (from emaste@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u8MLNS6K001813; Thu, 22 Sep 2016 21:23:28 GMT (envelope-from emaste@FreeBSD.org) Message-Id: <201609222123.u8MLNS6K001813@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: emaste set sender to emaste@FreeBSD.org using -f From: Ed Maste Date: Thu, 22 Sep 2016 21:23:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r306217 - in stable/9/usr.bin/bsdiff: bsdiff bspatch X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Sep 2016 21:23:29 -0000 Author: emaste Date: Thu Sep 22 21:23:28 2016 New Revision: 306217 URL: https://svnweb.freebsd.org/changeset/base/306217 Log: MFC r264823 (ed): Make usage printing more consistent with other tools. - Introduce a separate usage() function. - Don't use argv[0]. Directly name the application, as we do elsewhere. - Don't prepend the application name. - Don't print two newlines. Also apply the unnecessary semicolon cleanup from r298089 Modified: stable/9/usr.bin/bsdiff/bsdiff/bsdiff.c stable/9/usr.bin/bsdiff/bspatch/bspatch.c Directory Properties: stable/9/usr.bin/bsdiff/ (props changed) Modified: stable/9/usr.bin/bsdiff/bsdiff/bsdiff.c ============================================================================== --- stable/9/usr.bin/bsdiff/bsdiff/bsdiff.c Thu Sep 22 21:19:25 2016 (r306216) +++ stable/9/usr.bin/bsdiff/bsdiff/bsdiff.c Thu Sep 22 21:23:28 2016 (r306217) @@ -196,6 +196,14 @@ static void offtout(off_t x,u_char *buf) if(x<0) buf[7]|=0x80; } +static void +usage(void) +{ + + fprintf(stderr, "usage: bsdiff oldfile newfile patchfile\n"); + exit(1); +} + int main(int argc,char *argv[]) { int fd; @@ -216,7 +224,8 @@ int main(int argc,char *argv[]) BZFILE * pfbz2; int bz2err; - if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); + if (argc != 4) + usage(); /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure that we never try to malloc(0) and get a NULL pointer */ Modified: stable/9/usr.bin/bsdiff/bspatch/bspatch.c ============================================================================== --- stable/9/usr.bin/bsdiff/bspatch/bspatch.c Thu Sep 22 21:19:25 2016 (r306216) +++ stable/9/usr.bin/bsdiff/bspatch/bspatch.c Thu Sep 22 21:23:28 2016 (r306217) @@ -57,6 +57,14 @@ static off_t offtin(u_char *buf) return y; } +static void +usage(void) +{ + + fprintf(stderr, "usage: bspatch oldfile newfile patchfile\n"); + exit(1); +} + int main(int argc,char * argv[]) { FILE * f, * cpf, * dpf, * epf; @@ -72,7 +80,8 @@ int main(int argc,char * argv[]) off_t lenread; off_t i; - if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); + if (argc != 4) + usage(); /* Open patch file */ if ((f = fopen(argv[3], "rb")) == NULL) @@ -152,7 +161,7 @@ int main(int argc,char * argv[]) (cbz2err != BZ_STREAM_END))) errx(1, "Corrupt patch\n"); ctrl[i]=offtin(buf); - }; + } /* Sanity-check */ if ((ctrl[0] < 0) || (ctrl[1] < 0)) @@ -190,7 +199,7 @@ int main(int argc,char * argv[]) /* Adjust pointers */ newpos+=ctrl[1]; oldpos+=ctrl[2]; - }; + } /* Clean up the bzip2 reads */ BZ2_bzReadClose(&cbz2err, cpfbz2); From owner-svn-src-stable-9@freebsd.org Fri Sep 23 01:52:07 2016 Return-Path: Delivered-To: svn-src-stable-9@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id BE775BE5F25; Fri, 23 Sep 2016 01:52:07 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 7E24CC2A; Fri, 23 Sep 2016 01:52:07 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u8N1q6ox001864; Fri, 23 Sep 2016 01:52:06 GMT (envelope-from emaste@FreeBSD.org) Received: (from emaste@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u8N1q6D6001863; Fri, 23 Sep 2016 01:52:06 GMT (envelope-from emaste@FreeBSD.org) Message-Id: <201609230152.u8N1q6D6001863@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: emaste set sender to emaste@FreeBSD.org using -f From: Ed Maste Date: Fri, 23 Sep 2016 01:52:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r306222 - stable/9/usr.bin/bsdiff/bspatch X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2016 01:52:07 -0000 Author: emaste Date: Fri Sep 23 01:52:06 2016 New Revision: 306222 URL: https://svnweb.freebsd.org/changeset/base/306222 Log: MFC bspatch Capsicumization and 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. Modified: stable/9/usr.bin/bsdiff/bspatch/bspatch.c Directory Properties: stable/9/usr.bin/bsdiff/ (props changed) Modified: stable/9/usr.bin/bsdiff/bspatch/bspatch.c ============================================================================== --- stable/9/usr.bin/bsdiff/bspatch/bspatch.c Thu Sep 22 23:54:58 2016 (r306221) +++ stable/9/usr.bin/bsdiff/bspatch/bspatch.c Fri Sep 23 01:52:06 2016 (r306222) @@ -27,34 +27,60 @@ #include __FBSDID("$FreeBSD$"); +#if defined(__FreeBSD__) +#include +#if __FreeBSD_version >= 1001511 +#include +#define HAVE_CAPSICUM +#endif +#endif + #include -#include +#include +#include +#include +#include +#include +#include #include +#include #include -#include #include -#include #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); } static void @@ -65,20 +91,23 @@ usage(void) exit(1); } -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) usage(); @@ -86,6 +115,54 @@ int main(int argc,char * argv[]) /* 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: @@ -102,99 +179,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 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=0) && (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]; @@ -209,12 +286,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); } From owner-svn-src-stable-9@freebsd.org Fri Sep 23 07:44:13 2016 Return-Path: Delivered-To: svn-src-stable-9@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id AEC9ABE6FF2; Fri, 23 Sep 2016 07:44:13 +0000 (UTC) (envelope-from delphij@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4B2AC1BAC; Fri, 23 Sep 2016 07:44:13 +0000 (UTC) (envelope-from delphij@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u8N7iCtL034582; Fri, 23 Sep 2016 07:44:12 GMT (envelope-from delphij@FreeBSD.org) Received: (from delphij@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u8N7iBoG034567; Fri, 23 Sep 2016 07:44:11 GMT (envelope-from delphij@FreeBSD.org) Message-Id: <201609230744.u8N7iBoG034567@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: delphij set sender to delphij@FreeBSD.org using -f From: Xin LI Date: Fri, 23 Sep 2016 07:44:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r306229 - in stable/9/crypto/openssl: crypto/bn crypto/dsa crypto/mdc2 ssl X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2016 07:44:13 -0000 Author: delphij Date: Fri Sep 23 07:44:10 2016 New Revision: 306229 URL: https://svnweb.freebsd.org/changeset/base/306229 Log: Fix multiple OpenSSL vulnerabilities. Security: FreeBSD-SA-16:26.openssl Modified: stable/9/crypto/openssl/crypto/bn/bn_print.c stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c stable/9/crypto/openssl/ssl/d1_both.c stable/9/crypto/openssl/ssl/d1_clnt.c stable/9/crypto/openssl/ssl/d1_lib.c stable/9/crypto/openssl/ssl/d1_pkt.c stable/9/crypto/openssl/ssl/d1_srvr.c stable/9/crypto/openssl/ssl/s3_clnt.c stable/9/crypto/openssl/ssl/s3_srvr.c stable/9/crypto/openssl/ssl/ssl.h stable/9/crypto/openssl/ssl/ssl_err.c stable/9/crypto/openssl/ssl/ssl_locl.h stable/9/crypto/openssl/ssl/ssl_sess.c stable/9/crypto/openssl/ssl/t1_lib.c Modified: stable/9/crypto/openssl/crypto/bn/bn_print.c ============================================================================== --- stable/9/crypto/openssl/crypto/bn/bn_print.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/crypto/bn/bn_print.c Fri Sep 23 07:44:10 2016 (r306229) @@ -111,6 +111,7 @@ char *BN_bn2dec(const BIGNUM *a) char *p; BIGNUM *t = NULL; BN_ULONG *bn_data = NULL, *lp; + int bn_data_num; /*- * get an upper bound for the length of the decimal integer @@ -120,8 +121,8 @@ char *BN_bn2dec(const BIGNUM *a) */ i = BN_num_bits(a) * 3; num = (i / 10 + i / 1000 + 1) + 1; - bn_data = - (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG)); + bn_data_num = num / BN_DEC_NUM + 1; + bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); buf = (char *)OPENSSL_malloc(num + 3); if ((buf == NULL) || (bn_data == NULL)) { BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE); @@ -143,7 +144,11 @@ char *BN_bn2dec(const BIGNUM *a) i = 0; while (!BN_is_zero(t)) { *lp = BN_div_word(t, BN_DEC_CONV); + if (*lp == (BN_ULONG)-1) + goto err; lp++; + if (lp - bn_data >= bn_data_num) + goto err; } lp--; /* Modified: stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c ============================================================================== --- stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/crypto/dsa/dsa_ossl.c Fri Sep 23 07:44:10 2016 (r306229) @@ -235,11 +235,13 @@ static int dsa_sign_setup(DSA *dsa, BN_C do if (!BN_rand_range(&k, dsa->q)) goto err; - while (BN_is_zero(&k)) ; + while (BN_is_zero(&k)); + if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { BN_set_flags(&k, BN_FLG_CONSTTIME); } + if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, CRYPTO_LOCK_DSA, dsa->p, ctx)) @@ -252,6 +254,8 @@ static int dsa_sign_setup(DSA *dsa, BN_C if (!BN_copy(&kq, &k)) goto err; + BN_set_flags(&kq, BN_FLG_CONSTTIME); + /* * We do not want timing information to leak the length of k, so we * compute g^k using an equivalent exponent of fixed length. (This @@ -270,6 +274,7 @@ static int dsa_sign_setup(DSA *dsa, BN_C } else { K = &k; } + DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p); if (!BN_mod(r, r, dsa->q, ctx)) Modified: stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c ============================================================================== --- stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/crypto/mdc2/mdc2dgst.c Fri Sep 23 07:44:10 2016 (r306229) @@ -94,7 +94,7 @@ int MDC2_Update(MDC2_CTX *c, const unsig i = c->num; if (i != 0) { - if (i + len < MDC2_BLOCK) { + if (len < MDC2_BLOCK - i) { /* partial block */ memcpy(&(c->data[i]), in, len); c->num += (int)len; Modified: stable/9/crypto/openssl/ssl/d1_both.c ============================================================================== --- stable/9/crypto/openssl/ssl/d1_both.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/d1_both.c Fri Sep 23 07:44:10 2016 (r306229) @@ -543,11 +543,23 @@ static int dtls1_retrieve_buffered_fragm int al; *ok = 0; - item = pqueue_peek(s->d1->buffered_messages); - if (item == NULL) - return 0; + do { + item = pqueue_peek(s->d1->buffered_messages); + if (item == NULL) + return 0; + + frag = (hm_fragment *)item->data; + + if (frag->msg_header.seq < s->d1->handshake_read_seq) { + /* This is a stale message that has been buffered so clear it */ + pqueue_pop(s->d1->buffered_messages); + dtls1_hm_fragment_free(frag); + pitem_free(item); + item = NULL; + frag = NULL; + } + } while (item == NULL); - frag = (hm_fragment *)item->data; /* Don't return if reassembly still in progress */ if (frag->reassembly != NULL) @@ -1335,18 +1347,6 @@ dtls1_retransmit_message(SSL *s, unsigne return ret; } -/* call this function when the buffered messages are no longer needed */ -void dtls1_clear_record_buffer(SSL *s) -{ - pitem *item; - - for (item = pqueue_pop(s->d1->sent_messages); - item != NULL; item = pqueue_pop(s->d1->sent_messages)) { - dtls1_hm_fragment_free((hm_fragment *)item->data); - pitem_free(item); - } -} - unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt, unsigned long len, unsigned long frag_off, Modified: stable/9/crypto/openssl/ssl/d1_clnt.c ============================================================================== --- stable/9/crypto/openssl/ssl/d1_clnt.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/d1_clnt.c Fri Sep 23 07:44:10 2016 (r306229) @@ -564,6 +564,7 @@ int dtls1_connect(SSL *s) /* done with handshaking */ s->d1->handshake_read_seq = 0; s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); goto end; /* break; */ Modified: stable/9/crypto/openssl/ssl/d1_lib.c ============================================================================== --- stable/9/crypto/openssl/ssl/d1_lib.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/d1_lib.c Fri Sep 23 07:44:10 2016 (r306229) @@ -155,7 +155,6 @@ int dtls1_new(SSL *s) static void dtls1_clear_queues(SSL *s) { pitem *item = NULL; - hm_fragment *frag = NULL; DTLS1_RECORD_DATA *rdata; while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) { @@ -176,12 +175,36 @@ static void dtls1_clear_queues(SSL *s) pitem_free(item); } + while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + if (rdata->rbuf.buf) { + OPENSSL_free(rdata->rbuf.buf); + } + OPENSSL_free(item->data); + pitem_free(item); + } + + dtls1_clear_received_buffer(s); + dtls1_clear_sent_buffer(s); +} + +void dtls1_clear_received_buffer(SSL *s) +{ + pitem *item = NULL; + hm_fragment *frag = NULL; + while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) { frag = (hm_fragment *)item->data; OPENSSL_free(frag->fragment); OPENSSL_free(frag); pitem_free(item); } +} + +void dtls1_clear_sent_buffer(SSL *s) +{ + pitem *item = NULL; + hm_fragment *frag = NULL; while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) { frag = (hm_fragment *)item->data; @@ -189,17 +212,9 @@ static void dtls1_clear_queues(SSL *s) OPENSSL_free(frag); pitem_free(item); } - - while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) { - rdata = (DTLS1_RECORD_DATA *)item->data; - if (rdata->rbuf.buf) { - OPENSSL_free(rdata->rbuf.buf); - } - OPENSSL_free(item->data); - pitem_free(item); - } } + void dtls1_free(SSL *s) { ssl3_free(s); @@ -431,7 +446,7 @@ void dtls1_stop_timer(SSL *s) BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); /* Clear retransmission buffer */ - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); } int dtls1_check_timeout_num(SSL *s) Modified: stable/9/crypto/openssl/ssl/d1_pkt.c ============================================================================== --- stable/9/crypto/openssl/ssl/d1_pkt.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/d1_pkt.c Fri Sep 23 07:44:10 2016 (r306229) @@ -124,8 +124,7 @@ static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, int len, int peek); -static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, - PQ_64BIT * seq_num); +static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap); static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap); static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, unsigned int *is_next_epoch); @@ -135,7 +134,7 @@ static int dtls1_record_needs_buffering( unsigned long *offset); #endif static int dtls1_buffer_record(SSL *s, record_pqueue *q, PQ_64BIT * priority); -static int dtls1_process_record(SSL *s); +static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap); #if PQ_64BIT_IS_INTEGER static PQ_64BIT bytes_to_long_long(unsigned char *bytes, PQ_64BIT * num); #endif @@ -248,20 +247,66 @@ static int dtls1_retrieve_buffered_recor static int dtls1_process_buffered_records(SSL *s) { pitem *item; + SSL3_BUFFER *rb; + SSL3_RECORD *rr; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + int replayok = 1; item = pqueue_peek(s->d1->unprocessed_rcds.q); if (item) { /* Check if epoch is current. */ if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch) - return (1); /* Nothing to do. */ + return 1; /* Nothing to do. */ + + rr = &s->s3->rrec; + rb = &s->s3->rbuf; + + if (rb->left > 0) { + /* + * We've still got data from the current packet to read. There could + * be a record from the new epoch in it - so don't overwrite it + * with the unprocessed records yet (we'll do it when we've + * finished reading the current packet). + */ + return 1; + } + /* Process all the records. */ while (pqueue_peek(s->d1->unprocessed_rcds.q)) { dtls1_get_unprocessed_record(s); - if (!dtls1_process_record(s)) - return (0); - dtls1_buffer_record(s, &(s->d1->processed_rcds), - &s->s3->rrec.seq_num); + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + /* + * Should not happen. This will only ever be NULL when the + * current record is from a different epoch. But that cannot + * be the case because we already checked the epoch above + */ + SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, + ERR_R_INTERNAL_ERROR); + return 0; + } + { + /* + * Check whether this is a repeat, or aged record. We did this + * check once already when we first received the record - but + * we might have updated the window since then due to + * records we subsequently processed. + */ + replayok = dtls1_record_replay_check(s, bitmap); + } + + if (!replayok || !dtls1_process_record(s, bitmap)) { + /* dump this record */ + rr->length = 0; + s->packet_length = 0; + continue; + } + + if (dtls1_buffer_record(s, &(s->d1->processed_rcds), + &s->s3->rrec.seq_num) < 0) + return 0; } } @@ -272,7 +317,7 @@ static int dtls1_process_buffered_record s->d1->processed_rcds.epoch = s->d1->r_epoch; s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1; - return (1); + return 1; } #if 0 @@ -319,7 +364,7 @@ static int dtls1_get_buffered_record(SSL #endif -static int dtls1_process_record(SSL *s) +static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap) { int i, al; int enc_err; @@ -478,8 +523,10 @@ static int dtls1_process_record(SSL *s) /* we have pulled in a full packet so zero things */ s->packet_length = 0; - dtls1_record_bitmap_update(s, &(s->d1->bitmap)); /* Mark receipt of - * record. */ + + /* Mark receipt of record. */ + dtls1_record_bitmap_update(s, bitmap); + return (1); f_err: @@ -510,6 +557,7 @@ int dtls1_get_record(SSL *s) rr = &(s->s3->rrec); + again: /* * The epoch may have changed. If so, process all the pending records. * This is a non-blocking operation. @@ -521,7 +569,6 @@ int dtls1_get_record(SSL *s) return 1; /* get something from the wire */ - again: /* check if we have the header */ if ((s->rstate != SSL_ST_READ_BODY) || (s->packet_length < DTLS1_RT_HEADER_LENGTH)) { @@ -620,7 +667,7 @@ int dtls1_get_record(SSL *s) if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE && s->packet_length > DTLS1_RT_HEADER_LENGTH && s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) && - !dtls1_record_replay_check(s, bitmap, &(rr->seq_num))) { + !dtls1_record_replay_check(s, bitmap)) { rr->length = 0; s->packet_length = 0; /* dump this record */ goto again; /* get another record */ @@ -638,14 +685,16 @@ int dtls1_get_record(SSL *s) */ if (is_next_epoch) { if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) { - dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), &rr->seq_num); + if (dtls1_buffer_record + (s, &(s->d1->unprocessed_rcds), &rr->seq_num) < 0) + return -1; } rr->length = 0; s->packet_length = 0; goto again; } - if (!dtls1_process_record(s)) { + if (!dtls1_process_record(s, bitmap)) { rr->length = 0; s->packet_length = 0; /* dump this record */ goto again; /* get another record */ @@ -1514,8 +1563,7 @@ int do_dtls1_write(SSL *s, int type, con return -1; } -static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, - PQ_64BIT * seq_num) +static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap) { #if PQ_64BIT_IS_INTEGER PQ_64BIT mask = 0x0000000000000001L; @@ -1530,7 +1578,7 @@ static int dtls1_record_replay_check(SSL if (pq_64bit_gt(&rcd_num, &(bitmap->max_seq_num)) || pq_64bit_eq(&rcd_num, &(bitmap->max_seq_num))) { - pq_64bit_assign(seq_num, &rcd_num); + pq_64bit_assign(&s->s3->rrec.seq_num, &rcd_num); pq_64bit_free(&rcd_num); pq_64bit_free(&tmp); return 1; /* this record is new */ @@ -1561,7 +1609,7 @@ static int dtls1_record_replay_check(SSL return 0; /* record previously received */ #endif - pq_64bit_assign(seq_num, &rcd_num); + pq_64bit_assign(&s->s3->rrec.seq_num, &rcd_num); pq_64bit_free(&rcd_num); pq_64bit_free(&tmp); return 1; @@ -1687,8 +1735,13 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SS if (rr->epoch == s->d1->r_epoch) return &s->d1->bitmap; - /* Only HM and ALERT messages can be from the next epoch */ + /* + * Only HM and ALERT messages can be from the next epoch and only if we + * have already processed all of the unprocessed records from the last + * epoch + */ else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) && + s->d1->unprocessed_rcds.epoch != s->d1->r_epoch && (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { *is_next_epoch = 1; return &s->d1->next_bitmap; @@ -1776,6 +1829,12 @@ void dtls1_reset_seq_numbers(SSL *s, int memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP)); pq_64bit_init(&(s->d1->next_bitmap.map)); pq_64bit_init(&(s->d1->next_bitmap.max_seq_num)); + + /* + * We must not use any buffered messages received from the previous + * epoch + */ + dtls1_clear_received_buffer(s); } else { seq = s->s3->write_sequence; memcpy(s->d1->last_write_sequence, seq, Modified: stable/9/crypto/openssl/ssl/d1_srvr.c ============================================================================== --- stable/9/crypto/openssl/ssl/d1_srvr.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/d1_srvr.c Fri Sep 23 07:44:10 2016 (r306229) @@ -242,7 +242,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_HELLO_REQ_B: s->shutdown = 0; - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); dtls1_start_timer(s); ret = dtls1_send_hello_request(s); if (ret <= 0) @@ -648,6 +648,7 @@ int dtls1_accept(SSL *s) /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); goto end; /* break; */ Modified: stable/9/crypto/openssl/ssl/s3_clnt.c ============================================================================== --- stable/9/crypto/openssl/ssl/s3_clnt.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/s3_clnt.c Fri Sep 23 07:44:10 2016 (r306229) @@ -931,6 +931,12 @@ int ssl3_get_server_certificate(SSL *s) goto f_err; } for (nc = 0; nc < llen;) { + if (nc + 3 > llen) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } n2l3(p, l); if ((l + nc + 3) > llen) { al = SSL_AD_DECODE_ERROR; @@ -1627,6 +1633,11 @@ int ssl3_get_certificate_request(SSL *s) } for (nc = 0; nc < llen;) { + if (nc + 2 > llen) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG); + goto err; + } n2s(p, l); if ((l + nc + 2) > llen) { if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) Modified: stable/9/crypto/openssl/ssl/s3_srvr.c ============================================================================== --- stable/9/crypto/openssl/ssl/s3_srvr.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/s3_srvr.c Fri Sep 23 07:44:10 2016 (r306229) @@ -819,7 +819,7 @@ int ssl3_get_client_hello(SSL *s) session_length = *(p + SSL3_RANDOM_SIZE); - if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) { + if (SSL3_RANDOM_SIZE + session_length + 1 >= (d + n) - p) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -837,7 +837,7 @@ int ssl3_get_client_hello(SSL *s) /* get the session-id */ j = *(p++); - if (p + j > d + n) { + if ((d + n) - p < j) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -874,14 +874,14 @@ int ssl3_get_client_hello(SSL *s) if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { /* cookie stuff */ - if (p + 1 > d + n) { + if ((d + n) - p < 1) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; } cookie_len = *(p++); - if (p + cookie_len > d + n) { + if ((d + n ) - p < cookie_len) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -927,7 +927,7 @@ int ssl3_get_client_hello(SSL *s) p += cookie_len; } - if (p + 2 > d + n) { + if ((d + n ) - p < 2) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -941,7 +941,7 @@ int ssl3_get_client_hello(SSL *s) } /* i bytes of cipher data + 1 byte for compression length later */ - if ((p + i + 1) > (d + n)) { + if ((d + n) - p < i + 1) { /* not enough data */ al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); @@ -1007,7 +1007,7 @@ int ssl3_get_client_hello(SSL *s) /* compression */ i = *(p++); - if ((p + i) > (d + n)) { + if ((d + n) - p < i) { /* not enough data */ al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); @@ -1029,7 +1029,7 @@ int ssl3_get_client_hello(SSL *s) #ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ if (s->version >= SSL3_VERSION) { - if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) { + if (!ssl_parse_clienthello_tlsext(s, &p, d + n, &al)) { /* 'al' set by ssl_parse_clienthello_tlsext */ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT); goto f_err; @@ -2526,6 +2526,12 @@ int ssl3_get_client_certificate(SSL *s) goto f_err; } for (nc = 0; nc < llen;) { + if (nc + 3 > llen) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } n2l3(p, l); if ((l + nc + 3) > llen) { al = SSL_AD_DECODE_ERROR; Modified: stable/9/crypto/openssl/ssl/ssl.h ============================================================================== --- stable/9/crypto/openssl/ssl/ssl.h Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/ssl.h Fri Sep 23 07:44:10 2016 (r306229) @@ -1803,6 +1803,7 @@ void ERR_load_SSL_strings(void); # define SSL_F_DTLS1_HANDLE_TIMEOUT 282 # define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255 # define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277 +# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424 # define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256 # define SSL_F_DTLS1_PROCESS_RECORD 257 # define SSL_F_DTLS1_READ_BYTES 258 Modified: stable/9/crypto/openssl/ssl/ssl_err.c ============================================================================== --- stable/9/crypto/openssl/ssl/ssl_err.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/ssl_err.c Fri Sep 23 07:44:10 2016 (r306229) @@ -1,6 +1,6 @@ /* ssl/ssl_err.c */ /* ==================================================================== - * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2016 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -92,6 +92,8 @@ static ERR_STRING_DATA SSL_str_functs[] {ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT), "DTLS1_HANDLE_TIMEOUT"}, {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"}, {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"}, + {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS), + "DTLS1_PROCESS_BUFFERED_RECORDS"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE), "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"}, Modified: stable/9/crypto/openssl/ssl/ssl_locl.h ============================================================================== --- stable/9/crypto/openssl/ssl/ssl_locl.h Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/ssl_locl.h Fri Sep 23 07:44:10 2016 (r306229) @@ -910,7 +910,8 @@ int dtls1_retransmit_message(SSL *s, uns unsigned long frag_off, int *found); int dtls1_get_queue_priority(unsigned short seq, int is_ccs); int dtls1_retransmit_buffered_messages(SSL *s); -void dtls1_clear_record_buffer(SSL *s); +void dtls1_clear_received_buffer(SSL *s); +void dtls1_clear_sent_buffer(SSL *s); void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr); void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr); @@ -1022,7 +1023,7 @@ unsigned char *ssl_add_clienthello_tlsex unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, - unsigned char *d, int n, int *al); + unsigned char *limit, int *al); int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al); int ssl_prepare_clienthello_tlsext(SSL *s); Modified: stable/9/crypto/openssl/ssl/ssl_sess.c ============================================================================== --- stable/9/crypto/openssl/ssl/ssl_sess.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/ssl_sess.c Fri Sep 23 07:44:10 2016 (r306229) @@ -384,7 +384,7 @@ int ssl_get_prev_session(SSL *s, unsigne if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) goto err; - if (session_id + len > limit) { + if (limit - session_id < len) { fatal = 1; goto err; } Modified: stable/9/crypto/openssl/ssl/t1_lib.c ============================================================================== --- stable/9/crypto/openssl/ssl/t1_lib.c Fri Sep 23 07:41:23 2016 (r306228) +++ stable/9/crypto/openssl/ssl/t1_lib.c Fri Sep 23 07:44:10 2016 (r306229) @@ -357,7 +357,7 @@ unsigned char *ssl_add_serverhello_tlsex * 10.8..10.8.3 (which don't work). */ static void ssl_check_for_safari(SSL *s, const unsigned char *data, - const unsigned char *d, int n) + const unsigned char *limit) { unsigned short type, size; static const unsigned char kSafariExtensionsBlock[] = { @@ -386,11 +386,11 @@ static void ssl_check_for_safari(SSL *s, 0x02, 0x03, /* SHA-1/ECDSA */ }; - if (data >= (d + n - 2)) + if (limit - data <= 2) return; data += 2; - if (data > (d + n - 4)) + if (limit - data < 4) return; n2s(data, type); n2s(data, size); @@ -398,7 +398,7 @@ static void ssl_check_for_safari(SSL *s, if (type != TLSEXT_TYPE_server_name) return; - if (data + size > d + n) + if (limit - data < size) return; data += size; @@ -406,7 +406,7 @@ static void ssl_check_for_safari(SSL *s, const size_t len1 = sizeof(kSafariExtensionsBlock); const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock); - if (data + len1 + len2 != d + n) + if (limit - data != (int)(len1 + len2)) return; if (memcmp(data, kSafariExtensionsBlock, len1) != 0) return; @@ -415,7 +415,7 @@ static void ssl_check_for_safari(SSL *s, } else { const size_t len = sizeof(kSafariExtensionsBlock); - if (data + len != d + n) + if (limit - data != (int)(len)) return; if (memcmp(data, kSafariExtensionsBlock, len) != 0) return; @@ -425,8 +425,8 @@ static void ssl_check_for_safari(SSL *s, } # endif /* !OPENSSL_NO_EC */ -int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, - int n, int *al) +int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, + unsigned char *limit, int *al) { unsigned short type; unsigned short size; @@ -439,24 +439,26 @@ int ssl_parse_clienthello_tlsext(SSL *s, # ifndef OPENSSL_NO_EC if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG) - ssl_check_for_safari(s, data, d, n); + ssl_check_for_safari(s, data, limit); # endif /* !OPENSSL_NO_EC */ - if (data >= (d + n - 2)) + if (data == limit) goto ri_check; + if (limit - data < 2) + goto err; + n2s(data, len); - if (data > (d + n - len)) - goto ri_check; + if (limit - data != len) + goto err; - while (data <= (d + n - 4)) { + while (limit - data >= 4) { n2s(data, type); n2s(data, size); - if (data + size > (d + n)) - goto ri_check; - + if (limit - data < size) + goto err; if (s->tlsext_debug_cb) s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg); /*- @@ -580,6 +582,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, *al = SSL_AD_DECODE_ERROR; return 0; } + + /* + * We remove any OCSP_RESPIDs from a previous handshake + * to prevent unbounded memory growth - CVE-2016-6304 + */ + sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, + OCSP_RESPID_free); + if (dsize > 0) { + s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null(); + if (s->tlsext_ocsp_ids == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + return 0; + } + } else { + s->tlsext_ocsp_ids = NULL; + } + while (dsize > 0) { OCSP_RESPID *id; int idsize; @@ -606,13 +625,6 @@ int ssl_parse_clienthello_tlsext(SSL *s, *al = SSL_AD_DECODE_ERROR; return 0; } - if (!s->tlsext_ocsp_ids - && !(s->tlsext_ocsp_ids = - sk_OCSP_RESPID_new_null())) { - OCSP_RESPID_free(id); - *al = SSL_AD_INTERNAL_ERROR; - return 0; - } if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) { OCSP_RESPID_free(id); *al = SSL_AD_INTERNAL_ERROR; @@ -672,6 +684,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, } return 1; + +err: + *al = SSL_AD_DECODE_ERROR; + return 0; } int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, @@ -684,20 +700,20 @@ int ssl_parse_serverhello_tlsext(SSL *s, int tlsext_servername = 0; int renegotiate_seen = 0; - if (data >= (d + n - 2)) + if ((d + n) - data <= 2) goto ri_check; n2s(data, length); - if (data + length != d + n) { + if ((d + n) - data != length) { *al = SSL_AD_DECODE_ERROR; return 0; } - while (data <= (d + n - 4)) { + while ((d + n) - data >= 4) { n2s(data, type); n2s(data, size); - if (data + size > (d + n)) + if ((d + n) - data < size) goto ri_check; if (s->tlsext_debug_cb) @@ -960,29 +976,33 @@ int tls1_process_ticket(SSL *s, unsigned /* Skip past DTLS cookie */ if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { i = *(p++); - p += i; - if (p >= limit) + + if (limit - p <= i) return -1; + + p += i; } /* Skip past cipher list */ n2s(p, i); - p += i; - if (p >= limit) + if (limit - p <= i) return -1; + p += i; + /* Skip past compression algorithm list */ i = *(p++); - p += i; - if (p > limit) + if (limit - p < i) return -1; + p += i; + /* Now at start of extensions */ - if ((p + 2) >= limit) + if (limit - p <= 2) return 1; n2s(p, i); - while ((p + 4) <= limit) { + while (limit - p >= 4) { unsigned short type, size; n2s(p, type); n2s(p, size); - if (p + size > limit) + if (limit - p < size) return 1; if (type == TLSEXT_TYPE_session_ticket) { /* @@ -1012,9 +1032,7 @@ static int tls_decrypt_ticket(SSL *s, co HMAC_CTX hctx; EVP_CIPHER_CTX ctx; SSL_CTX *tctx = s->initial_ctx; - /* Need at least keyname + iv + some encrypted data */ - if (eticklen < 48) - goto tickerr; + /* Initialize session ticket encryption and HMAC contexts */ HMAC_CTX_init(&hctx); EVP_CIPHER_CTX_init(&ctx); @@ -1042,6 +1060,13 @@ static int tls_decrypt_ticket(SSL *s, co * checks on ticket. */ mlen = HMAC_size(&hctx); + /* Sanity check ticket length: must exceed keyname + IV + HMAC */ + if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) { + HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_cleanup(&ctx); + return 2; + } + eticklen -= mlen; /* Check HMAC of encrypted ticket */ HMAC_Update(&hctx, etick, eticklen);