From 5c48e47c17fbf6a8624ea6b5c867ed937a8670b0 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Dec 12 2014 02:04:10 +0000 Subject: import bind-9.9.4-14.el7_0.1 --- 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