[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#772684: marked as done (unblock: unbound/1.4.22-3)



Your message dated Wed, 10 Dec 2014 05:40:03 +0000
with message-id <1418190003.5790.63.camel@adam-barratt.org.uk>
and subject line Re: Bug#772684: unblock: unbound/1.4.22-3
has caused the Debian Bug report #772684,
regarding unblock: unbound/1.4.22-3
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
772684: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=772684
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- 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 ---
--- Begin Message ---
On Tue, 2014-12-09 at 18:29 -0500, Robert Edmonds wrote:
> 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

Unblocked, thanks.

Regards,

Adam

--- End Message ---

Reply to: