diff --git a/SOURCES/bind99-CVE-2014-8500.patch b/SOURCES/bind99-CVE-2014-8500.patch
new file mode 100644
index 0000000..1369769
--- /dev/null
+++ b/SOURCES/bind99-CVE-2014-8500.patch
@@ -0,0 +1,924 @@
+diff -up bind-9.9.4/bin/named/config.c.CVE-2014-8500 bind-9.9.4/bin/named/config.c
+--- bind-9.9.4/bin/named/config.c.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200
++++ bind-9.9.4/bin/named/config.c 2014-12-10 14:56:24.959552559 +0100
+@@ -160,6 +160,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\
+diff -up bind-9.9.4/bin/named/query.c.CVE-2014-8500 bind-9.9.4/bin/named/query.c
+--- bind-9.9.4/bin/named/query.c.CVE-2014-8500 2014-12-10 14:56:24.945552543 +0100
++++ bind-9.9.4/bin/named/query.c 2014-12-10 14:56:24.960552560 +0100
+@@ -3872,12 +3872,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);
+
+diff -up bind-9.9.4/bin/named/server.c.CVE-2014-8500 bind-9.9.4/bin/named/server.c
+--- bind-9.9.4/bin/named/server.c.CVE-2014-8500 2014-12-10 14:56:24.913552507 +0100
++++ bind-9.9.4/bin/named/server.c 2014-12-10 14:56:24.961552561 +0100
+@@ -3205,6 +3205,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);
+diff -up bind-9.9.4/doc/arm/Bv9ARM-book.xml.CVE-2014-8500 bind-9.9.4/doc/arm/Bv9ARM-book.xml
+--- bind-9.9.4/doc/arm/Bv9ARM-book.xml.CVE-2014-8500 2014-12-10 14:56:24.957552556 +0100
++++ bind-9.9.4/doc/arm/Bv9ARM-book.xml 2014-12-10 15:00:53.108931629 +0100
+@@ -4874,6 +4874,8 @@ badresp:1,adberr:0,findfail:0,valfail:0]
+ max-acache-size size_spec ;
+ clients-per-query number ;
+ max-clients-per-query number ;
++ max-recursion-depth number ;
++ max-recursion-queries number ;
+ masterfile-format (text|raw) ;
+ empty-server name ;
+ empty-contact name ;
+@@ -8623,6 +8625,35 @@ avoid-v6-udp-ports { 40000; range 50000
+
+
+
++
++
++ max-recursion-depth
++
++
++ Sets the maximum number of levels of recursion
++ that are permitted at any one time while servicing
++ a recursive query. Resolving a name may require
++ looking up a name server address, which in turn
++ requires resolving another name, etc; if the number
++ of indirections exceeds this value, the recursive
++ query is terminated and returns SERVFAIL. The
++ default is 7.
++
++
++
++
++
++ max-recursion-queries
++
++
++ Sets the maximum number of iterative queries that
++ may be sent while servicing a recursive query.
++ If more queries are sent, the recursive query
++ is terminated and returns SERVFAIL. The default
++ is 50.
++
++
++
+
+
+ notify-delay
+diff -up bind-9.9.4/doc/misc/options.CVE-2014-8500 bind-9.9.4/doc/misc/options
+--- bind-9.9.4/doc/misc/options.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200
++++ bind-9.9.4/doc/misc/options 2014-12-10 14:56:24.964552564 +0100
+@@ -162,6 +162,8 @@ options {
+ max-ixfr-log-size ; // obsolete
+ max-journal-size ;
+ max-ncache-ttl ;
++ max-recursion-depth ;
++ max-recursion-queries ;
+ max-refresh-time ;
+ max-retry-time ;
+ max-rsa-exponent-size ;
+@@ -385,6 +387,8 @@ view {
+ max-ixfr-log-size ; // obsolete
+ max-journal-size ;
+ max-ncache-ttl ;
++ max-recursion-depth ;
++ max-recursion-queries ;
+ max-refresh-time ;
+ max-retry-time ;
+ max-transfer-idle-in ;
+diff -up bind-9.9.4/lib/dns/adb.c.CVE-2014-8500 bind-9.9.4/lib/dns/adb.c
+--- bind-9.9.4/lib/dns/adb.c.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200
++++ bind-9.9.4/lib/dns/adb.c 2014-12-10 14:56:24.965552566 +0100
+@@ -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 *);
+@@ -2770,6 +2771,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;
+@@ -3000,7 +3014,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",
+@@ -3011,7 +3025,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: "
+@@ -3754,6 +3768,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);
+@@ -3791,9 +3811,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;
+@@ -3838,12 +3857,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;
+
+diff -up bind-9.9.4/lib/dns/include/dns/adb.h.CVE-2014-8500 bind-9.9.4/lib/dns/include/dns/adb.h
+--- bind-9.9.4/lib/dns/include/dns/adb.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200
++++ bind-9.9.4/lib/dns/include/dns/adb.h 2014-12-10 14:56:24.965552566 +0100
+@@ -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
+diff -up bind-9.9.4/lib/dns/include/dns/resolver.h.CVE-2014-8500 bind-9.9.4/lib/dns/include/dns/resolver.h
+--- bind-9.9.4/lib/dns/include/dns/resolver.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200
++++ bind-9.9.4/lib/dns/include/dns/resolver.h 2014-12-10 14:56:24.965552566 +0100
+@@ -274,6 +274,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.
+ *
+@@ -573,6 +585,30 @@ dns_resolver_printbadcache(dns_resolver_
+ *
+ * Requires:
+ * \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
+diff -up bind-9.9.4/lib/dns/resolver.c.CVE-2014-8500 bind-9.9.4/lib/dns/resolver.c
+--- bind-9.9.4/lib/dns/resolver.c.CVE-2014-8500 2014-12-10 14:56:24.952552551 +0100
++++ bind-9.9.4/lib/dns/resolver.c 2014-12-10 15:01:56.855970646 +0100
+@@ -21,6 +21,7 @@
+
+ #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.
+ */
+@@ -233,12 +244,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.
+@@ -306,6 +318,7 @@ struct fetchctx {
+ isc_boolean_t timeout;
+ dns_adbaddrinfo_t *addrinfo;
+ isc_sockaddr_t *client;
++ unsigned int depth;
+ };
+
+ #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
+@@ -418,6 +431,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;
+@@ -1533,6 +1548,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);
+@@ -2186,9 +2202,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) {
+ /*
+@@ -2471,12 +2487,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) {
+ /*
+@@ -2584,6 +2601,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.
+ */
+@@ -3059,6 +3084,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__);
+@@ -3157,6 +3192,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);
+@@ -3485,7 +3521,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;
+@@ -3507,6 +3544,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 */
+@@ -3514,7 +3566,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);
+@@ -3537,6 +3589,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);
+@@ -3742,6 +3795,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));
+
+@@ -5655,7 +5711,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));
+@@ -5664,7 +5720,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) {
+@@ -7725,6 +7781,8 @@ dns_resolver_create(dns_view_t *view,
+ res->spillattimer = NULL;
+ res->zero_no_soa_ttl = ISC_FALSE;
+ res->query_timeout = DEFAULT_QUERY_TIMEOUT;
++ res->maxdepth = DEFAULT_RECURSION_DEPTH;
++ res->maxqueries = DEFAULT_MAX_QUERIES;
+ res->nbuckets = ntasks;
+ res->activebuckets = ntasks;
+ res->buckets = isc_mem_get(view->mctx,
+@@ -8163,9 +8221,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));
+ }
+
+@@ -8181,6 +8239,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;
+@@ -8269,11 +8346,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);
+@@ -9045,3 +9123,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);
++}
+diff -up bind-9.9.4/lib/export/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/export/isc/Makefile.in
+--- bind-9.9.4/lib/export/isc/Makefile.in.CVE-2014-8500 2014-12-10 14:56:24.907552500 +0100
++++ bind-9.9.4/lib/export/isc/Makefile.in 2014-12-10 14:56:24.967552568 +0100
+@@ -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@ \
+@@ -85,7 +85,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 \
+diff -up bind-9.9.4/lib/isccfg/namedconf.c.CVE-2014-8500 bind-9.9.4/lib/isccfg/namedconf.c
+--- bind-9.9.4/lib/isccfg/namedconf.c.CVE-2014-8500 2014-12-10 14:56:24.969552570 +0100
++++ bind-9.9.4/lib/isccfg/namedconf.c 2014-12-10 15:04:14.636091707 +0100
+@@ -1421,6 +1421,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 },
+diff -up bind-9.9.4/lib/isc/counter.c.CVE-2014-8500 bind-9.9.4/lib/isc/counter.c
+--- bind-9.9.4/lib/isc/counter.c.CVE-2014-8500 2014-12-10 14:56:24.968552569 +0100
++++ bind-9.9.4/lib/isc/counter.c 2014-12-10 14:56:24.968552569 +0100
+@@ -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);
++}
+diff -up bind-9.9.4/lib/isc/include/isc/counter.h.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/counter.h
+--- bind-9.9.4/lib/isc/include/isc/counter.h.CVE-2014-8500 2014-12-10 14:56:24.968552569 +0100
++++ bind-9.9.4/lib/isc/include/isc/counter.h 2014-12-10 14:56:24.968552569 +0100
+@@ -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 */
+diff -up bind-9.9.4/lib/isc/include/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/Makefile.in
+--- bind-9.9.4/lib/isc/include/isc/Makefile.in.CVE-2014-8500 2014-12-10 15:02:34.811005903 +0100
++++ bind-9.9.4/lib/isc/include/isc/Makefile.in 2014-12-10 15:03:01.099030322 +0100
+@@ -27,7 +27,7 @@ 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 \
+diff -up bind-9.9.4/lib/isc/include/isc/types.h.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/types.h
+--- bind-9.9.4/lib/isc/include/isc/types.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200
++++ bind-9.9.4/lib/isc/include/isc/types.h 2014-12-10 14:56:24.968552569 +0100
+@@ -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 */
+diff -up bind-9.9.4/lib/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/isc/Makefile.in
+--- bind-9.9.4/lib/isc/Makefile.in.CVE-2014-8500 2014-12-10 14:56:24.860552447 +0100
++++ bind-9.9.4/lib/isc/Makefile.in 2014-12-10 14:56:24.968552569 +0100
+@@ -53,7 +53,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@ \
+@@ -70,8 +70,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 \
diff --git a/SPECS/bind.spec b/SPECS/bind.spec
index aa4cc64..6979f7c 100644
--- a/SPECS/bind.spec
+++ b/SPECS/bind.spec
@@ -29,7 +29,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv
Name: bind
License: ISC
Version: 9.9.4
-Release: 14%{?PATCHVER}%{?PREVER}%{?dist}
+Release: 14%{?PATCHVER}%{?PREVER}%{?dist}.1
Epoch: 32
Url: http://www.isc.org/products/BIND/
Buildroot:%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -93,6 +93,7 @@ Patch140:bind99-ISC-Bugs-34870-v3.patch
Patch141:bind99-ISC-Bugs-35073.patch
Patch142:bind99-ISC-Bugs-35080.patch
Patch143:bind99-CVE-2014-0591.patch
+Patch144:bind99-CVE-2014-8500.patch
# SDB patches
Patch11: bind-9.3.2b2-sdbsrc.patch
@@ -311,6 +312,7 @@ popd
%patch141 -p1 -b .leak_35073
%patch142 -p1 -b .rbt_crash
%patch143 -p1 -b .CVE-2014-059
+%patch144 -p1 -b .CVE-2014-8500
%if %{SDB}
%patch101 -p1 -b .old-api
@@ -919,6 +921,9 @@ rm -rf ${RPM_BUILD_ROOT}
%endif
%changelog
+* Wed Dec 10 2014 Tomas Hozza - 32:9.9.4-14.1
+- Fix CVE-2014-8500 (#1171975)
+
* Fri Jan 24 2014 Daniel Mach - 32:9.9.4-14
- Mass rebuild 2014-01-24