Author: delphij
Date: Wed Dec 10 08:36:40 2014
New Revision: 275672
URL: https://svnweb.freebsd.org/changeset/base/275672

Log:
  Fix multiple vulnerabilities in file(1) and libmagic(3).
  
  Security:     FreeBSD-SA-14:28.file
  Security:     CVE-2014-3710, CVE-2014-8116, CVE-2014-8117
  
  Fix BIND remote denial of service vulnerability.
  
  Security:     FreeBSD-SA-14:29.bind
  Security:     CVE-2014-8500
  
  Approved by:  so

Added:
  releng/8.4/contrib/bind9/lib/isc/counter.c   (contents, props changed)
  releng/8.4/contrib/bind9/lib/isc/include/isc/counter.h   (contents, props 
changed)
  releng/9.1/contrib/bind9/lib/isc/counter.c   (contents, props changed)
  releng/9.1/contrib/bind9/lib/isc/include/isc/counter.h   (contents, props 
changed)
  releng/9.2/contrib/bind9/lib/isc/counter.c   (contents, props changed)
  releng/9.2/contrib/bind9/lib/isc/include/isc/counter.h   (contents, props 
changed)
Modified:
  releng/8.4/UPDATING
  releng/8.4/contrib/bind9/CHANGES
  releng/8.4/contrib/bind9/bin/named/config.c
  releng/8.4/contrib/bind9/bin/named/query.c
  releng/8.4/contrib/bind9/bin/named/server.c
  releng/8.4/contrib/bind9/lib/dns/adb.c
  releng/8.4/contrib/bind9/lib/dns/include/dns/adb.h
  releng/8.4/contrib/bind9/lib/dns/include/dns/resolver.h
  releng/8.4/contrib/bind9/lib/dns/resolver.c
  releng/8.4/contrib/bind9/lib/export/isc/Makefile.in
  releng/8.4/contrib/bind9/lib/isc/Makefile.in
  releng/8.4/contrib/bind9/lib/isc/include/isc/Makefile.in
  releng/8.4/contrib/bind9/lib/isc/include/isc/types.h
  releng/8.4/contrib/bind9/lib/isccfg/namedconf.c
  releng/8.4/contrib/file/elfclass.h
  releng/8.4/contrib/file/readelf.c
  releng/8.4/contrib/file/softmagic.c
  releng/8.4/lib/bind/isc/Makefile
  releng/8.4/sys/conf/newvers.sh
  releng/9.1/UPDATING
  releng/9.1/contrib/bind9/CHANGES
  releng/9.1/contrib/bind9/bin/named/config.c
  releng/9.1/contrib/bind9/bin/named/query.c
  releng/9.1/contrib/bind9/bin/named/server.c
  releng/9.1/contrib/bind9/lib/dns/adb.c
  releng/9.1/contrib/bind9/lib/dns/include/dns/adb.h
  releng/9.1/contrib/bind9/lib/dns/include/dns/resolver.h
  releng/9.1/contrib/bind9/lib/dns/resolver.c
  releng/9.1/contrib/bind9/lib/export/isc/Makefile.in
  releng/9.1/contrib/bind9/lib/isc/Makefile.in
  releng/9.1/contrib/bind9/lib/isc/include/isc/Makefile.in
  releng/9.1/contrib/bind9/lib/isc/include/isc/types.h
  releng/9.1/contrib/bind9/lib/isccfg/namedconf.c
  releng/9.1/contrib/file/elfclass.h
  releng/9.1/contrib/file/readelf.c
  releng/9.1/contrib/file/softmagic.c
  releng/9.1/lib/bind/isc/Makefile
  releng/9.1/sys/conf/newvers.sh
  releng/9.2/UPDATING
  releng/9.2/contrib/bind9/CHANGES
  releng/9.2/contrib/bind9/bin/named/config.c
  releng/9.2/contrib/bind9/bin/named/query.c
  releng/9.2/contrib/bind9/bin/named/server.c
  releng/9.2/contrib/bind9/lib/dns/adb.c
  releng/9.2/contrib/bind9/lib/dns/include/dns/adb.h
  releng/9.2/contrib/bind9/lib/dns/include/dns/resolver.h
  releng/9.2/contrib/bind9/lib/dns/resolver.c
  releng/9.2/contrib/bind9/lib/export/isc/Makefile.in
  releng/9.2/contrib/bind9/lib/isc/Makefile.in
  releng/9.2/contrib/bind9/lib/isc/include/isc/Makefile.in
  releng/9.2/contrib/bind9/lib/isc/include/isc/types.h
  releng/9.2/contrib/bind9/lib/isccfg/namedconf.c
  releng/9.2/contrib/file/elfclass.h
  releng/9.2/contrib/file/readelf.c
  releng/9.2/contrib/file/softmagic.c
  releng/9.2/lib/bind/isc/Makefile
  releng/9.2/sys/conf/newvers.sh
  releng/9.3/UPDATING
  releng/9.3/contrib/bind9/CHANGES
  releng/9.3/contrib/bind9/bin/named/config.c
  releng/9.3/contrib/bind9/bin/named/query.c
  releng/9.3/contrib/bind9/bin/named/server.c
  releng/9.3/contrib/bind9/lib/dns/adb.c
  releng/9.3/contrib/bind9/lib/dns/include/dns/adb.h
  releng/9.3/contrib/bind9/lib/dns/include/dns/resolver.h
  releng/9.3/contrib/bind9/lib/dns/resolver.c
  releng/9.3/contrib/bind9/lib/isccfg/namedconf.c
  releng/9.3/contrib/file/elfclass.h
  releng/9.3/contrib/file/readelf.c
  releng/9.3/contrib/file/softmagic.c
  releng/9.3/sys/conf/newvers.sh

Modified: releng/8.4/UPDATING
==============================================================================
--- releng/8.4/UPDATING Wed Dec 10 08:36:07 2014        (r275671)
+++ releng/8.4/UPDATING Wed Dec 10 08:36:40 2014        (r275672)
@@ -15,6 +15,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.
        debugging tools present in HEAD were left in place because
        sun4v support still needs work to become production ready.
 
+20141210:      p20     FreeBSD-SA-14:28.file
+                       FreeBSD-SA-14:29.bind
+
+       Fix multiple vulnerabilities in file(1) and libmagic(3).
+       [SA-14:28]
+
+       Fix BIND remote denial of service vulnerability. [SA-14:29]
+
 20141104:      p19     FreeBSD-SA-14:25.setlogin
                        FreeBSD-SA-14:26.ftp
                        FreeBSD-EN-14:12.zfs

Modified: releng/8.4/contrib/bind9/CHANGES
==============================================================================
--- releng/8.4/contrib/bind9/CHANGES    Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/bind9/CHANGES    Wed Dec 10 08:36:40 2014        
(r275672)
@@ -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

Modified: releng/8.4/contrib/bind9/bin/named/config.c
==============================================================================
--- releng/8.4/contrib/bind9/bin/named/config.c Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/bind9/bin/named/config.c Wed Dec 10 08:36:40 2014        
(r275672)
@@ -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 <config.h>
@@ -158,6 +156,8 @@ options {\n\
        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\

Modified: releng/8.4/contrib/bind9/bin/named/query.c
==============================================================================
--- releng/8.4/contrib/bind9/bin/named/query.c  Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/bind9/bin/named/query.c  Wed Dec 10 08:36:40 2014        
(r275672)
@@ -3755,12 +3755,11 @@ query_recurse(ns_client_t *client, dns_r
                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);
 

Modified: releng/8.4/contrib/bind9/bin/named/server.c
==============================================================================
--- releng/8.4/contrib/bind9/bin/named/server.c Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/bind9/bin/named/server.c Wed Dec 10 08:36:40 2014        
(r275672)
@@ -2580,6 +2580,16 @@ configure_view(dns_view_t *view, cfg_obj
                                        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);

Modified: releng/8.4/contrib/bind9/lib/dns/adb.c
==============================================================================
--- releng/8.4/contrib/bind9/lib/dns/adb.c      Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/bind9/lib/dns/adb.c      Wed Dec 10 08:36:40 2014        
(r275672)
@@ -201,6 +201,7 @@ struct dns_adbfetch {
        unsigned int                    magic;
        dns_fetch_t                    *fetch;
        dns_rdataset_t                  rdataset;
+       unsigned int                    depth;
 };
 
 /*%
@@ -300,8 +301,7 @@ static inline isc_boolean_t dec_entry_re
 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 void cancel_fetches_at_name(dns_a
 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 @@ dns_adb_createfind(dns_adb_t *adb, isc_t
                   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 @@ dns_adb_createfind(dns_adb_t *adb, isc_t
                 * 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 @@ dns_adb_createfind(dns_adb_t *adb, isc_t
                 * 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 @@ fetch_callback(isc_task_t *task, isc_eve
                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 @@ fetch_callback(isc_task_t *task, isc_eve
 }
 
 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 @@ fetch_name(dns_adbname_t *adbname,
                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;
 

Modified: releng/8.4/contrib/bind9/lib/dns/include/dns/adb.h
==============================================================================
--- releng/8.4/contrib/bind9/lib/dns/include/dns/adb.h  Wed Dec 10 08:36:07 
2014        (r275671)
+++ releng/8.4/contrib/bind9/lib/dns/include/dns/adb.h  Wed Dec 10 08:36:40 
2014        (r275672)
@@ -334,6 +334,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_t
                   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

Modified: releng/8.4/contrib/bind9/lib/dns/include/dns/resolver.h
==============================================================================
--- releng/8.4/contrib/bind9/lib/dns/include/dns/resolver.h     Wed Dec 10 
08:36:07 2014        (r275671)
+++ releng/8.4/contrib/bind9/lib/dns/include/dns/resolver.h     Wed Dec 10 
08:36:40 2014        (r275672)
@@ -271,6 +271,18 @@ dns_resolver_createfetch2(dns_resolver_t
                          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 @@ dns_resolver_printbadcache(dns_resolver_
  * \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 */

Modified: releng/8.4/contrib/bind9/lib/dns/resolver.c
==============================================================================
--- releng/8.4/contrib/bind9/lib/dns/resolver.c Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/bind9/lib/dns/resolver.c Wed Dec 10 08:36:40 2014        
(r275672)
@@ -21,6 +21,7 @@
 
 #include <config.h>
 
+#include <isc/counter.h>
 #include <isc/platform.h>
 #include <isc/print.h>
 #include <isc/string.h>
@@ -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 @@ struct fetchctx {
        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 @@ struct fetchctx {
        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 @@ struct dns_resolver {
        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 @@ fctx_query(fetchctx_t *fctx, dns_adbaddr
                if (result != ISC_R_SUCCESS)
                        goto cleanup_dispatch;
        }
+
        fctx->querysent++;
 
        ISC_LIST_APPEND(fctx->queries, query, link);
@@ -2210,9 +2226,9 @@ fctx_finddone(isc_task_t *task, isc_even
                 */
                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 @@ fctx_finddone(isc_task_t *task, isc_even
        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 @@ findname(fetchctx_t *fctx, dns_name_t *n
         * 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 @@ fctx_getaddresses(fetchctx_t *fctx, isc_
 
        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 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t
                }
        }
 
+       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 @@ fctx_destroy(fetchctx_t *fctx) {
                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 @@ log_ns_ttl(fetchctx_t *fctx, const char 
 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_create(dns_resolver_t *res, dns_nam
        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_create(dns_resolver_t *res, dns_nam
        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_create(dns_resolver_t *res, dns_nam
        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 @@ fctx_create(dns_resolver_t *res, dns_nam
  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 @@ noanswer_response(fetchctx_t *fctx, dns_
                                        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 @@ noanswer_response(fetchctx_t *fctx, dns_
                                        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 @@ dns_resolver_create(dns_view_t *view,
        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_resolver_createfetch(dns_resolver_t 
                         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_resolver_createfetch2(dns_resolver_t
                          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 @@ dns_resolver_createfetch2(dns_resolver_t
 
        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 @@ dns_resolver_settimeout(dns_resolver_t *
 
        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);
+}

Modified: releng/8.4/contrib/bind9/lib/export/isc/Makefile.in
==============================================================================
--- releng/8.4/contrib/bind9/lib/export/isc/Makefile.in Wed Dec 10 08:36:07 
2014        (r275671)
+++ releng/8.4/contrib/bind9/lib/export/isc/Makefile.in Wed Dec 10 08:36:40 
2014        (r275672)
@@ -63,7 +63,7 @@ WIN32OBJS =   win32/condition.@O@ win32/d
 # 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 @@ ISCDRIVERSRCS =       mem.c task.c lib.c timer
 
 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 \

Modified: releng/8.4/contrib/bind9/lib/isc/Makefile.in
==============================================================================
--- releng/8.4/contrib/bind9/lib/isc/Makefile.in        Wed Dec 10 08:36:07 
2014        (r275671)
+++ releng/8.4/contrib/bind9/lib/isc/Makefile.in        Wed Dec 10 08:36:40 
2014        (r275672)
@@ -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 @@ WIN32OBJS =   win32/condition.@O@ win32/d
 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 @@ SYMTBLOBJS =  backtrace-emptytbl.@O@
 # 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 \

Added: releng/8.4/contrib/bind9/lib/isc/counter.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ releng/8.4/contrib/bind9/lib/isc/counter.c  Wed Dec 10 08:36:40 2014        
(r275672)
@@ -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 <config.h>
+
+#include <stddef.h>
+
+#include <isc/counter.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#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);
+}

Modified: releng/8.4/contrib/bind9/lib/isc/include/isc/Makefile.in
==============================================================================
--- releng/8.4/contrib/bind9/lib/isc/include/isc/Makefile.in    Wed Dec 10 
08:36:07 2014        (r275671)
+++ releng/8.4/contrib/bind9/lib/isc/include/isc/Makefile.in    Wed Dec 10 
08:36:40 2014        (r275672)
@@ -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 @@ top_srcdir =  @top_srcdir@
 # 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 \

Added: releng/8.4/contrib/bind9/lib/isc/include/isc/counter.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ releng/8.4/contrib/bind9/lib/isc/include/isc/counter.h      Wed Dec 10 
08:36:40 2014        (r275672)
@@ -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 <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+/*****
+ ***** 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 */

Modified: releng/8.4/contrib/bind9/lib/isc/include/isc/types.h
==============================================================================
--- releng/8.4/contrib/bind9/lib/isc/include/isc/types.h        Wed Dec 10 
08:36:07 2014        (r275671)
+++ releng/8.4/contrib/bind9/lib/isc/include/isc/types.h        Wed Dec 10 
08:36:40 2014        (r275672)
@@ -50,6 +50,7 @@ typedef struct isc_buffer             isc_buffer_t;
 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 */

Modified: releng/8.4/contrib/bind9/lib/isccfg/namedconf.c
==============================================================================
--- releng/8.4/contrib/bind9/lib/isccfg/namedconf.c     Wed Dec 10 08:36:07 
2014        (r275671)
+++ releng/8.4/contrib/bind9/lib/isccfg/namedconf.c     Wed Dec 10 08:36:40 
2014        (r275672)
@@ -15,8 +15,6 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id$ */
-
 /*! \file */
 
 #include <config.h>
@@ -1348,6 +1346,8 @@ view_clauses[] = {
        { "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 },

Modified: releng/8.4/contrib/file/elfclass.h
==============================================================================
--- releng/8.4/contrib/file/elfclass.h  Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/file/elfclass.h  Wed Dec 10 08:36:40 2014        
(r275672)
@@ -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)

Modified: releng/8.4/contrib/file/readelf.c
==============================================================================
--- releng/8.4/contrib/file/readelf.c   Wed Dec 10 08:36:07 2014        
(r275671)
+++ releng/8.4/contrib/file/readelf.c   Wed Dec 10 08:36:40 2014        
(r275672)
@@ -60,6 +60,18 @@ private uint16_t getu16(int, uint16_t);
 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 @@ donote(struct magic_set *ms, void *vbuf,
        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",

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to