diff --git a/share/security/advisories/FreeBSD-SA-14:27.stdio.asc b/share/security/advisories/FreeBSD-SA-14:27.stdio.asc new file mode 100644 index 0000000000..fdc36a51e8 --- /dev/null +++ b/share/security/advisories/FreeBSD-SA-14:27.stdio.asc @@ -0,0 +1,126 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-14:27.stdio Security Advisory + The FreeBSD Project + +Topic: Buffer overflow in stdio + +Category: core +Module: libc +Announced: 2014-12-10 +Credits: Adrian Chadd and Alfred Perlstein, Norse Corporation +Affects: FreeBSD 10.1 +Corrected: 2014-12-10 08:24:02 UTC (stable/10, 10.1-STABLE) + 2014-12-10 08:35:55 UTC (releng/10.1, 10.1-RELEASE-p1) +CVE Name: CVE-2014-8611 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit . + +I. Background + +The standard I/O library provides a simple and efficient buffered stream +I/O interface. The library writes buffered data when it is full or when +the application explicitly request so by calling the fflush(3) function. + +II. Problem Description + +A programming error in the standard I/O library's __sflush() function could +erroneously adjust the buffered stream's internal state even when no write +actually occurred in the case when write(2) system call returns an error. + +III. Impact + +The accounting mismatch would accumulate, if the caller does not check for +stream status and will eventually lead to a heap buffer overflow. + +Such overflows may lead to data corruption or the execution of arbitrary +code at the privilege level of the calling program. + +IV. Workaround + +No workaround is available. + +V. Solution + +Perform one of the following: + +1) Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +2) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch http://security.FreeBSD.org/patches/SA-14:27/stdio.patch +# fetch http://security.FreeBSD.org/patches/SA-14:27/stdio.patch.asc +# gpg --verify stdio.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in . + +Reboot the system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/10/ r275667 +releng/10.1/ r275670 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + + + +VII. References + + + +The latest revision of this advisory is available at + +-----BEGIN PGP SIGNATURE----- + +iQIcBAEBCgAGBQJUiA11AAoJEO1n7NZdz2rnZLMP/ic0j0lykvkZ4x39Th4vUIX7 +SCqROB8zxKj8qA3QlXhusaJA9o9hAPX8HA99ZVbDyugz0m4ST0t6JAYL+w3eVYZm +RpEszshxi7rwUXaoue99lk0JnP2ssZbNZn5y4Z0XCYvingfP7Um6tOG0XqUs+N45 +Mivhuz+JKaFSYG4WwrSIr2pNpn6XnDeGoihtuXOkinBv8Ga3xHyuTY+30vUnEEH+ +Vr2MftHMm3Wo87OM1XhrTQS5jYzD8u0xgwKjcf0/+6Q+iXzLDkk8MfCE1W9SP7FE +zas1MHxWeV5AICAX0CUI/9R2Zgymi/xJksw4BNZsDyGnOvIRdcMv+0KOWnCn42mk +HCm2NTyvUM2Cgjbj5T4yICQBEi5dI6WiTp2yKTKQOiqDsszUW1NyqGQdYPfyjjMS +kQA5RTdGVxwxp8FMnJGvYdlVRZgx5BAI8znhlxxqKs25uhbOnn+zKm+rA2XnLLMk +sg2V/E906vldjLw8ddvNKm5oy0UkezBj0J1NOgkpN3atvUB8X2H251h2n51+oAbE +FSd4qqN70vwHdOmIGNrjWZpOqSJzeGs5JjbaxMpo6MoIWJz2zrK2WLiFVWZGohgh +9TGU6Ubs/yTLLfu1jTDAMl1dbZd1lChmycKRuqTpe56keOlHghquCMxhogWY0PQE +nE47N3BP/KCtuQw1uxuK +=F9uH +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-SA-14:28.file.asc b/share/security/advisories/FreeBSD-SA-14:28.file.asc new file mode 100644 index 0000000000..915d5ab8b3 --- /dev/null +++ b/share/security/advisories/FreeBSD-SA-14:28.file.asc @@ -0,0 +1,157 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-14:28.file Security Advisory + The FreeBSD Project + +Topic: Multiple vulnerabilities in file(1) and libmagic(3) + +Category: contrib +Module: file +Announced: 2014-12-10 +Affects: All supported versions of FreeBSD. +Credits: Thomas Jarosch of Intra2net AG +Corrected: 2014-12-10 08:26:53 UTC (stable/10, 10.1-STABLE) + 2014-12-10 08:35:55 UTC (releng/10.1, 10.1-RELEASE-p1) + 2014-12-10 08:36:07 UTC (releng/10.0, 10.0-RELEASE-p13) + 2014-12-10 08:31:41 UTC (stable/9, 9.3-STABLE) + 2014-12-10 08:36:40 UTC (releng/9.3, 9.3-RELEASE-p6) + 2014-12-10 08:36:40 UTC (releng/9.2, 9.2-RELEASE-p16) + 2014-12-10 08:36:40 UTC (releng/9.1, 9.1-RELEASE-p23) + 2014-12-10 08:31:41 UTC (stable/8, 8.4-STABLE) + 2014-12-10 08:36:40 UTC (releng/8.4, 8.4-RELEASE-p20) +CVE Name: CVE-2014-3710, CVE-2014-8116, CVE-2014-8117 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit . + +I. Background + +The file(1) utility attempts to classify file system objects based on +filesystem, magic number and language tests. + +The libmagic(3) library provides most of the functionality of file(1) +and may be used by other applications. + +II. Problem Description + +There are a number of denial of service issues in the ELF parser used +by file(1). + +III. Impact + +An attacker who can cause file(1) or any other applications using the +libmagic(3) library to be run on a maliciously constructed input can +cause the application to crash or consume excessive CPU resources, +resulting in a denial-of-service. + +IV. Workaround + +No workaround is available, but systems where file(1) and other +libmagic(3)-using applications are never run on untrusted input are not +vulnerable. + +V. Solution + +Perform one of the following: + +1) Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +2) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 10.1] +# fetch http://security.FreeBSD.org/patches/SA-14:28/file-12.patch +# fetch http://security.FreeBSD.org/patches/SA-14:28/file-12.patch.asc +# gpg --verify file-12.patch.asc + +[FreeBSD 9.1, 9.2, 9.3 and 10.0] +# fetch http://security.FreeBSD.org/patches/SA-14:28/file-8.patch +# fetch http://security.FreeBSD.org/patches/SA-14:28/file-8.patch.asc +# gpg --verify file-8.patch.asc + +[FreeBSD 8.4] +# fetch http://security.FreeBSD.org/patches/SA-14:28/file-7.patch +# fetch http://security.FreeBSD.org/patches/SA-14:28/file-7.patch.asc +# gpg --verify file-7.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in . + +Restart all deamons using the library, or reboot the system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/8/ r275669 +releng/8.4/ r275672 +stable/9/ r275669 +releng/9.1/ r275672 +releng/9.2/ r275672 +releng/9.3/ r275672 +stable/10/ r275668 +releng/10.0/ r275671 +releng/10.1/ r275670 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + + + +VII. References + + + + + + + +The latest revision of this advisory is available at + +-----BEGIN PGP SIGNATURE----- + +iQIcBAEBCgAGBQJUiA11AAoJEO1n7NZdz2rnCBMQAL/22vlzYOuAilNqQu5SZCZ8 +i+VVrq9ZQv9Q32JiSs/eZtiz8d1OrhZK86a6dzx2vd5cV3QjWTOh5oK00gnO6Nq1 +g1tqRDYVSzoPBVNLkpH0gKJjUNcxhzehQy2oge+7mtkcj3RsIX9MrPDpagIwdlOm +KOHlfHL5w3sVbXvA9hqASH6GkvWKaj/QRm9wyHitVHYI9EbJE6jAyeDfzR1sFP54 +f4FkT3TtsVw712+TYkC/EmgyPA8R6tK08LpYsa0pnwCtuMUkT+/zmDhcjXEyqZ0X +cimkXyANSyDxzFjNrec0ETno35a5dNeasZvRg8DZXAGko9ainwUKTk5p+AUiKUOh +MGxCFCkAPK/jbzBfZmQ7WMwpEDpjCxKK/C1qM2hHmpXwodzMtxSONicomcQrHm3O +f2C1JWIy7V8pLZDVN8Ce25JLjDRt+cZc6JR2sICrfAjUWXRyCbmIsTj/+CjLHH1a +/8hXs/TI0Z4jvcPsujoo7GhOdXvLz4Z7bY9cdZgEmZaUw+OwPN3DGiUEkK1+VNNt +ClufF6cHWE9UaUp26fjoZ/qVTFt/ixIy7Qsx9EqA1YrnemI9mOxgxTFB1jqMM6uR +NGEFUsyUQWLJxpinrEJIvJj5r9lQw11GaqsvyOyZ8IzPLJ31okYUXUFiFUECI+aN +P0XVV9PyCfdO6tq8ajOi +=+w7r +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-SA-14:29.bind.asc b/share/security/advisories/FreeBSD-SA-14:29.bind.asc new file mode 100644 index 0000000000..564e86e5a4 --- /dev/null +++ b/share/security/advisories/FreeBSD-SA-14:29.bind.asc @@ -0,0 +1,158 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-SA-14:29.bind Security Advisory + The FreeBSD Project + +Topic: BIND remote denial of service vulnerability + +Category: contrib +Module: bind +Announced: 2014-12-10 +Credits: ISC +Affects: FreeBSD 8.4, 9.1, 9.2 and 9.3. +Corrected: 2014-12-10 08:31:41 UTC (stable/9, 9.3-STABLE) + 2014-12-10 08:36:40 UTC (releng/9.3, 9.3-RELEASE-p6) + 2014-12-10 08:36:40 UTC (releng/9.2, 9.2-RELEASE-p16) + 2014-12-10 08:36:40 UTC (releng/9.1, 9.1-RELEASE-p23) + 2014-12-10 08:31:41 UTC (stable/8, 8.4-STABLE) + 2014-12-10 08:36:40 UTC (releng/8.4, 8.4-RELEASE-p20) +CVE Name: CVE-2014-8500 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit . + +I. Background + +BIND 9 is an implementation of the Domain Name System (DNS) protocols. +The named(8) daemon is an Internet Domain Name Server. + +II. Problem Description + +By causing queries to be made against a maliciously-constructed zone or +against a malicious DNS server, an attacker who is able to cause +specific queries to be sent to a nameserver can cause named(8) to +crash, leading to a denial of service. + +All recursive BIND DNS servers are vulnerable to this. Authoritative +servers are only vulnerable if the attacker is able to control a +delegation traversed by the authoritative server in order to serve +the zone. + +III. Impact + +An attacker who can cause specific queries to be sent to a nameserver +could cause named(8) to crash, resulting in a denial of service. + +IV. Workaround + +No workaround is available, but hosts not running named(8) are not +vulnerable. + +V. Solution + +Perform one of the following: + +1) Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +2) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 9.3-RELEASE and 9.3-STABLE] +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind995.patch +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind995.patch.asc +# gpg --verify bind995.patch.asc + +[FreeBSD 9.2-RELEASE] +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind984.patch +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind984.patch.asc +# gpg --verify bind984.patch.asc + +[FreeBSD 9.1-RELEASE] +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind983.patch +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind983.patch.asc +# gpg --verify bind983.patch.asc + +[FreeBSD 8.4-STABLE] +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind987.patch +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind987.patch.asc +# gpg --verify bind987.patch.asc + +[FreeBSD 8.4-RELEASE] +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind984.patch +# fetch http://security.FreeBSD.org/patches/SA-14:29/bind984.patch.asc +# gpg --verify bind984.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in . + +Restart the applicable daemons, or reboot the system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/8/ r275669 +releng/8.4/ r275672 +stable/9/ r275669 +releng/9.1/ r275672 +releng/9.2/ r275672 +releng/9.3/ r275672 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + + + +VII. References + + + +The latest revision of this advisory is available at + +-----BEGIN PGP SIGNATURE----- + +iQIcBAEBCgAGBQJUiA11AAoJEO1n7NZdz2rn7kgP/RWw0Q9dx8/xS+NSypV3Hfqr +6D4Zh8LGsrKuWMGD29MYrFle2Ze5gUfjOFfaqonD2P5vyrCfnyVUhGiIRUKcFn/z +dF6XwWKoZHRRHxNL7d71ZRwG3o4gEJP0SWFbfIVUg0YCDdwpChASyHJkXR5rgrTB +6MFDdeNGq+NzQzESmJJyLT/hgWZB0p/g5tLnez+XNxxk4oGywJlNACEq9SfD618Q +86Pl7oFJjaKrAtb7kzI2tYG+UvUHdQriRwo9C87fnSH4TNf2G1VwVoV0Lip45w4I +MwJ8j4U3Vqr8cepqc6HSZauIA7N3N1Key7qzcnEP56iIfM1yIg+k7FTeaGM7tw45 +lxlrxgLDBpFt+F24cnROagNFZ8o2iWsnaH9ZhEkV6Qabu7eU/XjwKwY9evqqPgeP +bCFZeFCxl4DSNTgkLmP+GjXoRxXQ2NokboU7o+KnZGPnxduDK9RG4yx0IvQc3uyv +ad+zW4luYGuuIwVXiHif8y7SnOrp4LiVIX04isavaBVSndWC4VenlajoH8IvYxIW +P/Bc8J0qxPmEJzZmutzLNQEDEHnxz3o9s/6C7FSASRkMMJ7QXvq0bIdVpkubh0bE +PqJVu6WN2KD6tKjuZq4P/WVrRedsRG+qDYb819guIok2kGa6A4tgQ/DAvuZur+do +K3JRKm1SZmozOqV/SVmy +=uNWP +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:27/stdio.patch b/share/security/patches/SA-14:27/stdio.patch new file mode 100644 index 0000000000..e22504215e --- /dev/null +++ b/share/security/patches/SA-14:27/stdio.patch @@ -0,0 +1,22 @@ +Index: lib/libc/stdio/fflush.c +=================================================================== +--- lib/libc/stdio/fflush.c.orig ++++ lib/libc/stdio/fflush.c +@@ -124,11 +124,13 @@ + t = _swrite(fp, (char *)p, n); + if (t <= 0) { + /* Reset _p and _w. */ +- if (p > fp->_p) /* Some was written. */ ++ if (p > fp->_p) { ++ /* Some was written. */ + memmove(fp->_p, p, n); +- fp->_p += n; +- if ((fp->_flags & (__SLBF | __SNBF)) == 0) +- fp->_w -= n; ++ fp->_p += n; ++ if ((fp->_flags & (__SLBF | __SNBF)) == 0) ++ fp->_w -= n; ++ } + fp->_flags |= __SERR; + return (EOF); + } diff --git a/share/security/patches/SA-14:27/stdio.patch.asc b/share/security/patches/SA-14:27/stdio.patch.asc new file mode 100644 index 0000000000..42f6b97ebd --- /dev/null +++ b/share/security/patches/SA-14:27/stdio.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2QAAoJEO1n7NZdz2rnM3AP/0HoTCXA+hqUYQ3RuFXQJYLr +2/cbSEiMvfB40rvB9T7WvZYsiWJN+V0R1yMRDu2uF4KJB6Au5GGNzdeG742yU3B4 +W2IVFtCMST0DlsGuUQV/zXeMhQiwXZx0cP5iIoukeyf/vZ7+p8b+WObB81D6+gPf +tBlRG5cHc3eX+SGXzhbpuUQrG35KtFA0JijLIAy2criCFo+nN6iRBnVa5Uk0X3hx +p7lRK7G9tY9fQX3Z7BqoOHxBWC1YNJEWrzkLMVWUmowXMOWvcyab6k/kwtfVCrV0 +ZilEOukghDLhzeL9oeRCgQioMHjST4wi34n7ouU6mKb+IzouyPrR42Qfax3u7Lke +ndDauZU3G1D46+D7/O6lLpQWK8g5AYk9AL/PPDr2ewYQrxYRNchaZUdIHz9gNnud +HITnxYsRa3/ArooIti9wF2vsqM/iuzIJ7BEGntEFsCtQgLjMUnl0Hx+Gnu+cg3aj +Liy+bPXqtRhZdbGRVQyoFKeWjjbvwzBx692hBXqjWRhmPIWvggLHSP6o30qpsZmT +dJNmC2m5TBFaJOpQSaq6fk6ExPKVSMjQX/IrY22IfKZ+FN1tHXsnf2l3PcZEdjd/ +PgdNjNX9EP0Pp5GzND87ooe3Z+kJewzSdWNHTpT0i6ljhH/AaJbq5VYAVlx2B/9K +ctb+fAKvwGuyGGzZdibE +=3A4p +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:28/file-12.patch b/share/security/patches/SA-14:28/file-12.patch new file mode 100644 index 0000000000..358f23c181 --- /dev/null +++ b/share/security/patches/SA-14:28/file-12.patch @@ -0,0 +1,288 @@ +Index: contrib/file/src/elfclass.h +=================================================================== +--- contrib/file/src/elfclass.h.orig ++++ contrib/file/src/elfclass.h +@@ -35,10 +35,12 @@ + switch (type) { + #ifdef ELFCORE + case ET_CORE: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > MAX_PHNUM) ++ return toomany(ms, "program", phnum); + flags |= FLAGS_IS_CORE; + if (dophn_core(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), + fsize, &flags) == -1) + return -1; +@@ -46,18 +48,24 @@ + #endif + case ET_EXEC: + case ET_DYN: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > MAX_PHNUM) ++ return toomany(ms, "program", phnum); ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > MAX_SHNUM) ++ return toomany(ms, "section", shnum); + if (dophn_exec(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), +- fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) +- == -1) ++ fsize, &flags, shnum) == -1) + return -1; + /*FALLTHROUGH*/ + case ET_REL: ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > MAX_SHNUM) ++ return toomany(ms, "section", shnum); + if (doshn(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_shoff), +- elf_getu16(swap, elfhdr.e_shnum), ++ (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, + (size_t)elf_getu16(swap, elfhdr.e_shentsize), + fsize, &flags, elf_getu16(swap, elfhdr.e_machine), + (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1) +Index: contrib/file/src/file.h +=================================================================== +--- contrib/file/src/file.h.orig ++++ contrib/file/src/file.h +@@ -482,6 +482,14 @@ + protected void file_regfree(file_regex_t *); + protected void file_regerror(file_regex_t *, int, struct magic_set *); + ++typedef struct { ++ char *buf; ++ uint32_t offset; ++} file_pushbuf_t; ++ ++protected file_pushbuf_t *file_push_buffer(struct magic_set *); ++protected char *file_pop_buffer(struct magic_set *, file_pushbuf_t *); ++ + #ifndef COMPILE_ONLY + extern const char *file_names[]; + extern const size_t file_nnames; +Index: contrib/file/src/funcs.c +=================================================================== +--- contrib/file/src/funcs.c.orig ++++ contrib/file/src/funcs.c +@@ -491,3 +491,43 @@ + file_magerror(ms, "regex error %d for `%s', (%s)", rc, rx->pat, + errmsg); + } ++ ++protected file_pushbuf_t * ++file_push_buffer(struct magic_set *ms) ++{ ++ file_pushbuf_t *pb; ++ ++ if (ms->event_flags & EVENT_HAD_ERR) ++ return NULL; ++ ++ if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL) ++ return NULL; ++ ++ pb->buf = ms->o.buf; ++ pb->offset = ms->offset; ++ ++ ms->o.buf = NULL; ++ ms->offset = 0; ++ ++ return pb; ++} ++ ++protected char * ++file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) ++{ ++ char *rbuf; ++ ++ if (ms->event_flags & EVENT_HAD_ERR) { ++ free(pb->buf); ++ free(pb); ++ return NULL; ++ } ++ ++ rbuf = ms->o.buf; ++ ++ ms->o.buf = pb->buf; ++ ms->offset = pb->offset; ++ ++ free(pb); ++ return rbuf; ++} +Index: contrib/file/src/readelf.c +=================================================================== +--- contrib/file/src/readelf.c.orig ++++ contrib/file/src/readelf.c +@@ -60,6 +60,18 @@ + private uint32_t getu32(int, uint32_t); + private uint64_t getu64(int, uint64_t); + ++#define MAX_PHNUM 256 ++#define MAX_SHNUM 1024 ++ ++private int ++toomany(struct magic_set *ms, const char *name, uint16_t num) ++{ ++ if (file_printf(ms, ", too many %s header sections (%u)", name, num ++ ) == -1) ++ return -1; ++ return 0; ++} ++ + private uint16_t + getu16(int swap, uint16_t value) + { +@@ -477,6 +489,13 @@ + uint32_t namesz, descsz; + unsigned char *nbuf = CAST(unsigned char *, vbuf); + ++ if (xnh_sizeof + offset > size) { ++ /* ++ * We're out of note headers. ++ */ ++ return xnh_sizeof + offset; ++ } ++ + (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); + offset += xnh_sizeof; + +@@ -492,13 +511,13 @@ + if (namesz & 0x80000000) { + (void)file_printf(ms, ", bad note name size 0x%lx", + (unsigned long)namesz); +- return offset; ++ return 0; + } + + if (descsz & 0x80000000) { + (void)file_printf(ms, ", bad note description size 0x%lx", + (unsigned long)descsz); +- return offset; ++ return 0; + } + + +@@ -900,6 +919,7 @@ + Elf32_Shdr sh32; + Elf64_Shdr sh64; + int stripped = 1; ++ size_t nbadcap = 0; + void *nbuf; + off_t noff, coff, name_off; + uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ +@@ -988,6 +1008,8 @@ + goto skip; + } + ++ if (nbadcap > 5) ++ break; + if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) { + file_badseek(ms); + return -1; +@@ -1053,6 +1075,8 @@ + (unsigned long long)xcap_tag, + (unsigned long long)xcap_val) == -1) + return -1; ++ if (nbadcap++ > 2) ++ coff = xsh_size; + break; + } + } +@@ -1233,7 +1257,7 @@ + int flags = 0; + Elf32_Ehdr elf32hdr; + Elf64_Ehdr elf64hdr; +- uint16_t type; ++ uint16_t type, phnum, shnum; + + if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) + return 0; +Index: contrib/file/src/softmagic.c +=================================================================== +--- contrib/file/src/softmagic.c.orig ++++ contrib/file/src/softmagic.c +@@ -67,6 +67,9 @@ + private void cvt_64(union VALUETYPE *, const struct magic *); + + #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) ++ ++#define MAX_RECURSION_LEVEL 10 ++ + /* + * softmagic - lookup one file in parsed, in-memory copy of database + * Passed the name and FILE * of one file to be typed. +@@ -1193,14 +1196,15 @@ + int flip, int recursion_level, int *printed_something, + int *need_separator, int *returnval) + { +- uint32_t soffset, offset = ms->offset; ++ uint32_t offset = ms->offset; + uint32_t lhs; ++ file_pushbuf_t *pb; + int rv, oneed_separator, in_type; +- char *sbuf, *rbuf; ++ char *rbuf; + union VALUETYPE *p = &ms->ms_value; + struct mlist ml; + +- if (recursion_level >= 20) { ++ if (recursion_level >= MAX_RECURSION_LEVEL) { + file_error(ms, 0, "recursion nesting exceeded"); + return -1; + } +@@ -1644,19 +1648,23 @@ + case FILE_INDIRECT: + if (offset == 0) + return 0; ++ + if (nbytes < offset) + return 0; +- sbuf = ms->o.buf; +- soffset = ms->offset; +- ms->o.buf = NULL; +- ms->offset = 0; ++ ++ if ((pb = file_push_buffer(ms)) == NULL) ++ return -1; ++ + rv = file_softmagic(ms, s + offset, nbytes - offset, + recursion_level, BINTEST, text); ++ + if ((ms->flags & MAGIC_DEBUG) != 0) + fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); +- rbuf = ms->o.buf; +- ms->o.buf = sbuf; +- ms->offset = soffset; ++ ++ rbuf = file_pop_buffer(ms, pb); ++ if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR) ++ return -1; ++ + if (rv == 1) { + if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && + file_printf(ms, F(ms, m, "%u"), offset) == -1) { +@@ -1674,13 +1682,13 @@ + case FILE_USE: + if (nbytes < offset) + return 0; +- sbuf = m->value.s; +- if (*sbuf == '^') { +- sbuf++; ++ rbuf = m->value.s; ++ if (*rbuf == '^') { ++ rbuf++; + flip = !flip; + } +- if (file_magicfind(ms, sbuf, &ml) == -1) { +- file_error(ms, 0, "cannot find entry `%s'", sbuf); ++ if (file_magicfind(ms, rbuf, &ml) == -1) { ++ file_error(ms, 0, "cannot find entry `%s'", rbuf); + return -1; + } + diff --git a/share/security/patches/SA-14:28/file-12.patch.asc b/share/security/patches/SA-14:28/file-12.patch.asc new file mode 100644 index 0000000000..b8e4acd256 --- /dev/null +++ b/share/security/patches/SA-14:28/file-12.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2QAAoJEO1n7NZdz2rnjzAQANogueUdUbRBgn+EYwcnKUgQ +8y4P5VDNnAIxKrPCRGpRF9IvGaxAzO62y/GlZ6Fq+H+VFk+1poCIXDY3escUM0uk +BM/V+k3wuvsaefTiNIfTMEOYiJ81nrcMZ5cDtO4wgN1Pem44Lmh8O3gztAMSGgFm +IzJBYcDp8XgGYZqCtZN0gAQjLuJHn6vrqdW//dyXNmpsNFMLAlBFI9IJ6R/EuHyF +gcmw2UDtnTvR5+PfBSo9T/DZUB6sWrh3h2FQi2AFnOm1qbzhsRoZy+ea8zgnnYYD +kdTkiyXq6opoQYLeCrYcyaIksCNXvQNh6ocQKrEpTXNO9p6/uN4QSrd35HK+/8JK +4zgMWWOQB35QBhtxevVjR03JtPXa1r61Y/jY00nnGrnzVx01/GKo2vzbo3+iwBJB +rvkSvQKuJxm6k54oOUtCIOKzkackSiKIcbaPXt7g0dZhLrsV7JwXuCrXfz+aDFqt +F/gxckIybZjM1NW3/4PNN1W7nvc+cW3dsHaEW2susGXRi2eHlM2VqZjAoMHmqN3v +9swzo5Cu3Xotx3gSPGH19g6MLZh/xMSXCIylRYw5xxCOP3H3o2lO3Gnet+rFIJVs +pXUlibCmuTnalxlUT7q5OXancUItUQ4haYkXf7FglqOAeekdLvwboQoANKnBubhr +c07kINUBCQlbtRDd66Qs +=9qt7 +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:28/file-7.patch b/share/security/patches/SA-14:28/file-7.patch new file mode 100644 index 0000000000..ce0326305d --- /dev/null +++ b/share/security/patches/SA-14:28/file-7.patch @@ -0,0 +1,146 @@ +Index: contrib/file/elfclass.h +=================================================================== +--- contrib/file/elfclass.h.orig ++++ contrib/file/elfclass.h +@@ -35,9 +35,11 @@ + switch (type) { + #ifdef ELFCORE + case ET_CORE: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > MAX_PHNUM) ++ return toomany(ms, "program", phnum); + if (dophn_core(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), + fsize, &flags) == -1) + return -1; +@@ -45,18 +47,24 @@ + #endif + case ET_EXEC: + case ET_DYN: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > MAX_PHNUM) ++ return toomany(ms, "program", phnum); ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > MAX_SHNUM) ++ return toomany(ms, "section", shnum); + if (dophn_exec(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), +- fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) +- == -1) ++ fsize, &flags, shnum) == -1) + return -1; + /*FALLTHROUGH*/ + case ET_REL: ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > MAX_SHNUM) ++ return toomany(ms, "section", shnum); + if (doshn(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_shoff), +- elf_getu16(swap, elfhdr.e_shnum), ++ (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, + (size_t)elf_getu16(swap, elfhdr.e_shentsize), + &flags, + elf_getu16(swap, elfhdr.e_machine)) == -1) +Index: contrib/file/readelf.c +=================================================================== +--- contrib/file/readelf.c.orig ++++ contrib/file/readelf.c +@@ -60,6 +60,18 @@ + private uint32_t getu32(int, uint32_t); + private uint64_t getu64(int, uint64_t); + ++#define MAX_PHNUM 256 ++#define MAX_SHNUM 1024 ++ ++private int ++toomany(struct magic_set *ms, const char *name, uint16_t num) ++{ ++ if (file_printf(ms, ", too many %s header sections (%u)", name, num ++ ) == -1) ++ return -1; ++ return 0; ++} ++ + private uint16_t + getu16(int swap, uint16_t value) + { +@@ -391,13 +403,13 @@ + if (namesz & 0x80000000) { + (void)file_printf(ms, ", bad note name size 0x%lx", + (unsigned long)namesz); +- return offset; ++ return 0; + } + + if (descsz & 0x80000000) { + (void)file_printf(ms, ", bad note description size 0x%lx", + (unsigned long)descsz); +- return offset; ++ return 0; + } + + +@@ -821,6 +833,7 @@ + Elf32_Shdr sh32; + Elf64_Shdr sh64; + int stripped = 1; ++ size_t nbadcap = 0; + void *nbuf; + off_t noff; + uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ +@@ -893,6 +906,8 @@ + case SHT_SUNW_cap: + { + off_t coff; ++ if (nbadcap > 5) ++ break; + if ((off = lseek(fd, (off_t)0, SEEK_CUR)) == + (off_t)-1) { + file_badread(ms); +@@ -933,6 +948,8 @@ + (unsigned long long)xcap_tag, + (unsigned long long)xcap_val) == -1) + return -1; ++ if (nbadcap++ > 2) ++ coff = xsh_size; + break; + } + } +@@ -1139,7 +1156,7 @@ + int flags = 0; + Elf32_Ehdr elf32hdr; + Elf64_Ehdr elf64hdr; +- uint16_t type; ++ uint16_t type, phnum, shnum; + + if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) + return 0; +Index: contrib/file/softmagic.c +=================================================================== +--- contrib/file/softmagic.c.orig ++++ contrib/file/softmagic.c +@@ -61,6 +61,9 @@ + private void cvt_64(union VALUETYPE *, const struct magic *); + + #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) ++ ++#define MAX_RECURSION_LEVEL 10 ++ + /* + * softmagic - lookup one file in parsed, in-memory copy of database + * Passed the name and FILE * of one file to be typed. +@@ -1030,7 +1033,7 @@ + uint32_t count = m->str_range; + union VALUETYPE *p = &ms->ms_value; + +- if (recursion_level >= 20) { ++ if (recursion_level >= MAX_RECURSION_LEVEL) { + file_error(ms, 0, "recursion nesting exceeded"); + return -1; + } diff --git a/share/security/patches/SA-14:28/file-7.patch.asc b/share/security/patches/SA-14:28/file-7.patch.asc new file mode 100644 index 0000000000..e5bb6a3db7 --- /dev/null +++ b/share/security/patches/SA-14:28/file-7.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2RAAoJEO1n7NZdz2rnaRIQAOy5fBvNnNRIM2mEoiDVbI2a +nVoDsiSHWX9roIRdY/3L0d/S4mbvt08Sbd10qF6pR/haJlniDBR8BHxjkUHU5rTF +C/rkIsVJwasf4Mb6yTIlJntAqZDRVr4vtv3Y4EN9qJqI85q3KhSNJByrllltiBzg +BfHUxKV8vaBULDNbAICeNa6HJ9dOzup9Fr1zu+N+dup3SCIbvHBiS8I/fHvQvzf4 +to5kkp4XwHUDgemS9cuwLzs9Xs5VJbhJht8n/2flJI80mTrLa+sGlNLARjOMJU3n +NFW7oZ01spsWfLrdCr9fI/zsf7QowKHHEquZaX305BysmBqdes4FqkjMbRelM8a3 +4kKzV8b1ZLXXzqw6Tj4XXFcC0SAqvYtDou2u+AoIJwfdO7AbFDYBKS6AD5sP5tb6 +3ZwoiWk09Xnb3gVOPrzvh/9nF6BrjhHC5qlSt8Kdp1XWupoXBaxWbSu9Dcfu1Amd +PhivZ1DrK5lMkzIDCjW/aXrbhIWrZR/a2ilsWbeSgO8Wq899gPlj6zHnf9pxBKVJ +QKO/hkb0f4fmFd7RDi3fCN6dOXEyT3lo8GcDVLvfbJYjbbWveylPmg6/O2SOKqYY +KMFrECyoSRSgY9aV3pISw/ioukukkS+R0vDCdthNUHdxbpAM53OnnVaeJrZnoAt5 +xjvvLOy4c+UQZDj4GuON +=ZtPX +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:28/file-8.patch b/share/security/patches/SA-14:28/file-8.patch new file mode 100644 index 0000000000..4eb36a7cb1 --- /dev/null +++ b/share/security/patches/SA-14:28/file-8.patch @@ -0,0 +1,147 @@ +Index: contrib/file/elfclass.h +=================================================================== +--- contrib/file/elfclass.h.orig ++++ contrib/file/elfclass.h +@@ -35,10 +35,12 @@ + switch (type) { + #ifdef ELFCORE + case ET_CORE: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > MAX_PHNUM) ++ return toomany(ms, "program", phnum); + flags |= FLAGS_IS_CORE; + if (dophn_core(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), + fsize, &flags) == -1) + return -1; +@@ -46,18 +48,24 @@ + #endif + case ET_EXEC: + case ET_DYN: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > MAX_PHNUM) ++ return toomany(ms, "program", phnum); ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > MAX_SHNUM) ++ return toomany(ms, "section", shnum); + if (dophn_exec(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), +- fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) +- == -1) ++ fsize, &flags, shnum) == -1) + return -1; + /*FALLTHROUGH*/ + case ET_REL: ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > MAX_SHNUM) ++ return toomany(ms, "section", shnum); + if (doshn(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_shoff), +- elf_getu16(swap, elfhdr.e_shnum), ++ (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, + (size_t)elf_getu16(swap, elfhdr.e_shentsize), + fsize, &flags, elf_getu16(swap, elfhdr.e_machine)) == -1) + return -1; +Index: contrib/file/readelf.c +=================================================================== +--- contrib/file/readelf.c.orig ++++ contrib/file/readelf.c +@@ -60,6 +60,18 @@ + private uint32_t getu32(int, uint32_t); + private uint64_t getu64(int, uint64_t); + ++#define MAX_PHNUM 256 ++#define MAX_SHNUM 1024 ++ ++private int ++toomany(struct magic_set *ms, const char *name, uint16_t num) ++{ ++ if (file_printf(ms, ", too many %s header sections (%u)", name, num ++ ) == -1) ++ return -1; ++ return 0; ++} ++ + private uint16_t + getu16(int swap, uint16_t value) + { +@@ -384,13 +396,13 @@ + if (namesz & 0x80000000) { + (void)file_printf(ms, ", bad note name size 0x%lx", + (unsigned long)namesz); +- return offset; ++ return 0; + } + + if (descsz & 0x80000000) { + (void)file_printf(ms, ", bad note description size 0x%lx", + (unsigned long)descsz); +- return offset; ++ return 0; + } + + +@@ -847,6 +859,7 @@ + Elf32_Shdr sh32; + Elf64_Shdr sh64; + int stripped = 1; ++ size_t nbadcap = 0; + void *nbuf; + off_t noff, coff; + uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ +@@ -919,6 +932,8 @@ + free(nbuf); + break; + case SHT_SUNW_cap: ++ if (nbadcap > 5) ++ break; + if (lseek(fd, (off_t)xsh_offset, SEEK_SET) == + (off_t)-1) { + file_badseek(ms); +@@ -955,6 +970,8 @@ + (unsigned long long)xcap_tag, + (unsigned long long)xcap_val) == -1) + return -1; ++ if (nbadcap++ > 2) ++ coff = xsh_size; + break; + } + } +@@ -1142,7 +1159,7 @@ + int flags = 0; + Elf32_Ehdr elf32hdr; + Elf64_Ehdr elf64hdr; +- uint16_t type; ++ uint16_t type, phnum, shnum; + + if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) + return 0; +Index: contrib/file/softmagic.c +=================================================================== +--- contrib/file/softmagic.c.orig ++++ contrib/file/softmagic.c +@@ -61,6 +61,9 @@ + private void cvt_64(union VALUETYPE *, const struct magic *); + + #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) ++ ++#define MAX_RECURSION_LEVEL 10 ++ + /* + * softmagic - lookup one file in parsed, in-memory copy of database + * Passed the name and FILE * of one file to be typed. +@@ -1027,7 +1030,7 @@ + uint32_t count = m->str_range; + union VALUETYPE *p = &ms->ms_value; + +- if (recursion_level >= 20) { ++ if (recursion_level >= MAX_RECURSION_LEVEL) { + file_error(ms, 0, "recursion nesting exceeded"); + return -1; + } diff --git a/share/security/patches/SA-14:28/file-8.patch.asc b/share/security/patches/SA-14:28/file-8.patch.asc new file mode 100644 index 0000000000..6156541162 --- /dev/null +++ b/share/security/patches/SA-14:28/file-8.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2QAAoJEO1n7NZdz2rn6SAQAKXZOrvpfOUrSIN9HhGqdTn5 +IoHVlnPZnx7V4xikviHKkXfCRbRtTFHysB4XxcaMoeTqAdS2Kl9/pfPjMRdkPstA +UtzMNw8NYJeFHu4tdPXgE3VULpfqIaOuUirCsvFP5xuIWJDDr3HhwlO9ZJE7JAex +xASxuOA9jz22a/fkUuDu5iy5RLyzR9+n8zqDBHrkzZuPDFrLrbmtVL6kso+ka3zY +RUnc6SD9hAKyP7XVO95/wj8QfjUrW6dsI1XJbTzKTAUIPSvH5aC/1cKj2uwSKDxl +wsdC9ojCM3CaacqMfFQ5jTPsy72qtVTmVbCyZprPqHVNANRehweaDsyhbZZ4GwVW +RGQdXf+NYdiNxg+2RthVXL6JLsC+vI8mncQoMnIGgsXSKk2PbCl7J9lpDTjZpxN1 +YOykFPg5BfieMM/vGzzC7MySIduvDQkbjk4S4w6ju2y9lsG/gsbr78ewYDCZcoBa +jlGo3MB/3ip/k8sxLQwv+Rb4FYJE8OFlcGU/8UXwoBGEa5vNoAX3bVLgHzqnVztV +jY6qwpWThbEdqCpfwf7ROTDN3RMZgMuQkIrqCAejvX8mctxCHULGy5GHiCkfEbAk +9d5cTq+qeYMhbrgkwmAd0kT1lsBYvPyTISTEA3X6kfigFu7mQ7uc4dDOo5K2eEZJ +f7B7AKy5HMEV3odsriNu +=E3x/ +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:29/bind983.patch b/share/security/patches/SA-14:29/bind983.patch new file mode 100644 index 0000000000..d83e9cce84 --- /dev/null +++ b/share/security/patches/SA-14:29/bind983.patch @@ -0,0 +1,956 @@ +Index: contrib/bind9/CHANGES +=================================================================== +--- contrib/bind9/CHANGES.orig ++++ contrib/bind9/CHANGES +@@ -1,3 +1,15 @@ ++4006. [security] A flaw in delegation handling could be exploited ++ to put named into an infinite loop. This has ++ been addressed by placing limits on the number ++ of levels of recursion named will allow (default 7), ++ and the number of iterative queries that it will ++ send (default 50) before terminating a recursive ++ query (CVE-2014-8500). ++ ++ The recursion depth limit is configured via the ++ "max-recursion-depth" option, and the query limit ++ via the "max-recursion-queries" option. [RT #37580] ++ + --- 9.8.3-P4 released --- + + 3383. [security] A certain combination of records in the RBT could +Index: contrib/bind9/bin/named/config.c +=================================================================== +--- contrib/bind9/bin/named/config.c.orig ++++ contrib/bind9/bin/named/config.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: config.c,v 1.113.16.2 2011/02/28 01:19:58 tbox Exp $ */ +- + /*! \file */ + + #include +@@ -158,6 +156,8 @@ + dnssec-accept-expired no;\n\ + clients-per-query 10;\n\ + max-clients-per-query 100;\n\ ++ max-recursion-depth 7;\n\ ++ max-recursion-queries 50;\n\ + zero-no-soa-ttl-cache no;\n\ + nsec3-test-zone no;\n\ + allow-new-zones no;\n\ +Index: contrib/bind9/bin/named/query.c +=================================================================== +--- contrib/bind9/bin/named/query.c.orig ++++ contrib/bind9/bin/named/query.c +@@ -3761,12 +3761,11 @@ + peeraddr = &client->peeraddr; + else + peeraddr = NULL; +- result = dns_resolver_createfetch2(client->view->resolver, ++ result = dns_resolver_createfetch3(client->view->resolver, + qname, qtype, qdomain, nameservers, + NULL, peeraddr, client->message->id, +- client->query.fetchoptions, +- client->task, +- query_resume, client, ++ client->query.fetchoptions, 0, NULL, ++ client->task, query_resume, client, + rdataset, sigrdataset, + &client->query.fetch); + +Index: contrib/bind9/bin/named/server.c +=================================================================== +--- contrib/bind9/bin/named/server.c.orig ++++ contrib/bind9/bin/named/server.c +@@ -2566,6 +2566,16 @@ + cfg_obj_asuint32(obj), + max_clients_per_query); + ++ obj = NULL; ++ result = ns_config_get(maps, "max-recursion-depth", &obj); ++ INSIST(result == ISC_R_SUCCESS); ++ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); ++ ++ obj = NULL; ++ result = ns_config_get(maps, "max-recursion-queries", &obj); ++ INSIST(result == ISC_R_SUCCESS); ++ dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); ++ + #ifdef ALLOW_FILTER_AAAA_ON_V4 + obj = NULL; + result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); +Index: contrib/bind9/lib/dns/adb.c +=================================================================== +--- contrib/bind9/lib/dns/adb.c.orig ++++ contrib/bind9/lib/dns/adb.c +@@ -200,6 +200,7 @@ + unsigned int magic; + dns_fetch_t *fetch; + dns_rdataset_t rdataset; ++ unsigned int depth; + }; + + /*% +@@ -299,8 +300,7 @@ + static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); + static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); + static void clean_target(dns_adb_t *, dns_name_t *); +-static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, +- unsigned int); ++static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int); + static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); + static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, + isc_stdtime_t); +@@ -308,6 +308,7 @@ + static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, + dns_rdatatype_t); + static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, ++ unsigned int, isc_counter_t *qc, + dns_rdatatype_t); + static inline void check_exit(dns_adb_t *); + static void destroy(dns_adb_t *); +@@ -2743,6 +2744,19 @@ + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **findp) + { ++ return (dns_adb_createfind2(adb, task, action, arg, name, ++ qname, qtype, options, now, ++ target, port, 0, NULL, findp)); ++} ++ ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, ++ in_port_t port, unsigned int depth, isc_counter_t *qc, ++ dns_adbfind_t **findp) ++{ + dns_adbfind_t *find; + dns_adbname_t *adbname; + int bucket; +@@ -2973,7 +2987,7 @@ + * Start V4. + */ + if (WANT_INET(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, qc, + dns_rdatatype_a) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: started A fetch for name %p", +@@ -2984,7 +2998,7 @@ + * Start V6. + */ + if (WANT_INET6(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, qc, + dns_rdatatype_aaaa) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: " +@@ -3727,6 +3741,12 @@ + DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", + buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", + dns_result_totext(dev->result)); ++ /* ++ * Don't record a failure unless this is the initial ++ * fetch of a chain. ++ */ ++ if (fetch->depth > 1) ++ goto out; + /* XXXMLG Don't pound on bad servers. */ + if (address_type == DNS_ADBFIND_INET) { + name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); +@@ -3764,9 +3784,8 @@ + } + + static isc_result_t +-fetch_name(dns_adbname_t *adbname, +- isc_boolean_t start_at_zone, +- dns_rdatatype_t type) ++fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, ++ unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type) + { + isc_result_t result; + dns_adbfetch_t *fetch = NULL; +@@ -3811,12 +3830,14 @@ + result = ISC_R_NOMEMORY; + goto cleanup; + } ++ fetch->depth = depth; + +- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, +- type, name, nameservers, NULL, +- options, adb->task, fetch_callback, +- adbname, &fetch->rdataset, NULL, +- &fetch->fetch); ++ result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, ++ type, name, nameservers, NULL, ++ NULL, 0, options, depth, qc, ++ adb->task, fetch_callback, adbname, ++ &fetch->rdataset, NULL, ++ &fetch->fetch); + if (result != ISC_R_SUCCESS) + goto cleanup; + +Index: contrib/bind9/lib/dns/include/dns/adb.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/adb.h.orig ++++ contrib/bind9/lib/dns/include/dns/adb.h +@@ -334,6 +334,13 @@ + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **find); ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, in_port_t port, ++ unsigned int depth, isc_counter_t *qc, ++ dns_adbfind_t **find); + /*%< + * Main interface for clients. The adb will look up the name given in + * "name" and will build up a list of found addresses, and perhaps start +Index: contrib/bind9/lib/dns/include/dns/resolver.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/resolver.h.orig ++++ contrib/bind9/lib/dns/include/dns/resolver.h +@@ -271,6 +271,18 @@ + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp); ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, isc_uint16_t id, ++ unsigned int options, unsigned int depth, ++ isc_counter_t *qc, isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp); + /*%< + * Recurse to answer a question. + * +@@ -572,6 +584,30 @@ + * \li resolver to be valid. + */ + ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver); ++/*% ++ * Get and set how many NS indirections will be followed when looking for ++ * nameserver addresses. ++ * ++ * Requires: ++ * \li resolver to be valid. ++ */ ++ ++void ++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries); ++unsigned int ++dns_resolver_getmaxqueries(dns_resolver_t *resolver); ++/*% ++ * Get and set how many iterative queries will be allowed before ++ * terminating a recursive query. ++ * ++ * Requires: ++ * \li resolver to be valid. ++ */ ++ + ISC_LANG_ENDDECLS + + #endif /* DNS_RESOLVER_H */ +Index: contrib/bind9/lib/dns/resolver.c +=================================================================== +--- contrib/bind9/lib/dns/resolver.c.orig ++++ contrib/bind9/lib/dns/resolver.c +@@ -21,6 +21,7 @@ + + #include + ++#include + #include + #include + #include +@@ -113,6 +114,16 @@ + #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ + #endif + ++/* The default maximum number of recursions to follow before giving up. */ ++#ifndef DEFAULT_RECURSION_DEPTH ++#define DEFAULT_RECURSION_DEPTH 7 ++#endif ++ ++/* The default maximum number of iterative queries to allow before giving up. */ ++#ifndef DEFAULT_MAX_QUERIES ++#define DEFAULT_MAX_QUERIES 50 ++#endif ++ + /*% + * Maximum EDNS0 input packet size. + */ +@@ -214,12 +225,13 @@ + isc_sockaddrlist_t edns; + isc_sockaddrlist_t edns512; + isc_sockaddrlist_t bad_edns; +- dns_validator_t *validator; ++ dns_validator_t * validator; + ISC_LIST(dns_validator_t) validators; + dns_db_t * cache; + dns_adb_t * adb; + isc_boolean_t ns_ttl_ok; + isc_uint32_t ns_ttl; ++ isc_counter_t * qc; + + /*% + * The number of events we're waiting for. +@@ -287,6 +299,7 @@ + isc_boolean_t timeout; + dns_adbaddrinfo_t *addrinfo; + isc_sockaddr_t *client; ++ unsigned int depth; + }; + + #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') +@@ -399,6 +412,8 @@ + isc_timer_t * spillattimer; + isc_boolean_t zero_no_soa_ttl; + unsigned int query_timeout; ++ unsigned int maxdepth; ++ unsigned int maxqueries; + + /* Locked by lock. */ + unsigned int references; +@@ -1545,6 +1560,7 @@ + if (result != ISC_R_SUCCESS) + goto cleanup_dispatch; + } ++ + fctx->querysent++; + + ISC_LIST_APPEND(fctx->queries, query, link); +@@ -2186,9 +2202,9 @@ + */ + INSIST(!SHUTTINGDOWN(fctx)); + fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; +- if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) ++ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { + want_try = ISC_TRUE; +- else { ++ } else { + fctx->findfail++; + if (fctx->pending == 0) { + /* +@@ -2217,7 +2233,7 @@ + else if (want_done) + fctx_done(fctx, ISC_R_FAILURE, __LINE__); + else if (destroy) { +- fctx_destroy(fctx); ++ fctx_destroy(fctx); + if (bucket_empty) + empty_bucket(res); + } +@@ -2471,12 +2487,13 @@ + * See what we know about this address. + */ + find = NULL; +- result = dns_adb_createfind(fctx->adb, +- res->buckets[fctx->bucketnum].task, +- fctx_finddone, fctx, name, +- &fctx->name, fctx->type, +- options, now, NULL, +- res->view->dstport, &find); ++ result = dns_adb_createfind2(fctx->adb, ++ res->buckets[fctx->bucketnum].task, ++ fctx_finddone, fctx, name, ++ &fctx->name, fctx->type, ++ options, now, NULL, ++ res->view->dstport, ++ fctx->depth + 1, fctx->qc, &find); + if (result != ISC_R_SUCCESS) { + if (result == DNS_R_ALIAS) { + /* +@@ -2584,6 +2601,14 @@ + + res = fctx->res; + ++ if (fctx->depth > res->maxdepth) { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, ++ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), ++ "too much NS indirection resolving '%s'", ++ fctx->info); ++ return (DNS_R_SERVFAIL); ++ } ++ + /* + * Forwarders. + */ +@@ -3059,6 +3084,16 @@ + } + } + ++ result = isc_counter_increment(fctx->qc); ++ if (result != ISC_R_SUCCESS) { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, ++ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), ++ "exceeded max queries resolving '%s'", ++ fctx->info); ++ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); ++ return; ++ } ++ + result = fctx_query(fctx, addrinfo, fctx->options); + if (result != ISC_R_SUCCESS) + fctx_done(fctx, result, __LINE__); +@@ -3157,6 +3192,7 @@ + isc_mem_put(fctx->mctx, sa, sizeof(*sa)); + } + ++ isc_counter_detach(&fctx->qc); + isc_timer_detach(&fctx->timer); + dns_message_destroy(&fctx->rmessage); + dns_message_destroy(&fctx->qmessage); +@@ -3485,7 +3521,8 @@ + static isc_result_t + fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, +- unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) ++ unsigned int options, unsigned int bucketnum, unsigned int depth, ++ isc_counter_t *qc, fetchctx_t **fctxp) + { + fetchctx_t *fctx; + isc_result_t result; +@@ -3507,6 +3544,21 @@ + fctx = isc_mem_get(mctx, sizeof(*fctx)); + if (fctx == NULL) + return (ISC_R_NOMEMORY); ++ ++ fctx->qc = NULL; ++ if (qc != NULL) { ++ isc_counter_attach(qc, &fctx->qc); ++ } else { ++ result = isc_counter_create(res->mctx, ++ res->maxqueries, &fctx->qc); ++ if (result != ISC_R_SUCCESS) ++ goto cleanup_fetch; ++ } ++ ++ /* ++ * Make fctx->info point to a copy of a formatted string ++ * "name/type". ++ */ + dns_name_format(name, buf, sizeof(buf)); + dns_rdatatype_format(type, typebuf, sizeof(typebuf)); + strcat(buf, "/"); /* checked */ +@@ -3514,7 +3566,7 @@ + fctx->info = isc_mem_strdup(mctx, buf); + if (fctx->info == NULL) { + result = ISC_R_NOMEMORY; +- goto cleanup_fetch; ++ goto cleanup_counter; + } + FCTXTRACE("create"); + dns_name_init(&fctx->name, NULL); +@@ -3537,6 +3589,7 @@ + fctx->state = fetchstate_init; + fctx->want_shutdown = ISC_FALSE; + fctx->cloned = ISC_FALSE; ++ fctx->depth = depth; + ISC_LIST_INIT(fctx->queries); + ISC_LIST_INIT(fctx->finds); + ISC_LIST_INIT(fctx->altfinds); +@@ -3742,6 +3795,9 @@ + cleanup_info: + isc_mem_free(mctx, fctx->info); + ++ cleanup_counter: ++ isc_counter_detach(&fctx->qc); ++ + cleanup_fetch: + isc_mem_put(mctx, fctx, sizeof(*fctx)); + +@@ -5453,7 +5509,7 @@ + char qbuf[DNS_NAME_FORMATSIZE]; + char nbuf[DNS_NAME_FORMATSIZE]; + char tbuf[DNS_RDATATYPE_FORMATSIZE]; +- dns_rdatatype_format(fctx->type, tbuf, ++ dns_rdatatype_format(type, tbuf, + sizeof(tbuf)); + dns_name_format(name, nbuf, + sizeof(nbuf)); +@@ -5462,7 +5518,7 @@ + log_formerr(fctx, + "unrelated %s %s in " + "%s authority section", +- tbuf, qbuf, nbuf); ++ tbuf, nbuf, qbuf); + return (DNS_R_FORMERR); + } + if (type == dns_rdatatype_ns) { +@@ -7504,6 +7560,8 @@ + res->query_timeout = DEFAULT_QUERY_TIMEOUT; + res->ndisps = 0; + res->nextdisp = 0; /* meaningless at this point, but init it */ ++ res->maxdepth = DEFAULT_RECURSION_DEPTH; ++ res->maxqueries = DEFAULT_MAX_QUERIES; + res->nbuckets = ntasks; + res->activebuckets = ntasks; + res->buckets = isc_mem_get(view->mctx, +@@ -7943,9 +8001,9 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { +- return (dns_resolver_createfetch2(res, name, type, domain, ++ return (dns_resolver_createfetch3(res, name, type, domain, + nameservers, forwarders, NULL, 0, +- options, task, action, arg, ++ options, 0, NULL, task, action, arg, + rdataset, sigrdataset, fetchp)); + } + +@@ -7961,6 +8019,25 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { ++ return (dns_resolver_createfetch3(res, name, type, domain, ++ nameservers, forwarders, client, id, ++ options, 0, NULL, task, action, arg, ++ rdataset, sigrdataset, fetchp)); ++} ++ ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, dns_messageid_t id, ++ unsigned int options, unsigned int depth, ++ isc_counter_t *qc, isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp) ++{ + dns_fetch_t *fetch; + fetchctx_t *fctx = NULL; + isc_result_t result = ISC_R_SUCCESS; +@@ -8047,11 +8124,12 @@ + + if (fctx == NULL) { + result = fctx_create(res, name, type, domain, nameservers, +- options, bucketnum, &fctx); ++ options, bucketnum, depth, qc, &fctx); + if (result != ISC_R_SUCCESS) + goto unlock; + new_fctx = ISC_TRUE; +- } ++ } else if (fctx->depth > depth) ++ fctx->depth = depth; + + result = fctx_join(fctx, task, client, id, action, arg, + rdataset, sigrdataset, fetch); +@@ -8821,3 +8899,27 @@ + + resolver->query_timeout = seconds; + } ++ ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ resolver->maxdepth = maxdepth; ++} ++ ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ return (resolver->maxdepth); ++} ++ ++void ++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ resolver->maxqueries = queries; ++} ++ ++unsigned int ++dns_resolver_getmaxqueries(dns_resolver_t *resolver) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ return (resolver->maxqueries); ++} +Index: contrib/bind9/lib/export/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/export/isc/Makefile.in.orig ++++ contrib/bind9/lib/export/isc/Makefile.in +@@ -63,7 +63,7 @@ + # Alphabetically + OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ +- base64.@O@ buffer.@O@ bufferlist.@O@ \ ++ base64.@O@ buffer.@O@ bufferlist.@O@ counter.@O@ \ + error.@O@ event.@O@ \ + hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ +@@ -86,7 +86,7 @@ + + SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c backtrace-emptytbl.c base32.c \ +- base64.c buffer.c bufferlist.c \ ++ base64.c buffer.c bufferlist.c counter.c \ + error.c event.c \ + hash.c hex.c hmacmd5.c hmacsha.c \ + inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ +Index: contrib/bind9/lib/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/isc/Makefile.in.orig ++++ contrib/bind9/lib/isc/Makefile.in +@@ -13,8 +13,6 @@ + # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-# $Id$ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -53,7 +51,7 @@ + OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ + bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ +- error.@O@ event.@O@ \ ++ counter.@O@ error.@O@ event.@O@ \ + hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ + lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ +@@ -69,8 +67,8 @@ + # Alphabetically + SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c base32.c base64.c bitstring.c \ +- buffer.c bufferlist.c commandline.c error.c event.c \ +- heap.c hex.c hmacmd5.c hmacsha.c \ ++ buffer.c bufferlist.c commandline.c counter.c \ ++ error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ + httpd.c inet_aton.c iterated_hash.c \ + lex.c lfsr.c lib.c log.c \ + md5.c mem.c mutexblock.c \ +Index: contrib/bind9/lib/isc/counter.c +=================================================================== +--- contrib/bind9/lib/isc/counter.c.orig ++++ contrib/bind9/lib/isc/counter.c +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/*! \file */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define COUNTER_MAGIC ISC_MAGIC('C', 'n', 't', 'r') ++#define VALID_COUNTER(r) ISC_MAGIC_VALID(r, COUNTER_MAGIC) ++ ++struct isc_counter { ++ unsigned int magic; ++ isc_mem_t *mctx; ++ isc_mutex_t lock; ++ unsigned int references; ++ unsigned int limit; ++ unsigned int used; ++}; ++ ++isc_result_t ++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) { ++ isc_result_t result; ++ isc_counter_t *counter; ++ ++ REQUIRE(counterp != NULL && *counterp == NULL); ++ ++ counter = isc_mem_get(mctx, sizeof(*counter)); ++ if (counter == NULL) ++ return (ISC_R_NOMEMORY); ++ ++ result = isc_mutex_init(&counter->lock); ++ if (result != ISC_R_SUCCESS) { ++ isc_mem_put(mctx, counter, sizeof(*counter)); ++ return (result); ++ } ++ ++ counter->mctx = NULL; ++ isc_mem_attach(mctx, &counter->mctx); ++ ++ counter->references = 1; ++ counter->limit = limit; ++ counter->used = 0; ++ ++ counter->magic = COUNTER_MAGIC; ++ *counterp = counter; ++ return (ISC_R_SUCCESS); ++} ++ ++isc_result_t ++isc_counter_increment(isc_counter_t *counter) { ++ isc_result_t result = ISC_R_SUCCESS; ++ ++ LOCK(&counter->lock); ++ counter->used++; ++ if (counter->limit != 0 && counter->used >= counter->limit) ++ result = ISC_R_QUOTA; ++ UNLOCK(&counter->lock); ++ ++ return (result); ++} ++ ++unsigned int ++isc_counter_used(isc_counter_t *counter) { ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ return (counter->used); ++} ++ ++void ++isc_counter_setlimit(isc_counter_t *counter, int limit) { ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ LOCK(&counter->lock); ++ counter->limit = limit; ++ UNLOCK(&counter->lock); ++} ++ ++void ++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) { ++ REQUIRE(VALID_COUNTER(source)); ++ REQUIRE(targetp != NULL && *targetp == NULL); ++ ++ LOCK(&source->lock); ++ source->references++; ++ INSIST(source->references > 0); ++ UNLOCK(&source->lock); ++ ++ *targetp = source; ++} ++ ++static void ++destroy(isc_counter_t *counter) { ++ counter->magic = 0; ++ isc_mutex_destroy(&counter->lock); ++ isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter)); ++} ++ ++void ++isc_counter_detach(isc_counter_t **counterp) { ++ isc_counter_t *counter; ++ isc_boolean_t want_destroy = ISC_FALSE; ++ ++ REQUIRE(counterp != NULL && *counterp != NULL); ++ counter = *counterp; ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ *counterp = NULL; ++ ++ LOCK(&counter->lock); ++ INSIST(counter->references > 0); ++ counter->references--; ++ if (counter->references == 0) ++ want_destroy = ISC_TRUE; ++ UNLOCK(&counter->lock); ++ ++ if (want_destroy) ++ destroy(counter); ++} +Index: contrib/bind9/lib/isc/include/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/isc/include/isc/Makefile.in.orig ++++ contrib/bind9/lib/isc/include/isc/Makefile.in +@@ -13,8 +13,6 @@ + # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-# $Id$ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -27,7 +25,8 @@ + # install target below. + # + HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ +- buffer.h bufferlist.h commandline.h entropy.h error.h event.h \ ++ buffer.h bufferlist.h \ ++ commandline.h counter.h entropy.h error.h event.h \ + eventclass.h file.h formatcheck.h fsaccess.h \ + hash.h heap.h hex.h hmacmd5.h hmacsha.h \ + httpd.h \ +Index: contrib/bind9/lib/isc/include/isc/counter.h +=================================================================== +--- contrib/bind9/lib/isc/include/isc/counter.h.orig ++++ contrib/bind9/lib/isc/include/isc/counter.h +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef ISC_COUNTER_H ++#define ISC_COUNTER_H 1 ++ ++/***** ++ ***** Module Info ++ *****/ ++ ++/*! \file isc/counter.h ++ * ++ * \brief The isc_counter_t object is a simplified version of the ++ * isc_quota_t object; it tracks the consumption of limited ++ * resources, returning an error condition when the quota is ++ * exceeded. However, unlike isc_quota_t, attaching and detaching ++ * from a counter object does not increment or decrement the counter. ++ */ ++ ++/*** ++ *** Imports. ++ ***/ ++ ++#include ++#include ++#include ++ ++/***** ++ ***** Types. ++ *****/ ++ ++ISC_LANG_BEGINDECLS ++ ++isc_result_t ++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp); ++/*%< ++ * Allocate and initialize a counter object. ++ */ ++ ++isc_result_t ++isc_counter_increment(isc_counter_t *counter); ++/*%< ++ * Increment the counter. ++ * ++ * If the counter limit is nonzero and has been reached, then ++ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is ++ * incremented regardless of return value.) ++ */ ++ ++unsigned int ++isc_counter_used(isc_counter_t *counter); ++/*%< ++ * Return the current counter value. ++ */ ++ ++void ++isc_counter_setlimit(isc_counter_t *counter, int limit); ++/*%< ++ * Set the counter limit. ++ */ ++ ++void ++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp); ++/*%< ++ * Attach to a counter object, increasing its reference counter. ++ */ ++ ++void ++isc_counter_detach(isc_counter_t **counterp); ++/*%< ++ * Detach (and destroy if reference counter has dropped to zero) ++ * a counter object. ++ */ ++ ++ISC_LANG_ENDDECLS ++ ++#endif /* ISC_COUNTER_H */ +Index: contrib/bind9/lib/isc/include/isc/types.h +=================================================================== +--- contrib/bind9/lib/isc/include/isc/types.h.orig ++++ contrib/bind9/lib/isc/include/isc/types.h +@@ -50,6 +50,7 @@ + typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ + typedef struct isc_constregion isc_constregion_t; /*%< Const region */ + typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */ ++typedef struct isc_counter isc_counter_t; /*%< Counter */ + typedef struct isc_entropy isc_entropy_t; /*%< Entropy */ + typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */ + typedef struct isc_event isc_event_t; /*%< Event */ +Index: contrib/bind9/lib/isccfg/namedconf.c +=================================================================== +--- contrib/bind9/lib/isccfg/namedconf.c.orig ++++ contrib/bind9/lib/isccfg/namedconf.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id$ */ +- + /*! \file */ + + #include +@@ -1244,6 +1242,8 @@ + { "max-cache-ttl", &cfg_type_uint32, 0 }, + { "max-clients-per-query", &cfg_type_uint32, 0 }, + { "max-ncache-ttl", &cfg_type_uint32, 0 }, ++ { "max-recursion-depth", &cfg_type_uint32, 0 }, ++ { "max-recursion-queries", &cfg_type_uint32, 0 }, + { "max-udp-size", &cfg_type_uint32, 0 }, + { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, + { "minimal-responses", &cfg_type_boolean, 0 }, +Index: lib/bind/isc/Makefile +=================================================================== +--- lib/bind/isc/Makefile.orig ++++ lib/bind/isc/Makefile +@@ -28,7 +28,7 @@ + .PATH: ${SRCDIR} + SRCS+= inet_pton.c \ + assertions.c backtrace.c base32.c base64.c bitstring.c \ +- buffer.c bufferlist.c commandline.c error.c event.c \ ++ buffer.c bufferlist.c commandline.c counter.c error.c event.c \ + fsaccess.c hash.c \ + heap.c hex.c hmacmd5.c hmacsha.c \ + httpd.c inet_aton.c \ +@@ -65,6 +65,7 @@ + ${SRCDIR}/include/isc/buffer.h \ + ${SRCDIR}/include/isc/bufferlist.h \ + ${SRCDIR}/include/isc/commandline.h \ ++ ${SRCDIR}/include/isc/counter.h \ + ${SRCDIR}/include/isc/entropy.h \ + ${SRCDIR}/include/isc/error.h \ + ${SRCDIR}/include/isc/event.h \ diff --git a/share/security/patches/SA-14:29/bind983.patch.asc b/share/security/patches/SA-14:29/bind983.patch.asc new file mode 100644 index 0000000000..54972d7fef --- /dev/null +++ b/share/security/patches/SA-14:29/bind983.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2RAAoJEO1n7NZdz2rnLB0P/iDqii0FWCXAGG8aareyo79v +1YxfXKRnWINNEUJGpe6jfOzoThMq6NCuy4Eh7a3r0ourcSTyCPs/fRGch/g/xBG/ +CtMtAb4ApXhlipOSXVCzz/wLXbjkg8OXfJ0Pb1kS3FDDfeC0eVlZmC/nJkQ5pUoS +5ITFCCPA4hXjIcvujaCv+GeC4m8Bde63ktR3vT8A91n7XYOS/WLl2cUzFx3kH9sR +Kz6XArnTfN3ou7fPTjodf3yKLKNzCRwijyQACbuJsaEejYqUHN2ek0DZCRJb5C8X +0dYao1CPmcIQa0732YXHeFvYMmeth7rmb9F+kVPrGxv4Dnc4yaPRxRcXK1yETDNA +pALEnceF3kYJWEfvU9EeY+3Ku7dSDKW8sPipd5OGDNuyKbUoZLneurZW9Hz0TgCO +brliFnA++GN87npMBC/Nrrn832MSLtVEznb7PT9ykWFvgrxx+VQolsr2LQy4ek7i +2ZjRzPR7tNj5Ost6+o7iDhYLoqZRMQ9G0SZSeC+hxoenqMj0Zt5CXm/SyvI/qPNL +C2N5SB+vTqwbCVmNh51h2QtB2mbwT/1EjTa/5lVWbwwDPtyJekyl9klj14wVTqyv +ryRcLd/yV4OywVoUxYazSYqM/zRUMEVUEL1/VZWbhvdMWkN+6KcmZbiYn++AEZyX +t/sNj1W4f0/tjmBvMEL4 +=4PXV +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:29/bind984.patch b/share/security/patches/SA-14:29/bind984.patch new file mode 100644 index 0000000000..af9d6b66b7 --- /dev/null +++ b/share/security/patches/SA-14:29/bind984.patch @@ -0,0 +1,956 @@ +Index: contrib/bind9/CHANGES +=================================================================== +--- contrib/bind9/CHANGES.orig ++++ contrib/bind9/CHANGES +@@ -1,3 +1,15 @@ ++4006. [security] A flaw in delegation handling could be exploited ++ to put named into an infinite loop. This has ++ been addressed by placing limits on the number ++ of levels of recursion named will allow (default 7), ++ and the number of iterative queries that it will ++ send (default 50) before terminating a recursive ++ query (CVE-2014-8500). ++ ++ The recursion depth limit is configured via the ++ "max-recursion-depth" option, and the query limit ++ via the "max-recursion-queries" option. [RT #37580] ++ + --- 9.8.4-P2 released --- + + 3516. [security] Removed the check for regex.h in configure in order +Index: contrib/bind9/bin/named/config.c +=================================================================== +--- contrib/bind9/bin/named/config.c.orig ++++ contrib/bind9/bin/named/config.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: config.c,v 1.113.16.2 2011/02/28 01:19:58 tbox Exp $ */ +- + /*! \file */ + + #include +@@ -158,6 +156,8 @@ + dnssec-accept-expired no;\n\ + clients-per-query 10;\n\ + max-clients-per-query 100;\n\ ++ max-recursion-depth 7;\n\ ++ max-recursion-queries 50;\n\ + zero-no-soa-ttl-cache no;\n\ + nsec3-test-zone no;\n\ + allow-new-zones no;\n\ +Index: contrib/bind9/bin/named/query.c +=================================================================== +--- contrib/bind9/bin/named/query.c.orig ++++ contrib/bind9/bin/named/query.c +@@ -3755,12 +3755,11 @@ + peeraddr = &client->peeraddr; + else + peeraddr = NULL; +- result = dns_resolver_createfetch2(client->view->resolver, ++ result = dns_resolver_createfetch3(client->view->resolver, + qname, qtype, qdomain, nameservers, + NULL, peeraddr, client->message->id, +- client->query.fetchoptions, +- client->task, +- query_resume, client, ++ client->query.fetchoptions, 0, NULL, ++ client->task, query_resume, client, + rdataset, sigrdataset, + &client->query.fetch); + +Index: contrib/bind9/bin/named/server.c +=================================================================== +--- contrib/bind9/bin/named/server.c.orig ++++ contrib/bind9/bin/named/server.c +@@ -2580,6 +2580,16 @@ + cfg_obj_asuint32(obj), + max_clients_per_query); + ++ obj = NULL; ++ result = ns_config_get(maps, "max-recursion-depth", &obj); ++ INSIST(result == ISC_R_SUCCESS); ++ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); ++ ++ obj = NULL; ++ result = ns_config_get(maps, "max-recursion-queries", &obj); ++ INSIST(result == ISC_R_SUCCESS); ++ dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); ++ + #ifdef ALLOW_FILTER_AAAA_ON_V4 + obj = NULL; + result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); +Index: contrib/bind9/lib/dns/adb.c +=================================================================== +--- contrib/bind9/lib/dns/adb.c.orig ++++ contrib/bind9/lib/dns/adb.c +@@ -201,6 +201,7 @@ + unsigned int magic; + dns_fetch_t *fetch; + dns_rdataset_t rdataset; ++ unsigned int depth; + }; + + /*% +@@ -300,8 +301,7 @@ + static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); + static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); + static void clean_target(dns_adb_t *, dns_name_t *); +-static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, +- unsigned int); ++static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int); + static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); + static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, + isc_stdtime_t); +@@ -309,6 +309,7 @@ + static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, + dns_rdatatype_t); + static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, ++ unsigned int, isc_counter_t *qc, + dns_rdatatype_t); + static inline void check_exit(dns_adb_t *); + static void destroy(dns_adb_t *); +@@ -2760,6 +2761,19 @@ + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **findp) + { ++ return (dns_adb_createfind2(adb, task, action, arg, name, ++ qname, qtype, options, now, ++ target, port, 0, NULL, findp)); ++} ++ ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, ++ in_port_t port, unsigned int depth, isc_counter_t *qc, ++ dns_adbfind_t **findp) ++{ + dns_adbfind_t *find; + dns_adbname_t *adbname; + int bucket; +@@ -2990,7 +3004,7 @@ + * Start V4. + */ + if (WANT_INET(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, qc, + dns_rdatatype_a) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: started A fetch for name %p", +@@ -3001,7 +3015,7 @@ + * Start V6. + */ + if (WANT_INET6(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, qc, + dns_rdatatype_aaaa) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: " +@@ -3744,6 +3758,12 @@ + DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", + buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", + dns_result_totext(dev->result)); ++ /* ++ * Don't record a failure unless this is the initial ++ * fetch of a chain. ++ */ ++ if (fetch->depth > 1) ++ goto out; + /* XXXMLG Don't pound on bad servers. */ + if (address_type == DNS_ADBFIND_INET) { + name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); +@@ -3781,9 +3801,8 @@ + } + + static isc_result_t +-fetch_name(dns_adbname_t *adbname, +- isc_boolean_t start_at_zone, +- dns_rdatatype_t type) ++fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, ++ unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type) + { + isc_result_t result; + dns_adbfetch_t *fetch = NULL; +@@ -3828,12 +3847,14 @@ + result = ISC_R_NOMEMORY; + goto cleanup; + } ++ fetch->depth = depth; + +- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, +- type, name, nameservers, NULL, +- options, adb->task, fetch_callback, +- adbname, &fetch->rdataset, NULL, +- &fetch->fetch); ++ result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, ++ type, name, nameservers, NULL, ++ NULL, 0, options, depth, qc, ++ adb->task, fetch_callback, adbname, ++ &fetch->rdataset, NULL, ++ &fetch->fetch); + if (result != ISC_R_SUCCESS) + goto cleanup; + +Index: contrib/bind9/lib/dns/include/dns/adb.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/adb.h.orig ++++ contrib/bind9/lib/dns/include/dns/adb.h +@@ -334,6 +334,13 @@ + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **find); ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, in_port_t port, ++ unsigned int depth, isc_counter_t *qc, ++ dns_adbfind_t **find); + /*%< + * Main interface for clients. The adb will look up the name given in + * "name" and will build up a list of found addresses, and perhaps start +Index: contrib/bind9/lib/dns/include/dns/resolver.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/resolver.h.orig ++++ contrib/bind9/lib/dns/include/dns/resolver.h +@@ -271,6 +271,18 @@ + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp); ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, isc_uint16_t id, ++ unsigned int options, unsigned int depth, ++ isc_counter_t *qc, isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp); + /*%< + * Recurse to answer a question. + * +@@ -572,6 +584,30 @@ + * \li resolver to be valid. + */ + ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver); ++/*% ++ * Get and set how many NS indirections will be followed when looking for ++ * nameserver addresses. ++ * ++ * Requires: ++ * \li resolver to be valid. ++ */ ++ ++void ++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries); ++unsigned int ++dns_resolver_getmaxqueries(dns_resolver_t *resolver); ++/*% ++ * Get and set how many iterative queries will be allowed before ++ * terminating a recursive query. ++ * ++ * Requires: ++ * \li resolver to be valid. ++ */ ++ + ISC_LANG_ENDDECLS + + #endif /* DNS_RESOLVER_H */ +Index: contrib/bind9/lib/dns/resolver.c +=================================================================== +--- contrib/bind9/lib/dns/resolver.c.orig ++++ contrib/bind9/lib/dns/resolver.c +@@ -21,6 +21,7 @@ + + #include + ++#include + #include + #include + #include +@@ -126,6 +127,16 @@ + #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ + #endif + ++/* The default maximum number of recursions to follow before giving up. */ ++#ifndef DEFAULT_RECURSION_DEPTH ++#define DEFAULT_RECURSION_DEPTH 7 ++#endif ++ ++/* The default maximum number of iterative queries to allow before giving up. */ ++#ifndef DEFAULT_MAX_QUERIES ++#define DEFAULT_MAX_QUERIES 50 ++#endif ++ + /*% + * Maximum EDNS0 input packet size. + */ +@@ -227,12 +238,13 @@ + isc_sockaddrlist_t edns; + isc_sockaddrlist_t edns512; + isc_sockaddrlist_t bad_edns; +- dns_validator_t *validator; ++ dns_validator_t * validator; + ISC_LIST(dns_validator_t) validators; + dns_db_t * cache; + dns_adb_t * adb; + isc_boolean_t ns_ttl_ok; + isc_uint32_t ns_ttl; ++ isc_counter_t * qc; + + /*% + * The number of events we're waiting for. +@@ -300,6 +312,7 @@ + isc_boolean_t timeout; + dns_adbaddrinfo_t *addrinfo; + isc_sockaddr_t *client; ++ unsigned int depth; + }; + + #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') +@@ -412,6 +425,8 @@ + isc_timer_t * spillattimer; + isc_boolean_t zero_no_soa_ttl; + unsigned int query_timeout; ++ unsigned int maxdepth; ++ unsigned int maxqueries; + + /* Locked by lock. */ + unsigned int references; +@@ -1569,6 +1584,7 @@ + if (result != ISC_R_SUCCESS) + goto cleanup_dispatch; + } ++ + fctx->querysent++; + + ISC_LIST_APPEND(fctx->queries, query, link); +@@ -2210,9 +2226,9 @@ + */ + INSIST(!SHUTTINGDOWN(fctx)); + fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; +- if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) ++ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { + want_try = ISC_TRUE; +- else { ++ } else { + fctx->findfail++; + if (fctx->pending == 0) { + /* +@@ -2241,7 +2257,7 @@ + else if (want_done) + fctx_done(fctx, ISC_R_FAILURE, __LINE__); + else if (destroy) { +- fctx_destroy(fctx); ++ fctx_destroy(fctx); + if (bucket_empty) + empty_bucket(res); + } +@@ -2495,12 +2511,13 @@ + * See what we know about this address. + */ + find = NULL; +- result = dns_adb_createfind(fctx->adb, +- res->buckets[fctx->bucketnum].task, +- fctx_finddone, fctx, name, +- &fctx->name, fctx->type, +- options, now, NULL, +- res->view->dstport, &find); ++ result = dns_adb_createfind2(fctx->adb, ++ res->buckets[fctx->bucketnum].task, ++ fctx_finddone, fctx, name, ++ &fctx->name, fctx->type, ++ options, now, NULL, ++ res->view->dstport, ++ fctx->depth + 1, fctx->qc, &find); + if (result != ISC_R_SUCCESS) { + if (result == DNS_R_ALIAS) { + /* +@@ -2608,6 +2625,14 @@ + + res = fctx->res; + ++ if (fctx->depth > res->maxdepth) { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, ++ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), ++ "too much NS indirection resolving '%s'", ++ fctx->info); ++ return (DNS_R_SERVFAIL); ++ } ++ + /* + * Forwarders. + */ +@@ -3083,6 +3108,16 @@ + } + } + ++ result = isc_counter_increment(fctx->qc); ++ if (result != ISC_R_SUCCESS) { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, ++ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), ++ "exceeded max queries resolving '%s'", ++ fctx->info); ++ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); ++ return; ++ } ++ + result = fctx_query(fctx, addrinfo, fctx->options); + if (result != ISC_R_SUCCESS) + fctx_done(fctx, result, __LINE__); +@@ -3181,6 +3216,7 @@ + isc_mem_put(fctx->mctx, sa, sizeof(*sa)); + } + ++ isc_counter_detach(&fctx->qc); + isc_timer_detach(&fctx->timer); + dns_message_destroy(&fctx->rmessage); + dns_message_destroy(&fctx->qmessage); +@@ -3509,7 +3545,8 @@ + static isc_result_t + fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, +- unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) ++ unsigned int options, unsigned int bucketnum, unsigned int depth, ++ isc_counter_t *qc, fetchctx_t **fctxp) + { + fetchctx_t *fctx; + isc_result_t result; +@@ -3531,6 +3568,21 @@ + fctx = isc_mem_get(mctx, sizeof(*fctx)); + if (fctx == NULL) + return (ISC_R_NOMEMORY); ++ ++ fctx->qc = NULL; ++ if (qc != NULL) { ++ isc_counter_attach(qc, &fctx->qc); ++ } else { ++ result = isc_counter_create(res->mctx, ++ res->maxqueries, &fctx->qc); ++ if (result != ISC_R_SUCCESS) ++ goto cleanup_fetch; ++ } ++ ++ /* ++ * Make fctx->info point to a copy of a formatted string ++ * "name/type". ++ */ + dns_name_format(name, buf, sizeof(buf)); + dns_rdatatype_format(type, typebuf, sizeof(typebuf)); + strcat(buf, "/"); /* checked */ +@@ -3538,7 +3590,7 @@ + fctx->info = isc_mem_strdup(mctx, buf); + if (fctx->info == NULL) { + result = ISC_R_NOMEMORY; +- goto cleanup_fetch; ++ goto cleanup_counter; + } + FCTXTRACE("create"); + dns_name_init(&fctx->name, NULL); +@@ -3561,6 +3613,7 @@ + fctx->state = fetchstate_init; + fctx->want_shutdown = ISC_FALSE; + fctx->cloned = ISC_FALSE; ++ fctx->depth = depth; + ISC_LIST_INIT(fctx->queries); + ISC_LIST_INIT(fctx->finds); + ISC_LIST_INIT(fctx->altfinds); +@@ -3766,6 +3819,9 @@ + cleanup_info: + isc_mem_free(mctx, fctx->info); + ++ cleanup_counter: ++ isc_counter_detach(&fctx->qc); ++ + cleanup_fetch: + isc_mem_put(mctx, fctx, sizeof(*fctx)); + +@@ -5477,7 +5533,7 @@ + char qbuf[DNS_NAME_FORMATSIZE]; + char nbuf[DNS_NAME_FORMATSIZE]; + char tbuf[DNS_RDATATYPE_FORMATSIZE]; +- dns_rdatatype_format(fctx->type, tbuf, ++ dns_rdatatype_format(type, tbuf, + sizeof(tbuf)); + dns_name_format(name, nbuf, + sizeof(nbuf)); +@@ -5486,7 +5542,7 @@ + log_formerr(fctx, + "unrelated %s %s in " + "%s authority section", +- tbuf, qbuf, nbuf); ++ tbuf, nbuf, qbuf); + return (DNS_R_FORMERR); + } + if (type == dns_rdatatype_ns) { +@@ -7528,6 +7584,8 @@ + res->query_timeout = DEFAULT_QUERY_TIMEOUT; + res->ndisps = 0; + res->nextdisp = 0; /* meaningless at this point, but init it */ ++ res->maxdepth = DEFAULT_RECURSION_DEPTH; ++ res->maxqueries = DEFAULT_MAX_QUERIES; + res->nbuckets = ntasks; + res->activebuckets = ntasks; + res->buckets = isc_mem_get(view->mctx, +@@ -7967,9 +8025,9 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { +- return (dns_resolver_createfetch2(res, name, type, domain, ++ return (dns_resolver_createfetch3(res, name, type, domain, + nameservers, forwarders, NULL, 0, +- options, task, action, arg, ++ options, 0, NULL, task, action, arg, + rdataset, sigrdataset, fetchp)); + } + +@@ -7985,6 +8043,25 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { ++ return (dns_resolver_createfetch3(res, name, type, domain, ++ nameservers, forwarders, client, id, ++ options, 0, NULL, task, action, arg, ++ rdataset, sigrdataset, fetchp)); ++} ++ ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, dns_messageid_t id, ++ unsigned int options, unsigned int depth, ++ isc_counter_t *qc, isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp) ++{ + dns_fetch_t *fetch; + fetchctx_t *fctx = NULL; + isc_result_t result = ISC_R_SUCCESS; +@@ -8071,11 +8148,12 @@ + + if (fctx == NULL) { + result = fctx_create(res, name, type, domain, nameservers, +- options, bucketnum, &fctx); ++ options, bucketnum, depth, qc, &fctx); + if (result != ISC_R_SUCCESS) + goto unlock; + new_fctx = ISC_TRUE; +- } ++ } else if (fctx->depth > depth) ++ fctx->depth = depth; + + result = fctx_join(fctx, task, client, id, action, arg, + rdataset, sigrdataset, fetch); +@@ -8847,3 +8925,27 @@ + + resolver->query_timeout = seconds; + } ++ ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ resolver->maxdepth = maxdepth; ++} ++ ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ return (resolver->maxdepth); ++} ++ ++void ++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ resolver->maxqueries = queries; ++} ++ ++unsigned int ++dns_resolver_getmaxqueries(dns_resolver_t *resolver) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ return (resolver->maxqueries); ++} +Index: contrib/bind9/lib/export/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/export/isc/Makefile.in.orig ++++ contrib/bind9/lib/export/isc/Makefile.in +@@ -63,7 +63,7 @@ + # Alphabetically + OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ +- base64.@O@ buffer.@O@ bufferlist.@O@ \ ++ base64.@O@ buffer.@O@ bufferlist.@O@ counter.@O@ \ + error.@O@ event.@O@ \ + hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ +@@ -86,7 +86,7 @@ + + SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c backtrace-emptytbl.c base32.c \ +- base64.c buffer.c bufferlist.c \ ++ base64.c buffer.c bufferlist.c counter.c \ + error.c event.c \ + hash.c hex.c hmacmd5.c hmacsha.c \ + inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ +Index: contrib/bind9/lib/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/isc/Makefile.in.orig ++++ contrib/bind9/lib/isc/Makefile.in +@@ -13,8 +13,6 @@ + # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-# $Id$ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -53,7 +51,7 @@ + OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ + bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ +- error.@O@ event.@O@ \ ++ counter.@O@ error.@O@ event.@O@ \ + hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ + lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ +@@ -69,8 +67,8 @@ + # Alphabetically + SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c base32.c base64.c bitstring.c \ +- buffer.c bufferlist.c commandline.c error.c event.c \ +- heap.c hex.c hmacmd5.c hmacsha.c \ ++ buffer.c bufferlist.c commandline.c counter.c \ ++ error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ + httpd.c inet_aton.c iterated_hash.c \ + lex.c lfsr.c lib.c log.c \ + md5.c mem.c mutexblock.c \ +Index: contrib/bind9/lib/isc/counter.c +=================================================================== +--- contrib/bind9/lib/isc/counter.c.orig ++++ contrib/bind9/lib/isc/counter.c +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/*! \file */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define COUNTER_MAGIC ISC_MAGIC('C', 'n', 't', 'r') ++#define VALID_COUNTER(r) ISC_MAGIC_VALID(r, COUNTER_MAGIC) ++ ++struct isc_counter { ++ unsigned int magic; ++ isc_mem_t *mctx; ++ isc_mutex_t lock; ++ unsigned int references; ++ unsigned int limit; ++ unsigned int used; ++}; ++ ++isc_result_t ++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) { ++ isc_result_t result; ++ isc_counter_t *counter; ++ ++ REQUIRE(counterp != NULL && *counterp == NULL); ++ ++ counter = isc_mem_get(mctx, sizeof(*counter)); ++ if (counter == NULL) ++ return (ISC_R_NOMEMORY); ++ ++ result = isc_mutex_init(&counter->lock); ++ if (result != ISC_R_SUCCESS) { ++ isc_mem_put(mctx, counter, sizeof(*counter)); ++ return (result); ++ } ++ ++ counter->mctx = NULL; ++ isc_mem_attach(mctx, &counter->mctx); ++ ++ counter->references = 1; ++ counter->limit = limit; ++ counter->used = 0; ++ ++ counter->magic = COUNTER_MAGIC; ++ *counterp = counter; ++ return (ISC_R_SUCCESS); ++} ++ ++isc_result_t ++isc_counter_increment(isc_counter_t *counter) { ++ isc_result_t result = ISC_R_SUCCESS; ++ ++ LOCK(&counter->lock); ++ counter->used++; ++ if (counter->limit != 0 && counter->used >= counter->limit) ++ result = ISC_R_QUOTA; ++ UNLOCK(&counter->lock); ++ ++ return (result); ++} ++ ++unsigned int ++isc_counter_used(isc_counter_t *counter) { ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ return (counter->used); ++} ++ ++void ++isc_counter_setlimit(isc_counter_t *counter, int limit) { ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ LOCK(&counter->lock); ++ counter->limit = limit; ++ UNLOCK(&counter->lock); ++} ++ ++void ++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) { ++ REQUIRE(VALID_COUNTER(source)); ++ REQUIRE(targetp != NULL && *targetp == NULL); ++ ++ LOCK(&source->lock); ++ source->references++; ++ INSIST(source->references > 0); ++ UNLOCK(&source->lock); ++ ++ *targetp = source; ++} ++ ++static void ++destroy(isc_counter_t *counter) { ++ counter->magic = 0; ++ isc_mutex_destroy(&counter->lock); ++ isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter)); ++} ++ ++void ++isc_counter_detach(isc_counter_t **counterp) { ++ isc_counter_t *counter; ++ isc_boolean_t want_destroy = ISC_FALSE; ++ ++ REQUIRE(counterp != NULL && *counterp != NULL); ++ counter = *counterp; ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ *counterp = NULL; ++ ++ LOCK(&counter->lock); ++ INSIST(counter->references > 0); ++ counter->references--; ++ if (counter->references == 0) ++ want_destroy = ISC_TRUE; ++ UNLOCK(&counter->lock); ++ ++ if (want_destroy) ++ destroy(counter); ++} +Index: contrib/bind9/lib/isc/include/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/isc/include/isc/Makefile.in.orig ++++ contrib/bind9/lib/isc/include/isc/Makefile.in +@@ -13,8 +13,6 @@ + # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-# $Id$ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -27,7 +25,8 @@ + # install target below. + # + HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ +- buffer.h bufferlist.h commandline.h entropy.h error.h event.h \ ++ buffer.h bufferlist.h \ ++ commandline.h counter.h entropy.h error.h event.h \ + eventclass.h file.h formatcheck.h fsaccess.h \ + hash.h heap.h hex.h hmacmd5.h hmacsha.h \ + httpd.h \ +Index: contrib/bind9/lib/isc/include/isc/counter.h +=================================================================== +--- contrib/bind9/lib/isc/include/isc/counter.h.orig ++++ contrib/bind9/lib/isc/include/isc/counter.h +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef ISC_COUNTER_H ++#define ISC_COUNTER_H 1 ++ ++/***** ++ ***** Module Info ++ *****/ ++ ++/*! \file isc/counter.h ++ * ++ * \brief The isc_counter_t object is a simplified version of the ++ * isc_quota_t object; it tracks the consumption of limited ++ * resources, returning an error condition when the quota is ++ * exceeded. However, unlike isc_quota_t, attaching and detaching ++ * from a counter object does not increment or decrement the counter. ++ */ ++ ++/*** ++ *** Imports. ++ ***/ ++ ++#include ++#include ++#include ++ ++/***** ++ ***** Types. ++ *****/ ++ ++ISC_LANG_BEGINDECLS ++ ++isc_result_t ++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp); ++/*%< ++ * Allocate and initialize a counter object. ++ */ ++ ++isc_result_t ++isc_counter_increment(isc_counter_t *counter); ++/*%< ++ * Increment the counter. ++ * ++ * If the counter limit is nonzero and has been reached, then ++ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is ++ * incremented regardless of return value.) ++ */ ++ ++unsigned int ++isc_counter_used(isc_counter_t *counter); ++/*%< ++ * Return the current counter value. ++ */ ++ ++void ++isc_counter_setlimit(isc_counter_t *counter, int limit); ++/*%< ++ * Set the counter limit. ++ */ ++ ++void ++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp); ++/*%< ++ * Attach to a counter object, increasing its reference counter. ++ */ ++ ++void ++isc_counter_detach(isc_counter_t **counterp); ++/*%< ++ * Detach (and destroy if reference counter has dropped to zero) ++ * a counter object. ++ */ ++ ++ISC_LANG_ENDDECLS ++ ++#endif /* ISC_COUNTER_H */ +Index: contrib/bind9/lib/isc/include/isc/types.h +=================================================================== +--- contrib/bind9/lib/isc/include/isc/types.h.orig ++++ contrib/bind9/lib/isc/include/isc/types.h +@@ -50,6 +50,7 @@ + typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ + typedef struct isc_constregion isc_constregion_t; /*%< Const region */ + typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */ ++typedef struct isc_counter isc_counter_t; /*%< Counter */ + typedef struct isc_entropy isc_entropy_t; /*%< Entropy */ + typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */ + typedef struct isc_event isc_event_t; /*%< Event */ +Index: contrib/bind9/lib/isccfg/namedconf.c +=================================================================== +--- contrib/bind9/lib/isccfg/namedconf.c.orig ++++ contrib/bind9/lib/isccfg/namedconf.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id$ */ +- + /*! \file */ + + #include +@@ -1348,6 +1346,8 @@ + { "max-cache-ttl", &cfg_type_uint32, 0 }, + { "max-clients-per-query", &cfg_type_uint32, 0 }, + { "max-ncache-ttl", &cfg_type_uint32, 0 }, ++ { "max-recursion-depth", &cfg_type_uint32, 0 }, ++ { "max-recursion-queries", &cfg_type_uint32, 0 }, + { "max-udp-size", &cfg_type_uint32, 0 }, + { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, + { "minimal-responses", &cfg_type_boolean, 0 }, +Index: lib/bind/isc/Makefile +=================================================================== +--- lib/bind/isc/Makefile.orig ++++ lib/bind/isc/Makefile +@@ -28,7 +28,7 @@ + .PATH: ${SRCDIR} + SRCS+= inet_pton.c \ + assertions.c backtrace.c base32.c base64.c bitstring.c \ +- buffer.c bufferlist.c commandline.c error.c event.c \ ++ buffer.c bufferlist.c commandline.c counter.c error.c event.c \ + fsaccess.c hash.c \ + heap.c hex.c hmacmd5.c hmacsha.c \ + httpd.c inet_aton.c \ +@@ -65,6 +65,7 @@ + ${SRCDIR}/include/isc/buffer.h \ + ${SRCDIR}/include/isc/bufferlist.h \ + ${SRCDIR}/include/isc/commandline.h \ ++ ${SRCDIR}/include/isc/counter.h \ + ${SRCDIR}/include/isc/entropy.h \ + ${SRCDIR}/include/isc/error.h \ + ${SRCDIR}/include/isc/event.h \ diff --git a/share/security/patches/SA-14:29/bind984.patch.asc b/share/security/patches/SA-14:29/bind984.patch.asc new file mode 100644 index 0000000000..79861cd730 --- /dev/null +++ b/share/security/patches/SA-14:29/bind984.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2RAAoJEO1n7NZdz2rn4HgQAOookP9oIbPnYVRpgAoqoa9x +aRrOju3+P8lDKCoQDrdTaFEIwbMwGjANbUOM91zG9NaZLAX/qdGFrFEPIx4hI74c +034Byt/gBUsZxeXF4kAzdvV4LDqOOt38bcph6SX869gxF+BXvPLdXOKOvIKJ8ZWx +J0Yg5FcBEpg0pgQR+LqHo6G0fOVI3BqOLgoj/o1JGq3SkuYwtJink8fd/Ejgtd/F +OsK5mHnsCmDhG/aMnPP0rM1aycgRoTjlVIi4apRYyS3ZN31yQeKgEgqHBfmsfzwz +7NBjwKaF8hu5YwfBKv1h13mlNgghPDBttSzFmhB4Cf6ScP53AZ23zErI78gNTVIe +RKtPns5BmntVDaX8g+0sO1DPch7SujM3hSRfwWV/bHY864EOf3hvIV8yXBThXP00 +9Fd27JEqDFEaEHGIEf2ATxLVm6d+QH4hwPVHKiSAvONQs0uBr0/4mliZv1HFdT3M +6wAdvgPT3OV8hCqmqRUt1GyUxB6GVBEZd7lcvekNowYi+AT4Jo0gojkU22E7+Dlt +FNCqOpahZrBlS613ywZ4qZQegeVvvR23z7s1iYYmpAnn9NlkauPib2HHTpGRmgBl +huD1GmqvvZxT3jsW2cxHdMvYZg4HkBQO4wX9icoSO2nLrV9pYWtlMimI1CcjF9Ah +AirWWyKBuzyceh4qsL/U +=MvL5 +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:29/bind987.patch b/share/security/patches/SA-14:29/bind987.patch new file mode 100644 index 0000000000..f6e3b6b9f4 --- /dev/null +++ b/share/security/patches/SA-14:29/bind987.patch @@ -0,0 +1,956 @@ +Index: contrib/bind9/CHANGES +=================================================================== +--- contrib/bind9/CHANGES.orig ++++ contrib/bind9/CHANGES +@@ -1,3 +1,15 @@ ++4006. [security] A flaw in delegation handling could be exploited ++ to put named into an infinite loop. This has ++ been addressed by placing limits on the number ++ of levels of recursion named will allow (default 7), ++ and the number of iterative queries that it will ++ send (default 50) before terminating a recursive ++ query (CVE-2014-8500). ++ ++ The recursion depth limit is configured via the ++ "max-recursion-depth" option, and the query limit ++ via the "max-recursion-queries" option. [RT #37580] ++ + --- 9.8.7 released --- + + --- 9.8.7rc2 released --- +Index: contrib/bind9/bin/named/config.c +=================================================================== +--- contrib/bind9/bin/named/config.c.orig ++++ contrib/bind9/bin/named/config.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: config.c,v 1.113.16.2 2011/02/28 01:19:58 tbox Exp $ */ +- + /*! \file */ + + #include +@@ -159,6 +157,8 @@ + dnssec-accept-expired no;\n\ + clients-per-query 10;\n\ + max-clients-per-query 100;\n\ ++ max-recursion-depth 7;\n\ ++ max-recursion-queries 50;\n\ + zero-no-soa-ttl-cache no;\n\ + nsec3-test-zone no;\n\ + allow-new-zones no;\n\ +Index: contrib/bind9/bin/named/query.c +=================================================================== +--- contrib/bind9/bin/named/query.c.orig ++++ contrib/bind9/bin/named/query.c +@@ -3802,12 +3802,11 @@ + peeraddr = &client->peeraddr; + else + peeraddr = NULL; +- result = dns_resolver_createfetch2(client->view->resolver, ++ result = dns_resolver_createfetch3(client->view->resolver, + qname, qtype, qdomain, nameservers, + NULL, peeraddr, client->message->id, +- client->query.fetchoptions, +- client->task, +- query_resume, client, ++ client->query.fetchoptions, 0, NULL, ++ client->task, query_resume, client, + rdataset, sigrdataset, + &client->query.fetch); + +Index: contrib/bind9/bin/named/server.c +=================================================================== +--- contrib/bind9/bin/named/server.c.orig ++++ contrib/bind9/bin/named/server.c +@@ -2949,6 +2949,16 @@ + cfg_obj_asuint32(obj), + max_clients_per_query); + ++ obj = NULL; ++ result = ns_config_get(maps, "max-recursion-depth", &obj); ++ INSIST(result == ISC_R_SUCCESS); ++ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); ++ ++ obj = NULL; ++ result = ns_config_get(maps, "max-recursion-queries", &obj); ++ INSIST(result == ISC_R_SUCCESS); ++ dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); ++ + #ifdef ALLOW_FILTER_AAAA_ON_V4 + obj = NULL; + result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); +Index: contrib/bind9/lib/dns/adb.c +=================================================================== +--- contrib/bind9/lib/dns/adb.c.orig ++++ contrib/bind9/lib/dns/adb.c +@@ -201,6 +201,7 @@ + unsigned int magic; + dns_fetch_t *fetch; + dns_rdataset_t rdataset; ++ unsigned int depth; + }; + + /*% +@@ -300,8 +301,7 @@ + static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); + static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); + static void clean_target(dns_adb_t *, dns_name_t *); +-static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, +- unsigned int); ++static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int); + static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); + static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, + isc_stdtime_t); +@@ -309,6 +309,7 @@ + static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, + dns_rdatatype_t); + static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, ++ unsigned int, isc_counter_t *qc, + dns_rdatatype_t); + static inline void check_exit(dns_adb_t *); + static void destroy(dns_adb_t *); +@@ -2770,6 +2771,19 @@ + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **findp) + { ++ return (dns_adb_createfind2(adb, task, action, arg, name, ++ qname, qtype, options, now, ++ target, port, 0, NULL, findp)); ++} ++ ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, ++ in_port_t port, unsigned int depth, isc_counter_t *qc, ++ dns_adbfind_t **findp) ++{ + dns_adbfind_t *find; + dns_adbname_t *adbname; + int bucket; +@@ -3000,7 +3014,7 @@ + * Start V4. + */ + if (WANT_INET(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, qc, + dns_rdatatype_a) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: started A fetch for name %p", +@@ -3011,7 +3025,7 @@ + * Start V6. + */ + if (WANT_INET6(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, qc, + dns_rdatatype_aaaa) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: " +@@ -3754,6 +3768,12 @@ + DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", + buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", + dns_result_totext(dev->result)); ++ /* ++ * Don't record a failure unless this is the initial ++ * fetch of a chain. ++ */ ++ if (fetch->depth > 1) ++ goto out; + /* XXXMLG Don't pound on bad servers. */ + if (address_type == DNS_ADBFIND_INET) { + name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); +@@ -3791,9 +3811,8 @@ + } + + static isc_result_t +-fetch_name(dns_adbname_t *adbname, +- isc_boolean_t start_at_zone, +- dns_rdatatype_t type) ++fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, ++ unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type) + { + isc_result_t result; + dns_adbfetch_t *fetch = NULL; +@@ -3838,12 +3857,14 @@ + result = ISC_R_NOMEMORY; + goto cleanup; + } ++ fetch->depth = depth; + +- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, +- type, name, nameservers, NULL, +- options, adb->task, fetch_callback, +- adbname, &fetch->rdataset, NULL, +- &fetch->fetch); ++ result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, ++ type, name, nameservers, NULL, ++ NULL, 0, options, depth, qc, ++ adb->task, fetch_callback, adbname, ++ &fetch->rdataset, NULL, ++ &fetch->fetch); + if (result != ISC_R_SUCCESS) + goto cleanup; + +Index: contrib/bind9/lib/dns/include/dns/adb.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/adb.h.orig ++++ contrib/bind9/lib/dns/include/dns/adb.h +@@ -334,6 +334,13 @@ + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **find); ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, in_port_t port, ++ unsigned int depth, isc_counter_t *qc, ++ dns_adbfind_t **find); + /*%< + * Main interface for clients. The adb will look up the name given in + * "name" and will build up a list of found addresses, and perhaps start +Index: contrib/bind9/lib/dns/include/dns/resolver.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/resolver.h.orig ++++ contrib/bind9/lib/dns/include/dns/resolver.h +@@ -271,6 +271,18 @@ + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp); ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, isc_uint16_t id, ++ unsigned int options, unsigned int depth, ++ isc_counter_t *qc, isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp); + /*%< + * Recurse to answer a question. + * +@@ -572,6 +584,30 @@ + * \li resolver to be valid. + */ + ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver); ++/*% ++ * Get and set how many NS indirections will be followed when looking for ++ * nameserver addresses. ++ * ++ * Requires: ++ * \li resolver to be valid. ++ */ ++ ++void ++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries); ++unsigned int ++dns_resolver_getmaxqueries(dns_resolver_t *resolver); ++/*% ++ * Get and set how many iterative queries will be allowed before ++ * terminating a recursive query. ++ * ++ * Requires: ++ * \li resolver to be valid. ++ */ ++ + ISC_LANG_ENDDECLS + + #endif /* DNS_RESOLVER_H */ +Index: contrib/bind9/lib/dns/resolver.c +=================================================================== +--- contrib/bind9/lib/dns/resolver.c.orig ++++ contrib/bind9/lib/dns/resolver.c +@@ -22,6 +22,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -130,6 +131,16 @@ + #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ + #endif + ++/* The default maximum number of recursions to follow before giving up. */ ++#ifndef DEFAULT_RECURSION_DEPTH ++#define DEFAULT_RECURSION_DEPTH 7 ++#endif ++ ++/* The default maximum number of iterative queries to allow before giving up. */ ++#ifndef DEFAULT_MAX_QUERIES ++#define DEFAULT_MAX_QUERIES 50 ++#endif ++ + /*% + * Maximum EDNS0 input packet size. + */ +@@ -232,12 +243,13 @@ + isc_sockaddrlist_t edns; + isc_sockaddrlist_t edns512; + isc_sockaddrlist_t bad_edns; +- dns_validator_t *validator; ++ dns_validator_t * validator; + ISC_LIST(dns_validator_t) validators; + dns_db_t * cache; + dns_adb_t * adb; + isc_boolean_t ns_ttl_ok; + isc_uint32_t ns_ttl; ++ isc_counter_t * qc; + + /*% + * The number of events we're waiting for. +@@ -305,6 +317,7 @@ + isc_boolean_t timeout; + dns_adbaddrinfo_t *addrinfo; + isc_sockaddr_t *client; ++ unsigned int depth; + }; + + #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') +@@ -417,6 +430,8 @@ + isc_timer_t * spillattimer; + isc_boolean_t zero_no_soa_ttl; + unsigned int query_timeout; ++ unsigned int maxdepth; ++ unsigned int maxqueries; + + /* Locked by lock. */ + unsigned int references; +@@ -1530,6 +1545,7 @@ + if (result != ISC_R_SUCCESS) + goto cleanup_dispatch; + } ++ + fctx->querysent++; + + ISC_LIST_APPEND(fctx->queries, query, link); +@@ -2180,9 +2196,9 @@ + */ + INSIST(!SHUTTINGDOWN(fctx)); + fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; +- if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) ++ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { + want_try = ISC_TRUE; +- else { ++ } else { + fctx->findfail++; + if (fctx->pending == 0) { + /* +@@ -2211,7 +2227,7 @@ + else if (want_done) + fctx_done(fctx, ISC_R_FAILURE, __LINE__); + else if (destroy) { +- fctx_destroy(fctx); ++ fctx_destroy(fctx); + if (bucket_empty) + empty_bucket(res); + } +@@ -2465,12 +2481,13 @@ + * See what we know about this address. + */ + find = NULL; +- result = dns_adb_createfind(fctx->adb, +- res->buckets[fctx->bucketnum].task, +- fctx_finddone, fctx, name, +- &fctx->name, fctx->type, +- options, now, NULL, +- res->view->dstport, &find); ++ result = dns_adb_createfind2(fctx->adb, ++ res->buckets[fctx->bucketnum].task, ++ fctx_finddone, fctx, name, ++ &fctx->name, fctx->type, ++ options, now, NULL, ++ res->view->dstport, ++ fctx->depth + 1, fctx->qc, &find); + if (result != ISC_R_SUCCESS) { + if (result == DNS_R_ALIAS) { + /* +@@ -2578,6 +2595,14 @@ + + res = fctx->res; + ++ if (fctx->depth > res->maxdepth) { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, ++ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), ++ "too much NS indirection resolving '%s'", ++ fctx->info); ++ return (DNS_R_SERVFAIL); ++ } ++ + /* + * Forwarders. + */ +@@ -3053,6 +3078,16 @@ + } + } + ++ result = isc_counter_increment(fctx->qc); ++ if (result != ISC_R_SUCCESS) { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, ++ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), ++ "exceeded max queries resolving '%s'", ++ fctx->info); ++ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); ++ return; ++ } ++ + result = fctx_query(fctx, addrinfo, fctx->options); + if (result != ISC_R_SUCCESS) + fctx_done(fctx, result, __LINE__); +@@ -3151,6 +3186,7 @@ + isc_mem_put(fctx->mctx, sa, sizeof(*sa)); + } + ++ isc_counter_detach(&fctx->qc); + isc_timer_detach(&fctx->timer); + dns_message_destroy(&fctx->rmessage); + dns_message_destroy(&fctx->qmessage); +@@ -3479,7 +3515,8 @@ + static isc_result_t + fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, +- unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) ++ unsigned int options, unsigned int bucketnum, unsigned int depth, ++ isc_counter_t *qc, fetchctx_t **fctxp) + { + fetchctx_t *fctx; + isc_result_t result; +@@ -3501,6 +3538,21 @@ + fctx = isc_mem_get(mctx, sizeof(*fctx)); + if (fctx == NULL) + return (ISC_R_NOMEMORY); ++ ++ fctx->qc = NULL; ++ if (qc != NULL) { ++ isc_counter_attach(qc, &fctx->qc); ++ } else { ++ result = isc_counter_create(res->mctx, ++ res->maxqueries, &fctx->qc); ++ if (result != ISC_R_SUCCESS) ++ goto cleanup_fetch; ++ } ++ ++ /* ++ * Make fctx->info point to a copy of a formatted string ++ * "name/type". ++ */ + dns_name_format(name, buf, sizeof(buf)); + dns_rdatatype_format(type, typebuf, sizeof(typebuf)); + strcat(buf, "/"); /* checked */ +@@ -3508,7 +3560,7 @@ + fctx->info = isc_mem_strdup(mctx, buf); + if (fctx->info == NULL) { + result = ISC_R_NOMEMORY; +- goto cleanup_fetch; ++ goto cleanup_counter; + } + FCTXTRACE("create"); + dns_name_init(&fctx->name, NULL); +@@ -3531,6 +3583,7 @@ + fctx->state = fetchstate_init; + fctx->want_shutdown = ISC_FALSE; + fctx->cloned = ISC_FALSE; ++ fctx->depth = depth; + ISC_LIST_INIT(fctx->queries); + ISC_LIST_INIT(fctx->finds); + ISC_LIST_INIT(fctx->altfinds); +@@ -3738,6 +3791,9 @@ + cleanup_info: + isc_mem_free(mctx, fctx->info); + ++ cleanup_counter: ++ isc_counter_detach(&fctx->qc); ++ + cleanup_fetch: + isc_mem_put(mctx, fctx, sizeof(*fctx)); + +@@ -5651,7 +5707,7 @@ + char qbuf[DNS_NAME_FORMATSIZE]; + char nbuf[DNS_NAME_FORMATSIZE]; + char tbuf[DNS_RDATATYPE_FORMATSIZE]; +- dns_rdatatype_format(fctx->type, tbuf, ++ dns_rdatatype_format(type, tbuf, + sizeof(tbuf)); + dns_name_format(name, nbuf, + sizeof(nbuf)); +@@ -5660,7 +5716,7 @@ + log_formerr(fctx, + "unrelated %s %s in " + "%s authority section", +- tbuf, qbuf, nbuf); ++ tbuf, nbuf, qbuf); + return (DNS_R_FORMERR); + } + if (type == dns_rdatatype_ns) { +@@ -7725,6 +7781,8 @@ + res->query_timeout = DEFAULT_QUERY_TIMEOUT; + res->ndisps = 0; + res->nextdisp = 0; /* meaningless at this point, but init it */ ++ res->maxdepth = DEFAULT_RECURSION_DEPTH; ++ res->maxqueries = DEFAULT_MAX_QUERIES; + res->nbuckets = ntasks; + res->activebuckets = ntasks; + res->buckets = isc_mem_get(view->mctx, +@@ -8164,9 +8222,9 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { +- return (dns_resolver_createfetch2(res, name, type, domain, ++ return (dns_resolver_createfetch3(res, name, type, domain, + nameservers, forwarders, NULL, 0, +- options, task, action, arg, ++ options, 0, NULL, task, action, arg, + rdataset, sigrdataset, fetchp)); + } + +@@ -8182,6 +8240,25 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { ++ return (dns_resolver_createfetch3(res, name, type, domain, ++ nameservers, forwarders, client, id, ++ options, 0, NULL, task, action, arg, ++ rdataset, sigrdataset, fetchp)); ++} ++ ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, dns_messageid_t id, ++ unsigned int options, unsigned int depth, ++ isc_counter_t *qc, isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp) ++{ + dns_fetch_t *fetch; + fetchctx_t *fctx = NULL; + isc_result_t result = ISC_R_SUCCESS; +@@ -8268,11 +8345,12 @@ + + if (fctx == NULL) { + result = fctx_create(res, name, type, domain, nameservers, +- options, bucketnum, &fctx); ++ options, bucketnum, depth, qc, &fctx); + if (result != ISC_R_SUCCESS) + goto unlock; + new_fctx = ISC_TRUE; +- } ++ } else if (fctx->depth > depth) ++ fctx->depth = depth; + + result = fctx_join(fctx, task, client, id, action, arg, + rdataset, sigrdataset, fetch); +@@ -9044,3 +9122,27 @@ + + resolver->query_timeout = seconds; + } ++ ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ resolver->maxdepth = maxdepth; ++} ++ ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ return (resolver->maxdepth); ++} ++ ++void ++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ resolver->maxqueries = queries; ++} ++ ++unsigned int ++dns_resolver_getmaxqueries(dns_resolver_t *resolver) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ return (resolver->maxqueries); ++} +Index: contrib/bind9/lib/export/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/export/isc/Makefile.in.orig ++++ contrib/bind9/lib/export/isc/Makefile.in +@@ -63,7 +63,7 @@ + # Alphabetically + OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ +- base64.@O@ buffer.@O@ bufferlist.@O@ \ ++ base64.@O@ buffer.@O@ bufferlist.@O@ counter.@O@ \ + error.@O@ event.@O@ \ + hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ +@@ -85,7 +85,7 @@ + + SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c backtrace-emptytbl.c base32.c \ +- base64.c buffer.c bufferlist.c \ ++ base64.c buffer.c bufferlist.c counter.c \ + error.c event.c \ + hash.c hex.c hmacmd5.c hmacsha.c \ + inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ +Index: contrib/bind9/lib/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/isc/Makefile.in.orig ++++ contrib/bind9/lib/isc/Makefile.in +@@ -13,8 +13,6 @@ + # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-# $Id$ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -53,7 +51,7 @@ + OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ + bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ +- error.@O@ event.@O@ \ ++ counter.@O@ error.@O@ event.@O@ \ + hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ + lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ +@@ -70,8 +68,8 @@ + # Alphabetically + SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c base32.c base64.c bitstring.c \ +- buffer.c bufferlist.c commandline.c error.c event.c \ +- heap.c hex.c hmacmd5.c hmacsha.c \ ++ buffer.c bufferlist.c commandline.c counter.c \ ++ error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ + httpd.c inet_aton.c iterated_hash.c \ + lex.c lfsr.c lib.c log.c \ + md5.c mem.c mutexblock.c \ +Index: contrib/bind9/lib/isc/counter.c +=================================================================== +--- contrib/bind9/lib/isc/counter.c.orig ++++ contrib/bind9/lib/isc/counter.c +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/*! \file */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define COUNTER_MAGIC ISC_MAGIC('C', 'n', 't', 'r') ++#define VALID_COUNTER(r) ISC_MAGIC_VALID(r, COUNTER_MAGIC) ++ ++struct isc_counter { ++ unsigned int magic; ++ isc_mem_t *mctx; ++ isc_mutex_t lock; ++ unsigned int references; ++ unsigned int limit; ++ unsigned int used; ++}; ++ ++isc_result_t ++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) { ++ isc_result_t result; ++ isc_counter_t *counter; ++ ++ REQUIRE(counterp != NULL && *counterp == NULL); ++ ++ counter = isc_mem_get(mctx, sizeof(*counter)); ++ if (counter == NULL) ++ return (ISC_R_NOMEMORY); ++ ++ result = isc_mutex_init(&counter->lock); ++ if (result != ISC_R_SUCCESS) { ++ isc_mem_put(mctx, counter, sizeof(*counter)); ++ return (result); ++ } ++ ++ counter->mctx = NULL; ++ isc_mem_attach(mctx, &counter->mctx); ++ ++ counter->references = 1; ++ counter->limit = limit; ++ counter->used = 0; ++ ++ counter->magic = COUNTER_MAGIC; ++ *counterp = counter; ++ return (ISC_R_SUCCESS); ++} ++ ++isc_result_t ++isc_counter_increment(isc_counter_t *counter) { ++ isc_result_t result = ISC_R_SUCCESS; ++ ++ LOCK(&counter->lock); ++ counter->used++; ++ if (counter->limit != 0 && counter->used >= counter->limit) ++ result = ISC_R_QUOTA; ++ UNLOCK(&counter->lock); ++ ++ return (result); ++} ++ ++unsigned int ++isc_counter_used(isc_counter_t *counter) { ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ return (counter->used); ++} ++ ++void ++isc_counter_setlimit(isc_counter_t *counter, int limit) { ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ LOCK(&counter->lock); ++ counter->limit = limit; ++ UNLOCK(&counter->lock); ++} ++ ++void ++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) { ++ REQUIRE(VALID_COUNTER(source)); ++ REQUIRE(targetp != NULL && *targetp == NULL); ++ ++ LOCK(&source->lock); ++ source->references++; ++ INSIST(source->references > 0); ++ UNLOCK(&source->lock); ++ ++ *targetp = source; ++} ++ ++static void ++destroy(isc_counter_t *counter) { ++ counter->magic = 0; ++ isc_mutex_destroy(&counter->lock); ++ isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter)); ++} ++ ++void ++isc_counter_detach(isc_counter_t **counterp) { ++ isc_counter_t *counter; ++ isc_boolean_t want_destroy = ISC_FALSE; ++ ++ REQUIRE(counterp != NULL && *counterp != NULL); ++ counter = *counterp; ++ REQUIRE(VALID_COUNTER(counter)); ++ ++ *counterp = NULL; ++ ++ LOCK(&counter->lock); ++ INSIST(counter->references > 0); ++ counter->references--; ++ if (counter->references == 0) ++ want_destroy = ISC_TRUE; ++ UNLOCK(&counter->lock); ++ ++ if (want_destroy) ++ destroy(counter); ++} +Index: contrib/bind9/lib/isc/include/isc/Makefile.in +=================================================================== +--- contrib/bind9/lib/isc/include/isc/Makefile.in.orig ++++ contrib/bind9/lib/isc/include/isc/Makefile.in +@@ -13,8 +13,6 @@ + # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-# $Id$ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -27,7 +25,8 @@ + # install target below. + # + HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ +- buffer.h bufferlist.h commandline.h entropy.h error.h event.h \ ++ buffer.h bufferlist.h \ ++ commandline.h counter.h entropy.h error.h event.h \ + eventclass.h file.h formatcheck.h fsaccess.h \ + hash.h heap.h hex.h hmacmd5.h hmacsha.h \ + httpd.h \ +Index: contrib/bind9/lib/isc/include/isc/counter.h +=================================================================== +--- contrib/bind9/lib/isc/include/isc/counter.h.orig ++++ contrib/bind9/lib/isc/include/isc/counter.h +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef ISC_COUNTER_H ++#define ISC_COUNTER_H 1 ++ ++/***** ++ ***** Module Info ++ *****/ ++ ++/*! \file isc/counter.h ++ * ++ * \brief The isc_counter_t object is a simplified version of the ++ * isc_quota_t object; it tracks the consumption of limited ++ * resources, returning an error condition when the quota is ++ * exceeded. However, unlike isc_quota_t, attaching and detaching ++ * from a counter object does not increment or decrement the counter. ++ */ ++ ++/*** ++ *** Imports. ++ ***/ ++ ++#include ++#include ++#include ++ ++/***** ++ ***** Types. ++ *****/ ++ ++ISC_LANG_BEGINDECLS ++ ++isc_result_t ++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp); ++/*%< ++ * Allocate and initialize a counter object. ++ */ ++ ++isc_result_t ++isc_counter_increment(isc_counter_t *counter); ++/*%< ++ * Increment the counter. ++ * ++ * If the counter limit is nonzero and has been reached, then ++ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is ++ * incremented regardless of return value.) ++ */ ++ ++unsigned int ++isc_counter_used(isc_counter_t *counter); ++/*%< ++ * Return the current counter value. ++ */ ++ ++void ++isc_counter_setlimit(isc_counter_t *counter, int limit); ++/*%< ++ * Set the counter limit. ++ */ ++ ++void ++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp); ++/*%< ++ * Attach to a counter object, increasing its reference counter. ++ */ ++ ++void ++isc_counter_detach(isc_counter_t **counterp); ++/*%< ++ * Detach (and destroy if reference counter has dropped to zero) ++ * a counter object. ++ */ ++ ++ISC_LANG_ENDDECLS ++ ++#endif /* ISC_COUNTER_H */ +Index: contrib/bind9/lib/isc/include/isc/types.h +=================================================================== +--- contrib/bind9/lib/isc/include/isc/types.h.orig ++++ contrib/bind9/lib/isc/include/isc/types.h +@@ -50,6 +50,7 @@ + typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ + typedef struct isc_constregion isc_constregion_t; /*%< Const region */ + typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */ ++typedef struct isc_counter isc_counter_t; /*%< Counter */ + typedef struct isc_entropy isc_entropy_t; /*%< Entropy */ + typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */ + typedef struct isc_event isc_event_t; /*%< Event */ +Index: contrib/bind9/lib/isccfg/namedconf.c +=================================================================== +--- contrib/bind9/lib/isccfg/namedconf.c.orig ++++ contrib/bind9/lib/isccfg/namedconf.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id$ */ +- + /*! \file */ + + #include +@@ -1354,6 +1352,8 @@ + { "max-cache-ttl", &cfg_type_uint32, 0 }, + { "max-clients-per-query", &cfg_type_uint32, 0 }, + { "max-ncache-ttl", &cfg_type_uint32, 0 }, ++ { "max-recursion-depth", &cfg_type_uint32, 0 }, ++ { "max-recursion-queries", &cfg_type_uint32, 0 }, + { "max-udp-size", &cfg_type_uint32, 0 }, + { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, + { "minimal-responses", &cfg_type_boolean, 0 }, +Index: lib/bind/isc/Makefile +=================================================================== +--- lib/bind/isc/Makefile.orig ++++ lib/bind/isc/Makefile +@@ -28,7 +28,7 @@ + .PATH: ${SRCDIR} + SRCS+= inet_pton.c \ + assertions.c backtrace.c base32.c base64.c bitstring.c \ +- buffer.c bufferlist.c commandline.c error.c event.c \ ++ buffer.c bufferlist.c commandline.c counter.c error.c event.c \ + fsaccess.c hash.c \ + heap.c hex.c hmacmd5.c hmacsha.c \ + httpd.c inet_aton.c \ +@@ -66,6 +66,7 @@ + ${SRCDIR}/include/isc/buffer.h \ + ${SRCDIR}/include/isc/bufferlist.h \ + ${SRCDIR}/include/isc/commandline.h \ ++ ${SRCDIR}/include/isc/counter.h \ + ${SRCDIR}/include/isc/entropy.h \ + ${SRCDIR}/include/isc/error.h \ + ${SRCDIR}/include/isc/event.h \ diff --git a/share/security/patches/SA-14:29/bind987.patch.asc b/share/security/patches/SA-14:29/bind987.patch.asc new file mode 100644 index 0000000000..04bb31ceab --- /dev/null +++ b/share/security/patches/SA-14:29/bind987.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2RAAoJEO1n7NZdz2rnRBwP+wfGcF6e7O1QZN2kUpCRa1Vv +VMJGGTxAwG+j61tAa1ZaCo007VHTaUi+EO1OSNLKHKeCM6AzynonPJxeQ01IGHrt +kNWyMmGiw4ySsBAsEo3UdzN9tZsSv04FgTqlimrfqZPZq99VN4uhXM8EhOfJnzqq +6zeo8mwnw+5Lp3QijTU3bc+DzMvvAo44EWIIUmhZ6VCa0Vi8ZwBImKrDwR4sliYA +UhYsCqx3mNHYlvxjVX6WqfwA0ChsMRS6noWWDMrjG5e9de2ShjNlUAkpKaoOCqhh +ymTVLLJePd+zNCLWv65oS9VT4VI13JRIcX3ExTezUFJFuYT4PohhFzzhTbKttdxs +fveuWAOH26tEMOmSMsQWiBZRkugoLgiCPfYFupP92T2nEwFqWpSrNYw/SBAWonoH +SkGMElDc+Inlzg2tr8UhJLyuH4b/JhhGtb9nZWjOZ9SzCNbeMo0lIiRGpJMJxD56 +Hbvz10OsZzrR8TvNW8tmj6mNJObraGLA9Uhnyh4moNTitRptKjGTNtyfATstZkqB +4K9xYfb8aA52+zmiuXdfFKyqTXCFcqZVO2JzGMOriDFlyQ5LuGEhdEW4GlYO/E4g +OW8o1vLbg7o5rlh9pLeov6+RrzVntoajMHJWxrCLCrGOPkxNSVYVENhrtuz7c1VA +ieVo2x0nmiao1jjdxGzn +=KPoG +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-14:29/bind995.patch b/share/security/patches/SA-14:29/bind995.patch new file mode 100644 index 0000000000..5068a8381f --- /dev/null +++ b/share/security/patches/SA-14:29/bind995.patch @@ -0,0 +1,572 @@ +Index: contrib/bind9/CHANGES +=================================================================== +--- contrib/bind9/CHANGES.orig ++++ contrib/bind9/CHANGES +@@ -1,3 +1,14 @@ ++4006. [security] A flaw in delegation handling could be exploited ++ to put named into an infinite loop. This has ++ been addressed by placing limits on the number ++ of levels of recursion named will allow (default 7), ++ and the number of iterative queries that it will ++ send (default 50) before terminating a recursive ++ query (CVE-2014-8500). ++ ++ The recursion depth limit is configured via the ++ "max-recursion-depth" option. [RT #35780] ++ + --- 9.9.5 released --- + + --- 9.9.5rc2 released --- +Index: contrib/bind9/bin/named/config.c +=================================================================== +--- contrib/bind9/bin/named/config.c.orig ++++ contrib/bind9/bin/named/config.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: config.c,v 1.123 2012/01/06 23:46:41 tbox Exp $ */ +- + /*! \file */ + + #include +@@ -160,6 +158,7 @@ + dnssec-accept-expired no;\n\ + clients-per-query 10;\n\ + max-clients-per-query 100;\n\ ++ max-recursion-depth 7;\n\ + zero-no-soa-ttl-cache no;\n\ + nsec3-test-zone no;\n\ + allow-new-zones no;\n\ +Index: contrib/bind9/bin/named/query.c +=================================================================== +--- contrib/bind9/bin/named/query.c.orig ++++ contrib/bind9/bin/named/query.c +@@ -3872,12 +3872,11 @@ + peeraddr = &client->peeraddr; + else + peeraddr = NULL; +- result = dns_resolver_createfetch2(client->view->resolver, ++ result = dns_resolver_createfetch3(client->view->resolver, + qname, qtype, qdomain, nameservers, + NULL, peeraddr, client->message->id, +- client->query.fetchoptions, +- client->task, +- query_resume, client, ++ client->query.fetchoptions, 0, ++ client->task, query_resume, client, + rdataset, sigrdataset, + &client->query.fetch); + +Index: contrib/bind9/bin/named/server.c +=================================================================== +--- contrib/bind9/bin/named/server.c.orig ++++ contrib/bind9/bin/named/server.c +@@ -3141,6 +3141,11 @@ + cfg_obj_asuint32(obj), + max_clients_per_query); + ++ obj = NULL; ++ result = ns_config_get(maps, "max-recursion-depth", &obj); ++ INSIST(result == ISC_R_SUCCESS); ++ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); ++ + #ifdef ALLOW_FILTER_AAAA_ON_V4 + obj = NULL; + result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); +Index: contrib/bind9/lib/dns/adb.c +=================================================================== +--- contrib/bind9/lib/dns/adb.c.orig ++++ contrib/bind9/lib/dns/adb.c +@@ -201,6 +201,7 @@ + unsigned int magic; + dns_fetch_t *fetch; + dns_rdataset_t rdataset; ++ unsigned int depth; + }; + + /*% +@@ -301,7 +302,7 @@ + static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); + static void clean_target(dns_adb_t *, dns_name_t *); + static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, +- unsigned int); ++ isc_uint32_t, unsigned int); + static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); + static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, + isc_stdtime_t); +@@ -309,7 +310,7 @@ + static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, + dns_rdatatype_t); + static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, +- dns_rdatatype_t); ++ unsigned int, dns_rdatatype_t); + static inline void check_exit(dns_adb_t *); + static void destroy(dns_adb_t *); + static isc_boolean_t shutdown_names(dns_adb_t *); +@@ -982,7 +983,7 @@ + * Clean up the name's various lists. These two are destructive + * in that they will always empty the list. + */ +- clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK); ++ clean_finds_at_name(name, ev, 0, DNS_ADBFIND_ADDRESSMASK); + result4 = clean_namehooks(adb, &name->v4); + result6 = clean_namehooks(adb, &name->v6); + clean_target(adb, &name->target); +@@ -1407,7 +1408,7 @@ + */ + static void + clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype, +- unsigned int addrs) ++ isc_uint32_t qtotal, unsigned int addrs) + { + isc_event_t *ev; + isc_task_t *task; +@@ -1467,6 +1468,7 @@ + ev->ev_sender = find; + find->result_v4 = find_err_map[name->fetch_err]; + find->result_v6 = find_err_map[name->fetch6_err]; ++ find->qtotal += qtotal; + ev->ev_type = evtype; + ev->ev_destroy = event_free; + ev->ev_destroy_arg = find; +@@ -1821,6 +1823,7 @@ + h->flags = 0; + h->result_v4 = ISC_R_UNEXPECTED; + h->result_v6 = ISC_R_UNEXPECTED; ++ h->qtotal = 0; + ISC_LINK_INIT(h, publink); + ISC_LINK_INIT(h, plink); + ISC_LIST_INIT(h->list); +@@ -2770,6 +2773,19 @@ + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **findp) + { ++ return (dns_adb_createfind2(adb, task, action, arg, name, ++ qname, qtype, options, now, ++ target, port, 0, findp)); ++} ++ ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, ++ in_port_t port, unsigned int depth, ++ dns_adbfind_t **findp) ++{ + dns_adbfind_t *find; + dns_adbname_t *adbname; + int bucket; +@@ -3000,7 +3016,7 @@ + * Start V4. + */ + if (WANT_INET(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, + dns_rdatatype_a) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: started A fetch for name %p", +@@ -3011,7 +3027,7 @@ + * Start V6. + */ + if (WANT_INET6(wanted_fetches) && +- fetch_name(adbname, start_at_zone, ++ fetch_name(adbname, start_at_zone, depth, + dns_rdatatype_aaaa) == ISC_R_SUCCESS) { + DP(DEF_LEVEL, + "dns_adb_createfind: " +@@ -3627,6 +3643,7 @@ + isc_result_t result; + unsigned int address_type; + isc_boolean_t want_check_exit = ISC_FALSE; ++ isc_uint32_t qtotal = 0; + + UNUSED(task); + +@@ -3637,6 +3654,8 @@ + adb = name->adb; + INSIST(DNS_ADB_VALID(adb)); + ++ qtotal = dev->qtotal; ++ + bucket = name->lock_bucket; + LOCK(&adb->namelocks[bucket]); + +@@ -3754,6 +3773,12 @@ + DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", + buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", + dns_result_totext(dev->result)); ++ /* ++ * Don't record a failure unless this is the initial ++ * fetch of a chain. ++ */ ++ if (fetch->depth > 1) ++ goto out; + /* XXXMLG Don't pound on bad servers. */ + if (address_type == DNS_ADBFIND_INET) { + name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); +@@ -3785,15 +3810,14 @@ + free_adbfetch(adb, &fetch); + isc_event_free(&ev); + +- clean_finds_at_name(name, ev_status, address_type); ++ clean_finds_at_name(name, ev_status, qtotal, address_type); + + UNLOCK(&adb->namelocks[bucket]); + } + + static isc_result_t +-fetch_name(dns_adbname_t *adbname, +- isc_boolean_t start_at_zone, +- dns_rdatatype_t type) ++fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, ++ unsigned int depth, dns_rdatatype_t type) + { + isc_result_t result; + dns_adbfetch_t *fetch = NULL; +@@ -3838,12 +3862,14 @@ + result = ISC_R_NOMEMORY; + goto cleanup; + } ++ fetch->depth = depth; + +- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, +- type, name, nameservers, NULL, +- options, adb->task, fetch_callback, +- adbname, &fetch->rdataset, NULL, +- &fetch->fetch); ++ result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, ++ type, name, nameservers, NULL, ++ NULL, 0, options, depth, adb->task, ++ fetch_callback, adbname, ++ &fetch->rdataset, NULL, ++ &fetch->fetch); + if (result != ISC_R_SUCCESS) + goto cleanup; + +Index: contrib/bind9/lib/dns/include/dns/adb.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/adb.h.orig ++++ contrib/bind9/lib/dns/include/dns/adb.h +@@ -118,6 +118,8 @@ + isc_result_t result_v6; /*%< RO: v6 result */ + ISC_LINK(dns_adbfind_t) publink; /*%< RW: client use */ + ++ isc_uint32_t qtotal; ++ + /* Private */ + isc_mutex_t lock; /* locks all below */ + in_port_t port; +@@ -334,6 +336,12 @@ + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, + in_port_t port, dns_adbfind_t **find); ++isc_result_t ++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, ++ void *arg, dns_name_t *name, dns_name_t *qname, ++ dns_rdatatype_t qtype, unsigned int options, ++ isc_stdtime_t now, dns_name_t *target, in_port_t port, ++ unsigned int depth, dns_adbfind_t **find); + /*%< + * Main interface for clients. The adb will look up the name given in + * "name" and will build up a list of found addresses, and perhaps start +Index: contrib/bind9/lib/dns/include/dns/resolver.h +=================================================================== +--- contrib/bind9/lib/dns/include/dns/resolver.h.orig ++++ contrib/bind9/lib/dns/include/dns/resolver.h +@@ -82,6 +82,7 @@ + isc_sockaddr_t * client; + dns_messageid_t id; + isc_result_t vresult; ++ isc_uint32_t qtotal; + } dns_fetchevent_t; + + /* +@@ -274,6 +275,18 @@ + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp); ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, isc_uint16_t id, ++ unsigned int options, unsigned int depth, ++ isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp); + /*%< + * Recurse to answer a question. + * +@@ -575,6 +588,18 @@ + * \li resolver to be valid. + */ + ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver); ++/*% ++ * Get and set how many NS indirections will be followed when looking for ++ * nameserver addresses. ++ * ++ * Requires: ++ * \li resolver to be valid. ++ */ ++ + ISC_LANG_ENDDECLS + + #endif /* DNS_RESOLVER_H */ +Index: contrib/bind9/lib/dns/resolver.c +=================================================================== +--- contrib/bind9/lib/dns/resolver.c.orig ++++ contrib/bind9/lib/dns/resolver.c +@@ -131,6 +131,16 @@ + #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ + #endif + ++/* The default maximum number of recursions to follow before giving up. */ ++#ifndef DEFAULT_RECURSION_DEPTH ++#define DEFAULT_RECURSION_DEPTH 7 ++#endif ++ ++/* The default maximum number of iterative queries to allow before giving up. */ ++#ifndef DEFAULT_MAX_QUERIES ++#define DEFAULT_MAX_QUERIES 50 ++#endif ++ + /*% + * Maximum EDNS0 input packet size. + */ +@@ -297,6 +307,7 @@ + isc_uint64_t duration; + isc_boolean_t logged; + unsigned int querysent; ++ unsigned int totalqueries; + unsigned int referrals; + unsigned int lamecount; + unsigned int neterr; +@@ -307,6 +318,7 @@ + isc_boolean_t timeout; + dns_adbaddrinfo_t *addrinfo; + isc_sockaddr_t *client; ++ unsigned int depth; + }; + + #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') +@@ -418,6 +430,7 @@ + isc_timer_t * spillattimer; + isc_boolean_t zero_no_soa_ttl; + unsigned int query_timeout; ++ unsigned int maxdepth; + + /* Locked by lock. */ + unsigned int references; +@@ -1093,6 +1106,7 @@ + event->result == DNS_R_NCACHENXRRSET); + } + ++ event->qtotal = fctx->totalqueries; + isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event)); + count++; + } +@@ -1533,7 +1547,9 @@ + if (result != ISC_R_SUCCESS) + goto cleanup_dispatch; + } ++ + fctx->querysent++; ++ fctx->totalqueries++; + + ISC_LIST_APPEND(fctx->queries, query, link); + query->fctx->nqueries++; +@@ -2186,9 +2202,10 @@ + */ + INSIST(!SHUTTINGDOWN(fctx)); + fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; +- if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) ++ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { + want_try = ISC_TRUE; +- else { ++ fctx->totalqueries += find->qtotal; ++ } else { + fctx->findfail++; + if (fctx->pending == 0) { + /* +@@ -2471,12 +2488,13 @@ + * See what we know about this address. + */ + find = NULL; +- result = dns_adb_createfind(fctx->adb, +- res->buckets[fctx->bucketnum].task, +- fctx_finddone, fctx, name, +- &fctx->name, fctx->type, +- options, now, NULL, +- res->view->dstport, &find); ++ result = dns_adb_createfind2(fctx->adb, ++ res->buckets[fctx->bucketnum].task, ++ fctx_finddone, fctx, name, ++ &fctx->name, fctx->type, ++ options, now, NULL, ++ res->view->dstport, ++ fctx->depth + 1, &find); + if (result != ISC_R_SUCCESS) { + if (result == DNS_R_ALIAS) { + /* +@@ -2584,6 +2602,11 @@ + + res = fctx->res; + ++ if (fctx->depth > res->maxdepth) { ++ FCTXTRACE("too much NS indirection"); ++ return (DNS_R_SERVFAIL); ++ } ++ + /* + * Forwarders. + */ +@@ -3022,6 +3045,9 @@ + + REQUIRE(!ADDRWAIT(fctx)); + ++ if (fctx->totalqueries > DEFAULT_MAX_QUERIES) ++ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); ++ + addrinfo = fctx_nextaddress(fctx); + if (addrinfo == NULL) { + /* +@@ -3380,6 +3406,7 @@ + * Normal fctx startup. + */ + fctx->state = fetchstate_active; ++ fctx->totalqueries = 0; + /* + * Reset the control event for later use in shutting down + * the fctx. +@@ -3449,6 +3476,7 @@ + event->fetch = fetch; + event->client = client; + event->id = id; ++ event->qtotal = 0; + dns_fixedname_init(&event->foundname); + + /* +@@ -3485,7 +3513,8 @@ + static isc_result_t + fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, +- unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) ++ unsigned int options, unsigned int bucketnum, unsigned int depth, ++ fetchctx_t **fctxp) + { + fetchctx_t *fctx; + isc_result_t result; +@@ -3537,6 +3566,7 @@ + fctx->state = fetchstate_init; + fctx->want_shutdown = ISC_FALSE; + fctx->cloned = ISC_FALSE; ++ fctx->depth = depth; + ISC_LIST_INIT(fctx->queries); + ISC_LIST_INIT(fctx->finds); + ISC_LIST_INIT(fctx->altfinds); +@@ -3555,6 +3585,7 @@ + fctx->pending = 0; + fctx->restarts = 0; + fctx->querysent = 0; ++ fctx->totalqueries = 0; + fctx->referrals = 0; + TIME_NOW(&fctx->start); + fctx->timeouts = 0; +@@ -7731,6 +7762,7 @@ + res->spillattimer = NULL; + res->zero_no_soa_ttl = ISC_FALSE; + res->query_timeout = DEFAULT_QUERY_TIMEOUT; ++ res->maxdepth = DEFAULT_RECURSION_DEPTH; + res->nbuckets = ntasks; + res->activebuckets = ntasks; + res->buckets = isc_mem_get(view->mctx, +@@ -8169,9 +8201,9 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { +- return (dns_resolver_createfetch2(res, name, type, domain, ++ return (dns_resolver_createfetch3(res, name, type, domain, + nameservers, forwarders, NULL, 0, +- options, task, action, arg, ++ options, 0, task, action, arg, + rdataset, sigrdataset, fetchp)); + } + +@@ -8187,6 +8219,25 @@ + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) + { ++ return (dns_resolver_createfetch3(res, name, type, domain, ++ nameservers, forwarders, client, id, ++ options, 0, task, action, arg, ++ rdataset, sigrdataset, fetchp)); ++} ++ ++isc_result_t ++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, ++ dns_rdatatype_t type, ++ dns_name_t *domain, dns_rdataset_t *nameservers, ++ dns_forwarders_t *forwarders, ++ isc_sockaddr_t *client, dns_messageid_t id, ++ unsigned int options, unsigned int depth, ++ isc_task_t *task, ++ isc_taskaction_t action, void *arg, ++ dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset, ++ dns_fetch_t **fetchp) ++{ + dns_fetch_t *fetch; + fetchctx_t *fctx = NULL; + isc_result_t result = ISC_R_SUCCESS; +@@ -8273,11 +8324,12 @@ + + if (fctx == NULL) { + result = fctx_create(res, name, type, domain, nameservers, +- options, bucketnum, &fctx); ++ options, bucketnum, depth, &fctx); + if (result != ISC_R_SUCCESS) + goto unlock; + new_fctx = ISC_TRUE; +- } ++ } else if (fctx->depth > depth) ++ fctx->depth = depth; + + result = fctx_join(fctx, task, client, id, action, arg, + rdataset, sigrdataset, fetch); +@@ -9049,3 +9101,15 @@ + + resolver->query_timeout = seconds; + } ++ ++void ++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ resolver->maxdepth = maxdepth; ++} ++ ++unsigned int ++dns_resolver_getmaxdepth(dns_resolver_t *resolver) { ++ REQUIRE(VALID_RESOLVER(resolver)); ++ return (resolver->maxdepth); ++} +Index: contrib/bind9/lib/isccfg/namedconf.c +=================================================================== +--- contrib/bind9/lib/isccfg/namedconf.c.orig ++++ contrib/bind9/lib/isccfg/namedconf.c +@@ -1419,6 +1419,7 @@ + { "max-cache-ttl", &cfg_type_uint32, 0 }, + { "max-clients-per-query", &cfg_type_uint32, 0 }, + { "max-ncache-ttl", &cfg_type_uint32, 0 }, ++ { "max-recursion-depth", &cfg_type_uint32, 0 }, + { "max-udp-size", &cfg_type_uint32, 0 }, + { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, + { "minimal-responses", &cfg_type_boolean, 0 }, diff --git a/share/security/patches/SA-14:29/bind995.patch.asc b/share/security/patches/SA-14:29/bind995.patch.asc new file mode 100644 index 0000000000..dfeebec0ed --- /dev/null +++ b/share/security/patches/SA-14:29/bind995.patch.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABCgAGBQJUiA2RAAoJEO1n7NZdz2rnykkQAK0R3c2Y8DFGI8Fjk6GWoRZF +gVvoJ3m/q3y4sGrDrG2A7NlhVnwHJGT90xw6EUmmmRHDKf2bTA4iexc4KoZ1uS1g +0sVc/4my2CbyNl6eMJF98nXN4lon0pi873Dv37jp64kL+NEiFYB18sipPKu1gJ0h +Q6j7EdZbt8ShBZUth2IGljyN57sH3qkud+xDTD8kvh+ysQ6VavPP8wEcPMHOn8MZ +UvtOa01wyR4W9kOzzGp+Ai0IVQLnJnI7NkYGT4wFNY4L5xP63F3Ct2H1AuDHKGiT +s48tKR/pKm5S3oJuDO792g+P3u2RMXffuHg1swPmQs8WN7GmRX/3PhxjxpiE9m0P +nZ8eHhmSsH4M4AlS7pTfS4lNl5N8c33VLqgzA/10q9nYM1v6DDQMCG6tvJZk9gW9 +KZ0Ubj0qAjETxoZj8R2/e8O8W6s6t8r7tocXJC/iSFDjzn7//cE2Zlvvg2/6XXah +/lxQp631w3Q3z/Y/6KMAosRUp9Lt00dH4Stol4uzcyCzFLGFSVbYM4Lo5dyQvY81 +TvYX8kXWNjrCwjals2+ERz3w0PyCx3ZMyvKKETeCtZCpbJjH3WfCT1fsQtgWEIv2 +EYuOMi4nZPEm7zeqkhwslgZC4yGp7bKBi9TOK8Yv7arqcIl+cPmc2v9Lx6rrOGJM +7BFQcixJreATnbms3rnw +=89Sx +-----END PGP SIGNATURE----- diff --git a/share/xml/advisories.xml b/share/xml/advisories.xml index f6413f5946..e2b3a65fbb 100644 --- a/share/xml/advisories.xml +++ b/share/xml/advisories.xml @@ -7,6 +7,26 @@ 2014 + + 12 + + + 10 + + + FreeBSD-SA-14:29.bind + + + + FreeBSD-SA-14:28.file + + + + FreeBSD-SA-14:27.stdio + + + + 11