summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-networking/recipes-support/unbound/unbound/CVE-2022-3204.patch221
-rw-r--r--meta-networking/recipes-support/unbound/unbound_1.15.0.bb1
2 files changed, 222 insertions, 0 deletions
diff --git a/meta-networking/recipes-support/unbound/unbound/CVE-2022-3204.patch b/meta-networking/recipes-support/unbound/unbound/CVE-2022-3204.patch
new file mode 100644
index 0000000000..fb8fc5c1fe
--- /dev/null
+++ b/meta-networking/recipes-support/unbound/unbound/CVE-2022-3204.patch
@@ -0,0 +1,221 @@
1From 137719522a8ea5b380fbb6206d2466f402f5b554 Mon Sep 17 00:00:00 2001
2From: "W.C.A. Wijngaards" <wouter@nlnetlabs.nl>
3Date: Wed, 21 Sep 2022 11:10:38 +0200
4Subject: [PATCH] - Patch for CVE-2022-3204 Non-Responsive Delegation Attack.
5
6Upstream-Status: Backport [https://github.com/NLnetLabs/unbound/commit/137719522a8ea5b380fbb6206d2466f402f5b554]
7CVE: CVE-2022-3204
8Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
9---
10 iterator/iter_delegpt.c | 3 +++
11 iterator/iter_delegpt.h | 2 ++
12 iterator/iter_utils.c | 3 +++
13 iterator/iter_utils.h | 9 +++++++++
14 iterator/iterator.c | 36 +++++++++++++++++++++++++++++++++++-
15 services/cache/dns.c | 3 +++
16 services/mesh.c | 7 +++++++
17 services/mesh.h | 11 +++++++++++
18 8 files changed, 73 insertions(+), 1 deletion(-)
19
20diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c
21index 80148e810..10e8f5f30 100644
22--- a/iterator/iter_delegpt.c
23+++ b/iterator/iter_delegpt.c
24@@ -78,6 +78,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
25 if(!delegpt_add_ns(copy, region, ns->name, ns->lame,
26 ns->tls_auth_name, ns->port))
27 return NULL;
28+ copy->nslist->cache_lookup_count = ns->cache_lookup_count;
29 copy->nslist->resolved = ns->resolved;
30 copy->nslist->got4 = ns->got4;
31 copy->nslist->got6 = ns->got6;
32@@ -121,6 +122,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
33 ns->namelen = len;
34 dp->nslist = ns;
35 ns->name = regional_alloc_init(region, name, ns->namelen);
36+ ns->cache_lookup_count = 0;
37 ns->resolved = 0;
38 ns->got4 = 0;
39 ns->got6 = 0;
40@@ -613,6 +615,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
41 }
42 ns->next = dp->nslist;
43 dp->nslist = ns;
44+ ns->cache_lookup_count = 0;
45 ns->resolved = 0;
46 ns->got4 = 0;
47 ns->got6 = 0;
48diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h
49index 17db15a23..886c33a8e 100644
50--- a/iterator/iter_delegpt.h
51+++ b/iterator/iter_delegpt.h
52@@ -101,6 +101,8 @@ struct delegpt_ns {
53 uint8_t* name;
54 /** length of name */
55 size_t namelen;
56+ /** number of cache lookups for the name */
57+ int cache_lookup_count;
58 /**
59 * If the name has been resolved. false if not queried for yet.
60 * true if the A, AAAA queries have been generated.
61diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
62index 8480f41d1..65af304cf 100644
63--- a/iterator/iter_utils.c
64+++ b/iterator/iter_utils.c
65@@ -1195,6 +1195,9 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env,
66 struct delegpt_ns* ns;
67 size_t num = delegpt_count_targets(dp);
68 for(ns = dp->nslist; ns; ns = ns->next) {
69+ if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE)
70+ continue;
71+ ns->cache_lookup_count++;
72 /* get cached parentside A */
73 akey = rrset_cache_lookup(env->rrset_cache, ns->name,
74 ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass,
75diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
76index 660d6dc16..75e08d77b 100644
77--- a/iterator/iter_utils.h
78+++ b/iterator/iter_utils.h
79@@ -62,6 +62,15 @@ struct ub_packed_rrset_key;
80 struct module_stack;
81 struct outside_network;
82
83+/* max number of lookups in the cache for target nameserver names.
84+ * This stops, for large delegations, N*N lookups in the cache. */
85+#define ITERATOR_NAME_CACHELOOKUP_MAX 3
86+/* max number of lookups in the cache for parentside glue for nameserver names
87+ * This stops, for larger delegations, N*N lookups in the cache.
88+ * It is a little larger than the nonpside max, so it allows a couple extra
89+ * lookups of parent side glue. */
90+#define ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE 5
91+
92 /**
93 * Process config options and set iterator module state.
94 * Sets default values if no config is found.
95diff --git a/iterator/iterator.c b/iterator/iterator.c
96index 02741d0b4..66e9c68a0 100644
97--- a/iterator/iterator.c
98+++ b/iterator/iterator.c
99@@ -1206,6 +1206,15 @@ generate_dnskey_prefetch(struct module_qstate* qstate,
100 (qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD)){
101 return;
102 }
103+ /* we do not generate this prefetch when the query list is full,
104+ * the query is fetched, if needed, when the validator wants it.
105+ * At that time the validator waits for it, after spawning it.
106+ * This means there is one state that uses cpu and a socket, the
107+ * spawned while this one waits, and not several at the same time,
108+ * if we had created the lookup here. And this helps to keep
109+ * the total load down, but the query still succeeds to resolve. */
110+ if(mesh_jostle_exceeded(qstate->env->mesh))
111+ return;
112
113 /* if the DNSKEY is in the cache this lookup will stop quickly */
114 log_nametypeclass(VERB_ALGO, "schedule dnskey prefetch",
115@@ -1893,6 +1902,14 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
116 return 0;
117 }
118 query_count++;
119+ /* If the mesh query list is full, exit the loop here.
120+ * This makes the routine spawn one query at a time,
121+ * and this means there is no query state load
122+ * increase, because the spawned state uses cpu and a
123+ * socket while this state waits for that spawned
124+ * state. Next time we can look up further targets */
125+ if(mesh_jostle_exceeded(qstate->env->mesh))
126+ break;
127 }
128 /* Send the A request. */
129 if(ie->supports_ipv4 && !ns->got4) {
130@@ -1905,6 +1922,9 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
131 return 0;
132 }
133 query_count++;
134+ /* If the mesh query list is full, exit the loop. */
135+ if(mesh_jostle_exceeded(qstate->env->mesh))
136+ break;
137 }
138
139 /* mark this target as in progress. */
140@@ -2064,6 +2084,15 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
141 }
142 ns->done_pside6 = 1;
143 query_count++;
144+ if(mesh_jostle_exceeded(qstate->env->mesh)) {
145+ /* Wait for the lookup; do not spawn multiple
146+ * lookups at a time. */
147+ verbose(VERB_ALGO, "try parent-side glue lookup");
148+ iq->num_target_queries += query_count;
149+ target_count_increase(iq, query_count);
150+ qstate->ext_state[id] = module_wait_subquery;
151+ return 0;
152+ }
153 }
154 if(ie->supports_ipv4 && !ns->done_pside4) {
155 /* Send the A request. */
156@@ -2434,7 +2463,12 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
157 if(iq->depth < ie->max_dependency_depth
158 && iq->num_target_queries == 0
159 && (!iq->target_count || iq->target_count[2]==0)
160- && iq->sent_count < TARGET_FETCH_STOP) {
161+ && iq->sent_count < TARGET_FETCH_STOP
162+ /* if the mesh query list is full, then do not waste cpu
163+ * and sockets to fetch promiscuous targets. They can be
164+ * looked up when needed. */
165+ && !mesh_jostle_exceeded(qstate->env->mesh)
166+ ) {
167 tf_policy = ie->target_fetch_policy[iq->depth];
168 }
169
170diff --git a/services/cache/dns.c b/services/cache/dns.c
171index 99faaf678..96a33df7d 100644
172--- a/services/cache/dns.c
173+++ b/services/cache/dns.c
174@@ -404,6 +404,9 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
175 struct ub_packed_rrset_key* akey;
176 time_t now = *env->now;
177 for(ns = dp->nslist; ns; ns = ns->next) {
178+ if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX)
179+ continue;
180+ ns->cache_lookup_count++;
181 akey = rrset_cache_lookup(env->rrset_cache, ns->name,
182 ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
183 if(akey) {
184diff --git a/services/mesh.c b/services/mesh.c
185index 544ca0aa1..7a62d47d4 100644
186--- a/services/mesh.c
187+++ b/services/mesh.c
188@@ -2082,3 +2082,10 @@ mesh_serve_expired_callback(void* arg)
189 mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c, &tv);
190 }
191 }
192+
193+int mesh_jostle_exceeded(struct mesh_area* mesh)
194+{
195+ if(mesh->all.count < mesh->max_reply_states)
196+ return 0;
197+ return 1;
198+}
199diff --git a/services/mesh.h b/services/mesh.h
200index d0a4b5fb3..2248178b7 100644
201--- a/services/mesh.h
202+++ b/services/mesh.h
203@@ -674,4 +674,15 @@ struct dns_msg*
204 mesh_serve_expired_lookup(struct module_qstate* qstate,
205 struct query_info* lookup_qinfo);
206
207+/**
208+ * See if the mesh has space for more queries. You can allocate queries
209+ * anyway, but this checks for the allocated space.
210+ * @param mesh: mesh area.
211+ * @return true if the query list is full.
212+ * It checks the number of all queries, not just number of reply states,
213+ * that have a client address. So that spawned queries count too,
214+ * that were created by the iterator, or other modules.
215+ */
216+int mesh_jostle_exceeded(struct mesh_area* mesh);
217+
218 #endif /* SERVICES_MESH_H */
219--
2202.25.1
221
diff --git a/meta-networking/recipes-support/unbound/unbound_1.15.0.bb b/meta-networking/recipes-support/unbound/unbound_1.15.0.bb
index 8e0cefd7b3..d289bd2d46 100644
--- a/meta-networking/recipes-support/unbound/unbound_1.15.0.bb
+++ b/meta-networking/recipes-support/unbound/unbound_1.15.0.bb
@@ -12,6 +12,7 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=5308494bc0590c0cb036afd781d78f06"
12SRC_URI = "git://github.com/NLnetLabs/unbound.git;protocol=https;branch=master \ 12SRC_URI = "git://github.com/NLnetLabs/unbound.git;protocol=https;branch=master \
13 file://0001-contrib-add-yocto-compatible-init-script.patch \ 13 file://0001-contrib-add-yocto-compatible-init-script.patch \
14 file://CVE-2022-30698_30699.patch \ 14 file://CVE-2022-30698_30699.patch \
15 file://CVE-2022-3204.patch \
15" 16"
16SRCREV = "c29b0e0a96c4d281aef40d69a11c564d6ed1a2c6" 17SRCREV = "c29b0e0a96c4d281aef40d69a11c564d6ed1a2c6"
17 18