Yves-Alexis Perez wrote:
> For Wheezy you need to build with -sa (since it's the first security
> upload) and target wheezy-security distribution. Then you send us the
> debdiff so we can have a quick check, and after our ACK you can upload
> to security-master and we release the DSA.

OK, see attached debdiff for unbound 1.4.17-3+deb7u2.

> For Jessie, you'll have to make a minimal upload to sid, and ask an
> unblock to the release team.

unbound 1.4.22-3 uploaded, unblock request in #772684.

-- 
Robert Edmonds
edmo...@debian.org
diff -Nru unbound-1.4.17/debian/changelog unbound-1.4.17/debian/changelog
--- unbound-1.4.17/debian/changelog     2014-06-02 16:00:34.000000000 -0400
+++ unbound-1.4.17/debian/changelog     2014-12-09 18:35:51.000000000 -0500
@@ -1,3 +1,10 @@
+unbound (1.4.17-3+deb7u2) wheezy-security; urgency=medium
+
+   * Fix CVE-2014-8602: denial of service by making resolver chase endless
+     series of delegations; closes: #772622.
+
+ -- Robert Edmonds <edmo...@debian.org>  Tue, 09 Dec 2014 18:34:57 -0500
+
 unbound (1.4.17-3+deb7u1) stable-proposed-updates; urgency=low
 
   [ Helmut Grohne ]
diff -Nru unbound-1.4.17/debian/patches/debian-changes 
unbound-1.4.17/debian/patches/debian-changes
--- unbound-1.4.17/debian/patches/debian-changes        2014-06-02 
16:01:10.000000000 -0400
+++ unbound-1.4.17/debian/patches/debian-changes        2014-12-09 
18:38:40.000000000 -0500
@@ -5,12 +5,12 @@
  information below has been extracted from the changelog. Adjust it or drop
  it.
  .
- unbound (1.4.17-3+deb7u1) stable-proposed-updates; urgency=low
+ unbound (1.4.17-3+deb7u2) wheezy-security; urgency=medium
  .
-   [ Helmut Grohne ]
-   * Fix crash when using DNSSEC and num-threads > 1; closes: #691528.
-Author: Robert S. Edmonds <edmo...@debian.org>
-Bug-Debian: http://bugs.debian.org/691528
+    * Fix CVE-2014-8602: denial of service by making resolver chase endless
+      series of delegations; closes: #772622.
+Author: Robert Edmonds <edmo...@debian.org>
+Bug-Debian: http://bugs.debian.org/772622
 
 ---
 The information above should follow the Patch Tagging Guidelines, please
@@ -112,6 +112,151 @@
        if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
        if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241"))       return 0;
        if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4"))      return 0;
+--- unbound-1.4.17.orig/iterator/iterator.c
++++ unbound-1.4.17/iterator/iterator.c
+@@ -117,6 +117,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;
+@@ -444,6 +445,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
+@@ -515,6 +536,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);
+@@ -1341,6 +1366,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);
+@@ -1470,6 +1501,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 */
+@@ -1479,6 +1511,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 */
+@@ -1508,6 +1546,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;
+               }
+@@ -1664,6 +1703,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");
+@@ -1704,6 +1744,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. */
+@@ -1749,6 +1790,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. */
+@@ -2822,6 +2864,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.17.orig/iterator/iterator.h
++++ unbound-1.4.17/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.17.orig/smallapp/unbound-control-setup.sh
 +++ unbound-1.4.17/smallapp/unbound-control-setup.sh
 @@ -157,6 +157,6 @@ chmod o-rw $SVR_BASE.pem $SVR_BASE.key $

Reply via email to