--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Hi,
Please unblock unbound 1.4.22-3. This version addresses CVE-2014-8602,
"denial of service by making resolver chase endless series of
delegations", based on upstream's patch:
http://unbound.net/downloads/CVE-2014-8602.txt
Actually, I cherry picked upstream's svn r3289 and applied it against
the version of unbound in testing:
http://anonscm.debian.org/cgit/users/edmonds/unbound.git/commit/?h=branches/1.4.22%2bjessie&id=15037ee5f483ad5ef10ad7c99221b3b77018413b
The Debian bug tracking this issue is #772622.
This issue was found in at least three recursive DNS servers: BIND,
Unbound, and PowerDNS Recursor and was fixed in coordinated releases.
See also:
https://kb.isc.org/article/AA-01216/
"A Defect in Delegation Handling Can Be Exploited to Crash BIND"
[CVE-2014-8500]
(And Debian #772610.)
http://doc.powerdns.com/md/security/powerdns-advisory-2014-02/
"PowerDNS Recursor 3.6.1 and earlier can be made to provide bad service"
[CVE-2014-8601]
The debdiff is below.
Thanks!
diff -Nru unbound-1.4.22/debian/changelog unbound-1.4.22/debian/changelog
--- unbound-1.4.22/debian/changelog 2014-08-18 16:22:31.000000000 -0400
+++ unbound-1.4.22/debian/changelog 2014-12-09 17:55:16.000000000 -0500
@@ -1,3 +1,10 @@
+unbound (1.4.22-3) unstable; urgency=medium
+
+ * Fix CVE-2014-8602: denial of service by making resolver chase endless
+ series of delegations; closes: #772622.
+
+ -- Robert Edmonds <edmonds@debian.org> Tue, 09 Dec 2014 17:52:08 -0500
+
unbound (1.4.22-2) unstable; urgency=medium
* Drop unneeded Build-Dependency on doxygen.
diff -Nru unbound-1.4.22/debian/patches/debian-changes unbound-1.4.22/debian/patches/debian-changes
--- unbound-1.4.22/debian/patches/debian-changes 2014-08-18 16:23:10.000000000 -0400
+++ unbound-1.4.22/debian/patches/debian-changes 2014-12-09 17:58:56.000000000 -0500
@@ -5,15 +5,12 @@
information below has been extracted from the changelog. Adjust it or drop
it.
.
- unbound (1.4.22-2) unstable; urgency=medium
+ unbound (1.4.22-3) unstable; urgency=medium
.
- * Drop unneeded Build-Dependency on doxygen.
- * Drop unneeded Build-Dependency on automake. (Unbound does not use
- automake.)
- * Use dh_autotools-dev_updateconfig to update the config.{guess,sub} files
- at build time; closes: #746313.
-Author: Robert S. Edmonds <edmonds@debian.org>
-Bug-Debian: http://bugs.debian.org/746313
+ * Fix CVE-2014-8602: denial of service by making resolver chase endless
+ series of delegations; closes: #772622.
+Author: Robert Edmonds <edmonds@debian.org>
+Bug-Debian: http://bugs.debian.org/772622
---
The information above should follow the Patch Tagging Guidelines, please
@@ -66,6 +63,151 @@
If turned off, the server does not listen for control commands.
.TP 5
.B control\-interface: <ip address>
+--- unbound-1.4.22.orig/iterator/iterator.c
++++ unbound-1.4.22/iterator/iterator.c
+@@ -120,6 +120,7 @@ iter_new(struct module_qstate* qstate, i
+ iq->query_restart_count = 0;
+ iq->referral_count = 0;
+ iq->sent_count = 0;
++ iq->target_count = NULL;
+ iq->wait_priming_stub = 0;
+ iq->refetch_glue = 0;
+ iq->dnssec_expected = 0;
+@@ -445,6 +446,26 @@ handle_cname_response(struct module_qsta
+ return 1;
+ }
+
++/** create target count structure for this query */
++static void
++target_count_create(struct iter_qstate* iq)
++{
++ if(!iq->target_count) {
++ iq->target_count = (int*)calloc(2, sizeof(int));
++ /* if calloc fails we simply do not track this number */
++ if(iq->target_count)
++ iq->target_count[0] = 1;
++ }
++}
++
++static void
++target_count_increase(struct iter_qstate* iq, int num)
++{
++ target_count_create(iq);
++ if(iq->target_count)
++ iq->target_count[1] += num;
++}
++
+ /**
+ * Generate a subrequest.
+ * Generate a local request event. Local events are tied to this module, and
+@@ -516,6 +537,10 @@ generate_sub_request(uint8_t* qname, siz
+ subiq = (struct iter_qstate*)subq->minfo[id];
+ memset(subiq, 0, sizeof(*subiq));
+ subiq->num_target_queries = 0;
++ target_count_create(iq);
++ subiq->target_count = iq->target_count;
++ if(iq->target_count)
++ iq->target_count[0] ++; /* extra reference */
+ subiq->num_current_queries = 0;
+ subiq->depth = iq->depth+1;
+ outbound_list_init(&subiq->outlist);
+@@ -1342,6 +1367,12 @@ query_for_targets(struct module_qstate*
+
+ if(iq->depth == ie->max_dependency_depth)
+ return 0;
++ if(iq->depth > 0 && iq->target_count &&
++ iq->target_count[1] > MAX_TARGET_COUNT) {
++ verbose(VERB_QUERY, "request has exceeded the maximum "
++ "number of glue fetches %d", iq->target_count[1]);
++ return 0;
++ }
+
+ iter_mark_cycle_targets(qstate, iq->dp);
+ missing = (int)delegpt_count_missing_targets(iq->dp);
+@@ -1524,6 +1555,7 @@ processLastResort(struct module_qstate*
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+ iq->num_target_queries += qs;
++ target_count_increase(iq, qs);
+ if(qs != 0) {
+ qstate->ext_state[id] = module_wait_subquery;
+ return 0; /* and wait for them */
+@@ -1533,6 +1565,12 @@ processLastResort(struct module_qstate*
+ verbose(VERB_QUERY, "maxdepth and need more nameservers, fail");
+ return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
++ if(iq->depth > 0 && iq->target_count &&
++ iq->target_count[1] > MAX_TARGET_COUNT) {
++ verbose(VERB_QUERY, "request has exceeded the maximum "
++ "number of glue fetches %d", iq->target_count[1]);
++ return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
++ }
+ /* mark cycle targets for parent-side lookups */
+ iter_mark_pside_cycle_targets(qstate, iq->dp);
+ /* see if we can issue queries to get nameserver addresses */
+@@ -1562,6 +1600,7 @@ processLastResort(struct module_qstate*
+ if(query_count != 0) { /* suspend to await results */
+ verbose(VERB_ALGO, "try parent-side glue lookup");
+ iq->num_target_queries += query_count;
++ target_count_increase(iq, query_count);
+ qstate->ext_state[id] = module_wait_subquery;
+ return 0;
+ }
+@@ -1717,6 +1756,7 @@ processQueryTargets(struct module_qstate
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+ iq->num_target_queries += extra;
++ target_count_increase(iq, extra);
+ if(iq->num_target_queries > 0) {
+ /* wait to get all targets, we want to try em */
+ verbose(VERB_ALGO, "wait for all targets for fallback");
+@@ -1757,6 +1797,7 @@ processQueryTargets(struct module_qstate
+ /* errors ignored, these targets are not strictly necessary for
+ * this result, we do not have to reply with SERVFAIL */
+ iq->num_target_queries += extra;
++ target_count_increase(iq, extra);
+ }
+
+ /* Add the current set of unused targets to our queue. */
+@@ -1802,6 +1843,7 @@ processQueryTargets(struct module_qstate
+ return 1;
+ }
+ iq->num_target_queries += qs;
++ target_count_increase(iq, qs);
+ }
+ /* Since a target query might have been made, we
+ * need to check again. */
+@@ -2894,6 +2936,8 @@ iter_clear(struct module_qstate* qstate,
+ iq = (struct iter_qstate*)qstate->minfo[id];
+ if(iq) {
+ outbound_list_clear(&iq->outlist);
++ if(iq->target_count && --iq->target_count[0] == 0)
++ free(iq->target_count);
+ iq->num_current_queries = 0;
+ }
+ qstate->minfo[id] = NULL;
+--- unbound-1.4.22.orig/iterator/iterator.h
++++ unbound-1.4.22/iterator/iterator.h
+@@ -52,6 +52,8 @@ struct iter_donotq;
+ struct iter_prep_list;
+ struct iter_priv;
+
++/** max number of targets spawned for a query and its subqueries */
++#define MAX_TARGET_COUNT 32
+ /** max number of query restarts. Determines max number of CNAME chain. */
+ #define MAX_RESTART_COUNT 8
+ /** max number of referrals. Makes sure resolver does not run away */
+@@ -254,6 +256,10 @@ struct iter_qstate {
+
+ /** number of queries fired off */
+ int sent_count;
++
++ /** number of target queries spawned in [1], for this query and its
++ * subqueries, the malloced-array is shared, [0] refcount. */
++ int* target_count;
+
+ /**
+ * The query must store NS records from referrals as parentside RRs
--- unbound-1.4.22.orig/smallapp/unbound-control-setup.sh
+++ unbound-1.4.22/smallapp/unbound-control-setup.sh
@@ -157,6 +157,6 @@ chmod o-rw $SVR_BASE.pem $SVR_BASE.key $
--
Robert Edmonds
edmonds@debian.org
--- End Message ---