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 $