!64 fix CVE-2022-3204
From: @XWwalker Reviewed-by: @seuzw Signed-off-by: @seuzw
This commit is contained in:
commit
21f47cc615
218
backport-CVE-2022-3204.patch
Normal file
218
backport-CVE-2022-3204.patch
Normal file
@ -0,0 +1,218 @@
|
||||
From 137719522a8ea5b380fbb6206d2466f402f5b554 Mon Sep 17 00:00:00 2001
|
||||
From: "W.C.A. Wijngaards" <wouter@nlnetlabs.nl>
|
||||
Date: Wed, 21 Sep 2022 11:10:38 +0200
|
||||
Subject: [PATCH] - Patch for CVE-2022-3204 Non-Responsive Delegation Attack.
|
||||
|
||||
---
|
||||
iterator/iter_delegpt.c | 3 +++
|
||||
iterator/iter_delegpt.h | 2 ++
|
||||
iterator/iter_utils.c | 3 +++
|
||||
iterator/iter_utils.h | 9 +++++++++
|
||||
iterator/iterator.c | 36 +++++++++++++++++++++++++++++++++++-
|
||||
services/cache/dns.c | 3 +++
|
||||
services/mesh.c | 7 +++++++
|
||||
services/mesh.h | 11 +++++++++++
|
||||
8 files changed, 73 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c
|
||||
index 9a672b0..55a025b 100644
|
||||
--- a/iterator/iter_delegpt.c
|
||||
+++ b/iterator/iter_delegpt.c
|
||||
@@ -76,6 +76,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(!delegpt_add_ns(copy, region, ns->name, ns->lame))
|
||||
return NULL;
|
||||
+ copy->nslist->cache_lookup_count = ns->cache_lookup_count;
|
||||
copy->nslist->resolved = ns->resolved;
|
||||
copy->nslist->got4 = ns->got4;
|
||||
copy->nslist->got6 = ns->got6;
|
||||
@@ -119,6 +120,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
ns->namelen = len;
|
||||
dp->nslist = ns;
|
||||
ns->name = regional_alloc_init(region, name, ns->namelen);
|
||||
+ ns->cache_lookup_count = 0;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
@@ -597,6 +599,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
|
||||
}
|
||||
ns->next = dp->nslist;
|
||||
dp->nslist = ns;
|
||||
+ ns->cache_lookup_count = 0;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h
|
||||
index 138eb6e..8265c71 100644
|
||||
--- a/iterator/iter_delegpt.h
|
||||
+++ b/iterator/iter_delegpt.h
|
||||
@@ -99,6 +99,8 @@ struct delegpt_ns {
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
size_t namelen;
|
||||
+ /** number of cache lookups for the name */
|
||||
+ int cache_lookup_count;
|
||||
/**
|
||||
* If the name has been resolved. false if not queried for yet.
|
||||
* true if the A, AAAA queries have been generated.
|
||||
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
|
||||
index 680c8c0..65c84fa 100644
|
||||
--- a/iterator/iter_utils.c
|
||||
+++ b/iterator/iter_utils.c
|
||||
@@ -1191,6 +1191,9 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env,
|
||||
struct delegpt_ns* ns;
|
||||
size_t num = delegpt_count_targets(dp);
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
+ if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE)
|
||||
+ continue;
|
||||
+ ns->cache_lookup_count++;
|
||||
/* get cached parentside A */
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass,
|
||||
diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
|
||||
index b2cae17..cd4e6b8 100644
|
||||
--- a/iterator/iter_utils.h
|
||||
+++ b/iterator/iter_utils.h
|
||||
@@ -60,6 +60,15 @@ struct module_qstate;
|
||||
struct sock_list;
|
||||
struct ub_packed_rrset_key;
|
||||
|
||||
+/* max number of lookups in the cache for target nameserver names.
|
||||
+ * This stops, for large delegations, N*N lookups in the cache. */
|
||||
+#define ITERATOR_NAME_CACHELOOKUP_MAX 3
|
||||
+/* max number of lookups in the cache for parentside glue for nameserver names
|
||||
+ * This stops, for larger delegations, N*N lookups in the cache.
|
||||
+ * It is a little larger than the nonpside max, so it allows a couple extra
|
||||
+ * lookups of parent side glue. */
|
||||
+#define ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE 5
|
||||
+
|
||||
/**
|
||||
* Process config options and set iterator module state.
|
||||
* Sets default values if no config is found.
|
||||
diff --git a/iterator/iterator.c b/iterator/iterator.c
|
||||
index 41a1c9a..ed7ab45 100644
|
||||
--- a/iterator/iterator.c
|
||||
+++ b/iterator/iterator.c
|
||||
@@ -1152,6 +1152,15 @@ generate_dnskey_prefetch(struct module_qstate* qstate,
|
||||
(qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD)){
|
||||
return;
|
||||
}
|
||||
+ /* we do not generate this prefetch when the query list is full,
|
||||
+ * the query is fetched, if needed, when the validator wants it.
|
||||
+ * At that time the validator waits for it, after spawning it.
|
||||
+ * This means there is one state that uses cpu and a socket, the
|
||||
+ * spawned while this one waits, and not several at the same time,
|
||||
+ * if we had created the lookup here. And this helps to keep
|
||||
+ * the total load down, but the query still succeeds to resolve. */
|
||||
+ if(mesh_jostle_exceeded(qstate->env->mesh))
|
||||
+ return;
|
||||
|
||||
/* if the DNSKEY is in the cache this lookup will stop quickly */
|
||||
log_nametypeclass(VERB_ALGO, "schedule dnskey prefetch",
|
||||
@@ -1869,6 +1878,14 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
query_count++;
|
||||
+ /* If the mesh query list is full, exit the loop here.
|
||||
+ * This makes the routine spawn one query at a time,
|
||||
+ * and this means there is no query state load
|
||||
+ * increase, because the spawned state uses cpu and a
|
||||
+ * socket while this state waits for that spawned
|
||||
+ * state. Next time we can look up further targets */
|
||||
+ if(mesh_jostle_exceeded(qstate->env->mesh))
|
||||
+ break;
|
||||
}
|
||||
/* Send the A request. */
|
||||
if(ie->supports_ipv4 && !ns->got4) {
|
||||
@@ -1881,6 +1898,9 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
query_count++;
|
||||
+ /* If the mesh query list is full, exit the loop. */
|
||||
+ if(mesh_jostle_exceeded(qstate->env->mesh))
|
||||
+ break;
|
||||
}
|
||||
|
||||
/* mark this target as in progress. */
|
||||
@@ -2038,6 +2058,15 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
ns->done_pside6 = 1;
|
||||
query_count++;
|
||||
+ if(mesh_jostle_exceeded(qstate->env->mesh)) {
|
||||
+ /* Wait for the lookup; do not spawn multiple
|
||||
+ * lookups at a time. */
|
||||
+ 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;
|
||||
+ }
|
||||
}
|
||||
if(ie->supports_ipv4 && !ns->done_pside4) {
|
||||
/* Send the A request. */
|
||||
@@ -2405,7 +2434,12 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(iq->depth < ie->max_dependency_depth
|
||||
&& iq->num_target_queries == 0
|
||||
&& (!iq->target_count || iq->target_count[2]==0)
|
||||
- && iq->sent_count < TARGET_FETCH_STOP) {
|
||||
+ && iq->sent_count < TARGET_FETCH_STOP
|
||||
+ /* if the mesh query list is full, then do not waste cpu
|
||||
+ * and sockets to fetch promiscuous targets. They can be
|
||||
+ * looked up when needed. */
|
||||
+ && !mesh_jostle_exceeded(qstate->env->mesh)
|
||||
+ ) {
|
||||
tf_policy = ie->target_fetch_policy[iq->depth];
|
||||
}
|
||||
|
||||
diff --git a/services/cache/dns.c b/services/cache/dns.c
|
||||
index 6366183..d1098d9 100644
|
||||
--- a/services/cache/dns.c
|
||||
+++ b/services/cache/dns.c
|
||||
@@ -404,6 +404,9 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
struct ub_packed_rrset_key* akey;
|
||||
time_t now = *env->now;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
+ if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX)
|
||||
+ continue;
|
||||
+ ns->cache_lookup_count++;
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
diff --git a/services/mesh.c b/services/mesh.c
|
||||
index 8b4a59f..3648797 100644
|
||||
--- a/services/mesh.c
|
||||
+++ b/services/mesh.c
|
||||
@@ -2031,3 +2031,10 @@ mesh_serve_expired_callback(void* arg)
|
||||
mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c);
|
||||
}
|
||||
}
|
||||
+
|
||||
+int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
+{
|
||||
+ if(mesh->all.count < mesh->max_reply_states)
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
diff --git a/services/mesh.h b/services/mesh.h
|
||||
index df2972a..739236b 100644
|
||||
--- a/services/mesh.h
|
||||
+++ b/services/mesh.h
|
||||
@@ -672,4 +672,15 @@ struct dns_msg*
|
||||
mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
struct query_info* lookup_qinfo);
|
||||
|
||||
+/**
|
||||
+ * See if the mesh has space for more queries. You can allocate queries
|
||||
+ * anyway, but this checks for the allocated space.
|
||||
+ * @param mesh: mesh area.
|
||||
+ * @return true if the query list is full.
|
||||
+ * It checks the number of all queries, not just number of reply states,
|
||||
+ * that have a client address. So that spawned queries count too,
|
||||
+ * that were created by the iterator, or other modules.
|
||||
+ */
|
||||
+int mesh_jostle_exceeded(struct mesh_area* mesh);
|
||||
+
|
||||
#endif /* SERVICES_MESH_H */
|
||||
--
|
||||
2.33.0
|
||||
|
||||
20
unbound.spec
20
unbound.spec
@ -2,7 +2,7 @@
|
||||
|
||||
Name: unbound
|
||||
Version: 1.11.0
|
||||
Release: 7
|
||||
Release: 8
|
||||
Summary: Unbound is a validating, recursive, caching DNS resolver
|
||||
License: BSD
|
||||
Url: https://nlnetlabs.nl/projects/unbound/about/
|
||||
@ -22,12 +22,12 @@ Source12: unbound-anchor.timer
|
||||
Source13: unbound-anchor.service
|
||||
|
||||
Patch0: CVE-2020-28935.patch
|
||||
|
||||
Patch6000: backport-fix-610-undefine-shift-in-sldns_str2wire_hip_buf.patch
|
||||
Patch6001: backport-fix-for-611-integer-overflow-in-sldns_wire2str_pkt_s.patch
|
||||
Patch6002: backport-fix-q-doesnt-work-when-use-with-unbound-control-stats_shm.patch
|
||||
Patch6003: backport-0001-CVE-2022-30698-and-CVE-2022-30699.patch
|
||||
Patch6004: backport-0002-CVE-2022-30698-and-CVE-2022-30699.patch
|
||||
Patch1: backport-fix-610-undefine-shift-in-sldns_str2wire_hip_buf.patch
|
||||
Patch2: backport-fix-for-611-integer-overflow-in-sldns_wire2str_pkt_s.patch
|
||||
Patch3: backport-fix-q-doesnt-work-when-use-with-unbound-control-stats_shm.patch
|
||||
Patch4: backport-0001-CVE-2022-30698-and-CVE-2022-30699.patch
|
||||
Patch5: backport-0002-CVE-2022-30698-and-CVE-2022-30699.patch
|
||||
Patch6: backport-CVE-2022-3204.patch
|
||||
|
||||
BuildRequires: make flex swig pkgconfig systemd python-unversioned-command
|
||||
BuildRequires: libevent-devel expat-devel openssl-devel python3-devel
|
||||
@ -230,6 +230,12 @@ popd
|
||||
%{_mandir}/man*
|
||||
|
||||
%changelog
|
||||
* Thu Sep 22 2022 xingwei <xingwei14@h-partners.com> - 1.11.0-8
|
||||
- Type:cves
|
||||
- CVE:CVE-2022-3204
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2022-3204
|
||||
|
||||
* Mon Sep 05 2022 gaihuiying <eaglegai@163.com> - 1.11.0-7
|
||||
- Type:bugfix
|
||||
- CVE:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user