From 216132d4bfdecc900222f0bbc848ea005e504340 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 29 Jul 2025 11:27:55 +0000 Subject: [PATCH] import UBI unbound-1.20.0-12.el10_0 --- unbound-1.23.1-CVE-2025-5994.patch | 906 +++++++++++++++++++++++++++++ unbound.spec | 11 +- 2 files changed, 916 insertions(+), 1 deletion(-) create mode 100644 unbound-1.23.1-CVE-2025-5994.patch diff --git a/unbound-1.23.1-CVE-2025-5994.patch b/unbound-1.23.1-CVE-2025-5994.patch new file mode 100644 index 0000000..1b4c30c --- /dev/null +++ b/unbound-1.23.1-CVE-2025-5994.patch @@ -0,0 +1,906 @@ +commit 81cb270d19a0e016b8b74af931d9c6647ae00b16 +Author: Tomas Korbar +Date: Tue Jul 22 09:26:44 2025 +0200 + + Fix CVE-2025-5994 and add tests for it + +diff --git a/unbound-1.20.0/edns-subnet/subnetmod.c b/unbound-1.20.0/edns-subnet/subnetmod.c +index 1dff429..d31ecb3 100644 +--- a/unbound-1.20.0/edns-subnet/subnetmod.c ++++ b/unbound-1.20.0/edns-subnet/subnetmod.c +@@ -51,6 +51,7 @@ + #include "services/cache/dns.h" + #include "util/module.h" + #include "util/regional.h" ++#include "util/fptr_wlist.h" + #include "util/storage/slabhash.h" + #include "util/config_file.h" + #include "util/data/msgreply.h" +@@ -155,7 +156,8 @@ int ecs_whitelist_check(struct query_info* qinfo, + + /* Cache by default, might be disabled after parsing EDNS option + * received from nameserver. */ +- if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) { ++ if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0) ++ && sq->ecs_client_in.subnet_validdata) { + qstate->no_cache_store = 0; + } + +@@ -522,6 +524,69 @@ common_prefix(uint8_t *a, uint8_t *b, uint8_t net) + return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]); + } + ++/** ++ * Create sub request that looks up the query. ++ * @param qstate: query state ++ * @param sq: subnet qstate ++ * @return false on failure. ++ */ ++static int ++generate_sub_request(struct module_qstate *qstate, struct subnet_qstate* sq) ++{ ++ struct module_qstate* subq = NULL; ++ uint16_t qflags = 0; /* OPCODE QUERY, no flags */ ++ int prime = 0; ++ int valrec = 0; ++ struct query_info qinf; ++ qinf.qname = qstate->qinfo.qname; ++ qinf.qname_len = qstate->qinfo.qname_len; ++ qinf.qtype = qstate->qinfo.qtype; ++ qinf.qclass = qstate->qinfo.qclass; ++ qinf.local_alias = NULL; ++ ++ qflags |= BIT_RD; ++ if((qstate->query_flags & BIT_CD)!=0) { ++ qflags |= BIT_CD; ++ valrec = 1; ++ } ++ ++ fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); ++ if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec, ++ &subq)) { ++ return 0; ++ } ++ if(subq) { ++ /* It is possible to access the subquery module state. */ ++ if(sq->ecs_client_in.subnet_source_mask == 0 && ++ edns_opt_list_find(qstate->edns_opts_front_in, ++ qstate->env->cfg->client_subnet_opcode)) { ++ subq->no_cache_store = 1; ++ } ++ } ++ return 1; ++} ++ ++/** ++ * Perform the query without subnet ++ * @param qstate: query state ++ * @param sq: subnet qstate ++ * @return module state ++ */ ++static enum module_ext_state ++generate_lookup_without_subnet(struct module_qstate *qstate, ++ struct subnet_qstate* sq) ++{ ++ verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet"); ++ if(!generate_sub_request(qstate, sq)) { ++ verbose(VERB_ALGO, "Could not generate sub query"); ++ qstate->return_rcode = LDNS_RCODE_FORMERR; ++ qstate->return_msg = NULL; ++ return module_finished; ++ } ++ sq->wait_subquery = 1; ++ return module_wait_subquery; ++} ++ + static enum module_ext_state + eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) + { +@@ -557,14 +622,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) + * is still useful to put it in the edns subnet cache for + * when a client explicitly asks for subnet specific answer. */ + verbose(VERB_QUERY, "subnetcache: Authority indicates no support"); +- if(!sq->started_no_cache_store) { +- lock_rw_wrlock(&sne->biglock); +- update_cache(qstate, id); +- lock_rw_unlock(&sne->biglock); +- } +- if (sq->subnet_downstream) +- cp_edns_bad_response(c_out, c_in); +- return module_finished; ++ return generate_lookup_without_subnet(qstate, sq); + } + + /* Purposefully there was no sent subnet, and there is consequently +@@ -589,14 +647,14 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) + !common_prefix(s_out->subnet_addr, s_in->subnet_addr, + s_out->subnet_source_mask)) + { +- /* we can not accept, restart query without option */ ++ /* we can not accept, perform query without option */ + verbose(VERB_QUERY, "subnetcache: forged data"); + s_out->subnet_validdata = 0; + (void)edns_opt_list_remove(&qstate->edns_opts_back_out, + qstate->env->cfg->client_subnet_opcode); + sq->subnet_sent = 0; + sq->subnet_sent_no_subnet = 0; +- return module_restart_next; ++ return generate_lookup_without_subnet(qstate, sq); + } + + lock_rw_wrlock(&sne->biglock); +@@ -795,6 +853,9 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id, + } else if(sq->subnet_sent_no_subnet) { + /* The answer can be stored as scope 0, not in global cache. */ + qstate->no_cache_store = 1; ++ } else if(sq->subnet_sent) { ++ /* Need another query to be able to store in global cache. */ ++ qstate->no_cache_store = 1; + } + + return 1; +@@ -812,6 +873,32 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, + strmodulevent(event)); + log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo); + ++ if(sq && sq->wait_subquery_done) { ++ /* The subquery lookup returned. */ ++ if(sq->ecs_client_in.subnet_source_mask == 0 && ++ edns_opt_list_find(qstate->edns_opts_front_in, ++ qstate->env->cfg->client_subnet_opcode)) { ++ if(!sq->started_no_cache_store && ++ qstate->return_msg) { ++ lock_rw_wrlock(&sne->biglock); ++ update_cache(qstate, id); ++ lock_rw_unlock(&sne->biglock); ++ } ++ if (sq->subnet_downstream) ++ cp_edns_bad_response(&sq->ecs_client_out, ++ &sq->ecs_client_in); ++ /* It is a scope zero lookup, append edns subnet ++ * option to the querier. */ ++ subnet_ecs_opt_list_append(&sq->ecs_client_out, ++ &qstate->edns_opts_front_out, qstate, ++ qstate->region); ++ } ++ sq->wait_subquery_done = 0; ++ qstate->ext_state[id] = module_finished; ++ qstate->no_cache_store = sq->started_no_cache_store; ++ qstate->no_cache_lookup = sq->started_no_cache_lookup; ++ return; ++ } + if((event == module_event_new || event == module_event_pass) && + sq == NULL) { + struct edns_option* ecs_opt; +@@ -822,6 +909,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, + } + + sq = (struct subnet_qstate*)qstate->minfo[id]; ++ if(sq->wait_subquery) ++ return; /* Wait for that subquery to return */ + + if((ecs_opt = edns_opt_list_find( + qstate->edns_opts_front_in, +@@ -851,6 +940,14 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, + /* No clients are interested in result or we could not + * parse it, we don't do client subnet */ + sq->ecs_server_out.subnet_validdata = 0; ++ if(edns_opt_list_find(qstate->edns_opts_front_in, ++ qstate->env->cfg->client_subnet_opcode)) { ++ /* aggregated this deaggregated state */ ++ qstate->ext_state[id] = ++ generate_lookup_without_subnet( ++ qstate, sq); ++ return; ++ } + verbose(VERB_ALGO, "subnetcache: pass to next module"); + qstate->ext_state[id] = module_wait_module; + return; +@@ -891,6 +988,14 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, + } + lock_rw_unlock(&sne->biglock); + } ++ if(sq->ecs_client_in.subnet_source_mask == 0 && ++ edns_opt_list_find(qstate->edns_opts_front_in, ++ qstate->env->cfg->client_subnet_opcode)) { ++ /* client asked for resolution without edns subnet */ ++ qstate->ext_state[id] = generate_lookup_without_subnet( ++ qstate, sq); ++ return; ++ } + + sq->ecs_server_out.subnet_addr_fam = + sq->ecs_client_in.subnet_addr_fam; +@@ -927,6 +1032,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, + qstate->ext_state[id] = module_wait_module; + return; + } ++ if(sq && sq->wait_subquery) ++ return; /* Wait for that subquery to return */ + /* Query handed back by next module, we have a 'final' answer */ + if(sq && event == module_event_moddone) { + qstate->ext_state[id] = eval_response(qstate, id, sq); +@@ -975,10 +1082,27 @@ subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate), + } + + void +-subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate), +- int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) ++subnetmod_inform_super(struct module_qstate *qstate, int id, ++ struct module_qstate *super) + { +- /* Not used */ ++ struct subnet_qstate* super_sq = ++ (struct subnet_qstate*)super->minfo[id]; ++ log_query_info(VERB_ALGO, "subnetcache inform_super: query", ++ &super->qinfo); ++ super_sq->wait_subquery = 0; ++ super_sq->wait_subquery_done = 1; ++ if(qstate->return_rcode != LDNS_RCODE_NOERROR || ++ !qstate->return_msg) { ++ super->return_msg = NULL; ++ super->return_rcode = LDNS_RCODE_SERVFAIL; ++ return; ++ } ++ super->return_rcode = LDNS_RCODE_NOERROR; ++ super->return_msg = dns_copy_msg(qstate->return_msg, super->region); ++ if(!super->return_msg) { ++ log_err("subnetcache: copy response, out of memory"); ++ super->return_rcode = LDNS_RCODE_SERVFAIL; ++ } + } + + size_t +diff --git a/unbound-1.20.0/edns-subnet/subnetmod.h b/unbound-1.20.0/edns-subnet/subnetmod.h +index 1ff8a23..3893820 100644 +--- a/unbound-1.20.0/edns-subnet/subnetmod.h ++++ b/unbound-1.20.0/edns-subnet/subnetmod.h +@@ -102,6 +102,10 @@ struct subnet_qstate { + int started_no_cache_store; + /** has the subnet module been started with no_cache_lookup? */ + int started_no_cache_lookup; ++ /** Wait for subquery that has been started for nonsubnet lookup. */ ++ int wait_subquery; ++ /** The subquery waited for is done. */ ++ int wait_subquery_done; + }; + + void subnet_data_delete(void* d, void* ATTR_UNUSED(arg)); +diff --git a/unbound-1.20.0/testdata/subnet_noecs_mult.rpl b/unbound-1.20.0/testdata/subnet_noecs_mult.rpl +new file mode 100644 +index 0000000..3e2acef +--- /dev/null ++++ b/unbound-1.20.0/testdata/subnet_noecs_mult.rpl +@@ -0,0 +1,334 @@ ++# config ++server: ++ send-client-subnet: 1.2.3.4 ++ max-client-subnet-ipv4: 17 ++ module-config: "subnetcache iterator" ++ qname-minimisation: no ++ minimal-responses: yes ++ target-fetch-policy: "0 0 0 0 0" ++ ++stub-zone: ++ name: "." ++ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. ++CONFIG_END ++ ++SCENARIO_BEGIN Test subnet with no edns subnet from server multiple times ++; Multiple queries are sent to a server that does not reply with the ++; edns-subnet option. ++ ++; K.ROOT-SERVERS.NET. ++RANGE_BEGIN 0 100 ++ ADDRESS 193.0.14.129 ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR NOERROR ++SECTION QUESTION ++. IN NS ++SECTION ANSWER ++. IN NS K.ROOT-SERVERS.NET. ++SECTION ADDITIONAL ++K.ROOT-SERVERS.NET. IN A 193.0.14.129 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++com. IN NS ++SECTION AUTHORITY ++com. IN NS a.gtld-servers.net. ++SECTION ADDITIONAL ++a.gtld-servers.net. IN A 192.5.6.30 ++ENTRY_END ++RANGE_END ++ ++; a.gtld-servers.net. ++RANGE_BEGIN 0 100 ++ ADDRESS 192.5.6.30 ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++example.com. IN NS ++SECTION AUTHORITY ++example.com. IN NS ns.example.com. ++SECTION ADDITIONAL ++ns.example.com. IN A 1.2.3.4 ++ENTRY_END ++RANGE_END ++ ++; ns.example.com. ++RANGE_BEGIN 50 52 ++ ADDRESS 1.2.3.4 ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++example.com. IN NS ++SECTION ANSWER ++example.com. IN NS ns.example.com. ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN A ++SECTION ANSWER ++ns.example.com. IN A 1.2.3.4 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN AAAA ++SECTION ANSWER ++SECTION AUTHORITY ++example.com. IN SOA ns.example.com. host.example.com. 4 86400 3600 86400 3600 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ednsdata ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++SECTION ADDITIONAL ++ ; Match this subnet option ++ HEX_EDNSDATA_BEGIN ++ ; client is 127.0.0.1 ++ 00 08 ; OPC ++ 00 07 ; option length ++ 00 01 ; Family ++ 11 00 ; source mask, scopemask ++ 7f 00 00 ; address ++ HEX_EDNSDATA_END ++ ; This is the response, without the subnet option ++ HEX_ANSWER_BEGIN; ++ 00 00 84 00 00 01 00 01 ; ID 0 QR AA NOERROR ++ 00 00 00 01 03 77 77 77 ; www.example.com A (DO) ++ 07 65 78 61 6d 70 6c 65 ++ 03 63 6f 6d 00 00 01 00 ++ 01 ++ C0 0C 00 01 00 01 00 00 0E 10 ; www.example.com. A IN 3600 ++ 00 04 0A 14 1E 2C ; rdata 10.20.30.44 ++ 00 00 29 10 00 00 00 ++ 80 00 00 00 ++ HEX_ANSWER_END ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ednsdata ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++SECTION ADDITIONAL ++ ; Match this subnet option ++ HEX_EDNSDATA_BEGIN ++ ; client is 127.2.0.1 ++ 00 08 ; OPC ++ 00 07 ; option length ++ 00 01 ; Family ++ 11 00 ; source mask, scopemask ++ 7f 02 00 ; address ++ HEX_EDNSDATA_END ++ ; This is the response, without the subnet option ++ HEX_ANSWER_BEGIN; ++ 00 00 84 00 00 01 00 01 ; ID 0 QR AA NOERROR ++ 00 00 00 01 03 77 77 77 ; www.example.com A (DO) ++ 07 65 78 61 6d 70 6c 65 ++ 03 63 6f 6d 00 00 01 00 ++ 01 ++ C0 0C 00 01 00 01 00 00 0E 10 ; www.example.com. A IN 3600 ++ 00 04 0A 14 1E 2C ; rdata 10.20.30.44 ++ 00 00 29 10 00 00 00 ++ 80 00 00 00 ++ HEX_ANSWER_END ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ednsdata ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++SECTION ADDITIONAL ++ ; Match this subnet option ++ HEX_EDNSDATA_BEGIN ++ ; client is 127.3.0.1 ++ 00 08 ; OPC ++ 00 07 ; option length ++ 00 01 ; Family ++ 11 00 ; source mask, scopemask ++ 7f 03 00 ; address ++ HEX_EDNSDATA_END ++ ; This is the response, without the subnet option ++ HEX_ANSWER_BEGIN; ++ 00 00 84 00 00 01 00 01 ; ID 0 QR AA NOERROR ++ 00 00 00 01 03 77 77 77 ; www.example.com A (DO) ++ 07 65 78 61 6d 70 6c 65 ++ 03 63 6f 6d 00 00 01 00 ++ 01 ++ C0 0C 00 01 00 01 00 00 0E 10 ; www.example.com. A IN 3600 ++ 00 04 0A 14 1E 2C ; rdata 10.20.30.44 ++ 00 00 29 10 00 00 00 ++ 80 00 00 00 ++ HEX_ANSWER_END ++ENTRY_END ++ ++; The answer for a query without subnet ++;ENTRY_BEGIN ++;MATCH opcode qtype qname ++;ADJUST copy_id ++;REPLY QR AA NOERROR ++;SECTION QUESTION ++;www.example.com. IN A ++;SECTION ANSWER ++;www.example.com. IN A 10.20.30.40 ++;ENTRY_END ++RANGE_END ++ ++; ns.example.com. ++RANGE_BEGIN 53 57 ++ ADDRESS 1.2.3.4 ++; The answer for a query without subnet ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++www.example.com. IN A 10.20.30.40 ++ENTRY_END ++RANGE_END ++ ++STEP 10 QUERY ++ENTRY_BEGIN ++ HEX_ANSWER_BEGIN; ++ 00 00 01 00 00 01 00 00 ; ID 0 ++ 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) ++ 07 65 78 61 6d 70 6c 65 ++ 03 63 6f 6d 00 00 01 00 ++ 01 00 00 29 10 00 00 00 ++ 80 00 00 0b ++ ++ 00 08 00 07 ; OPC, optlen ++ 00 01 11 00 ; ip4, scope 17, source 0 ++ 7f 00 00 ; 127.0.0.0/17 ++ HEX_ANSWER_END ++ENTRY_END ++ ++STEP 20 QUERY ++ENTRY_BEGIN ++ HEX_ANSWER_BEGIN; ++ 00 00 01 00 00 01 00 00 ; ID 0 ++ 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) ++ 07 65 78 61 6d 70 6c 65 ++ 03 63 6f 6d 00 00 01 00 ++ 01 00 00 29 10 00 00 00 ++ 80 00 00 0b ++ ++ 00 08 00 07 ; OPC, optlen ++ 00 01 11 00 ; ip4, scope 17, source 0 ++ 7f 02 00 ; 127.2.0.0/17 ++ HEX_ANSWER_END ++ENTRY_END ++ ++STEP 30 QUERY ++ENTRY_BEGIN ++ HEX_ANSWER_BEGIN; ++ 00 00 01 00 00 01 00 00 ; ID 0 ++ 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) ++ 07 65 78 61 6d 70 6c 65 ++ 03 63 6f 6d 00 00 01 00 ++ 01 00 00 29 10 00 00 00 ++ 80 00 00 0b ++ ++ 00 08 00 07 ; OPC, optlen ++ 00 01 11 00 ; ip4, scope 17, source 0 ++ 7f 03 00 ; 127.3.0.0/17 ++ HEX_ANSWER_END ++ENTRY_END ++ ++; recursion happens here. ++; The upstream server RANGE starts responding at STEP 50. ++STEP 50 TRAFFIC ++ ++; The upstream server now responds for the nonsubnet response. ++STEP 55 TRAFFIC ++ ++STEP 60 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ednsdata ++REPLY QR RD RA DO NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++www.example.com. IN A 10.20.30.40 ++;www.example.com. IN A 10.20.30.44 ++SECTION ADDITIONAL ++; HEX_EDNSDATA_BEGIN ++; ; client is 127.3.0.1 ++; 00 08 ; OPC ++; 00 07 ; option length ++; 00 01 ; Family ++; 11 00 ; source mask, scopemask ++; 7f 03 00 ; address ++; HEX_EDNSDATA_END ++ENTRY_END ++ ++STEP 70 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ednsdata ++REPLY QR RD RA DO NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++www.example.com. IN A 10.20.30.40 ++;www.example.com. IN A 10.20.30.44 ++SECTION ADDITIONAL ++; HEX_EDNSDATA_BEGIN ++; ; client is 127.2.0.1 ++; 00 08 ; OPC ++; 00 07 ; option length ++; 00 01 ; Family ++; 11 00 ; source mask, scopemask ++; 7f 02 00 ; address ++; HEX_EDNSDATA_END ++ENTRY_END ++ ++STEP 80 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ednsdata ++REPLY QR RD RA DO NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++www.example.com. IN A 10.20.30.40 ++;www.example.com. IN A 10.20.30.44 ++SECTION ADDITIONAL ++; HEX_EDNSDATA_BEGIN ++; ; client is 127.0.0.1 ++; 00 08 ; OPC ++; 00 07 ; option length ++; 00 01 ; Family ++; 11 00 ; source mask, scopemask ++; 7f 00 00 ; address ++; HEX_EDNSDATA_END ++ENTRY_END ++ ++SCENARIO_END +diff --git a/unbound-1.20.0/testdata/subnet_noecs_refused.rpl b/unbound-1.20.0/testdata/subnet_noecs_refused.rpl +new file mode 100644 +index 0000000..39fbe85 +--- /dev/null ++++ b/unbound-1.20.0/testdata/subnet_noecs_refused.rpl +@@ -0,0 +1,159 @@ ++# config ++server: ++ send-client-subnet: 1.2.3.4 ++ max-client-subnet-ipv4: 17 ++ module-config: "subnetcache iterator" ++ qname-minimisation: no ++ minimal-responses: yes ++ target-fetch-policy: "0 0 0 0 0" ++ ++stub-zone: ++ name: "." ++ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. ++CONFIG_END ++ ++SCENARIO_BEGIN Test subnet with no edns subnet support but it is refused ++; The query is sent to a server that does not reply with the edns-subnet ++; option. The upstream server sends rcode refused. That results in a ++; NULL return_msg. ++ ++; K.ROOT-SERVERS.NET. ++RANGE_BEGIN 0 100 ++ ADDRESS 193.0.14.129 ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR NOERROR ++SECTION QUESTION ++. IN NS ++SECTION ANSWER ++. IN NS K.ROOT-SERVERS.NET. ++SECTION ADDITIONAL ++K.ROOT-SERVERS.NET. IN A 193.0.14.129 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++com. IN NS ++SECTION AUTHORITY ++com. IN NS a.gtld-servers.net. ++SECTION ADDITIONAL ++a.gtld-servers.net. IN A 192.5.6.30 ++ENTRY_END ++RANGE_END ++ ++; a.gtld-servers.net. ++RANGE_BEGIN 0 100 ++ ADDRESS 192.5.6.30 ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++example.com. IN NS ++SECTION AUTHORITY ++example.com. IN NS ns.example.com. ++SECTION ADDITIONAL ++ns.example.com. IN A 1.2.3.4 ++ENTRY_END ++RANGE_END ++ ++; ns.example.com. ++RANGE_BEGIN 0 100 ++ ADDRESS 1.2.3.4 ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++example.com. IN NS ++SECTION ANSWER ++example.com. IN NS ns.example.com. ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN A ++SECTION ANSWER ++ns.example.com. IN A 1.2.3.4 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN AAAA ++SECTION ANSWER ++SECTION AUTHORITY ++example.com. IN SOA ns.example.com. host.example.com. 4 86400 3600 86400 3600 ++ENTRY_END ++ ++; This matches the no EDNS subnet info queries that are made for the ++; fallback without subnet. The answer is refused. ++ENTRY_BEGIN ++MATCH opcode qtype qname ednsdata ++ADJUST copy_id ++REPLY QR AA REFUSED ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++;www.example.com. IN A 10.20.30.40 ++ENTRY_END ++ ++; This matches the initial query with edns subnet in the query, ++; the answer has no edns subnet in the reply. ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++www.example.com. IN A 10.20.30.40 ++ENTRY_END ++RANGE_END ++ ++STEP 1 QUERY ++;ENTRY_BEGIN ++;REPLY RD DO ++;SECTION QUESTION ++;www.example.com. IN A ++; but send this query with subnet scope zero in the query, because that ++; makes the reply possibly get stored in the cache. ++; ++; query with subnet 0.0.0.0/0. ++ENTRY_BEGIN ++HEX_ANSWER_BEGIN ++ 00 00 01 00 00 01 00 00 ;ID 0 ++ 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) ++ 07 65 78 61 6d 70 6c 65 ++ 03 63 6f 6d 00 00 01 00 ++ 01 00 00 29 10 00 00 00 ++ 80 00 00 08 ++ ++ 00 08 00 04 ; OPC, optlen ++ 00 01 00 00 ; ip4, scope 0, source 0 ++ ;0.0.0.0/0 ++HEX_ANSWER_END ++ENTRY_END ++ ++; recursion happens here. ++STEP 10 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ednsdata ++REPLY QR RD RA DO SERVFAIL ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++;www.example.com. IN A 10.20.30.40 ++ENTRY_END ++SCENARIO_END +diff --git a/unbound-1.20.0/testdata/subnet_noecs_support.rpl b/unbound-1.20.0/testdata/subnet_noecs_support.rpl +new file mode 100644 +index 0000000..0c9826c +--- /dev/null ++++ b/unbound-1.20.0/testdata/subnet_noecs_support.rpl +@@ -0,0 +1,127 @@ ++# config ++server: ++ send-client-subnet: 1.2.3.4 ++ max-client-subnet-ipv4: 17 ++ module-config: "subnetcache iterator" ++ qname-minimisation: no ++ minimal-responses: yes ++ target-fetch-policy: "0 0 0 0 0" ++ ++stub-zone: ++ name: "." ++ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. ++CONFIG_END ++ ++SCENARIO_BEGIN Test subnet with no edns subnet support from the server ++; The query is sent to a server that does not reply with the edns-subnet ++; option. ++ ++; K.ROOT-SERVERS.NET. ++RANGE_BEGIN 0 100 ++ ADDRESS 193.0.14.129 ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR NOERROR ++SECTION QUESTION ++. IN NS ++SECTION ANSWER ++. IN NS K.ROOT-SERVERS.NET. ++SECTION ADDITIONAL ++K.ROOT-SERVERS.NET. IN A 193.0.14.129 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++com. IN NS ++SECTION AUTHORITY ++com. IN NS a.gtld-servers.net. ++SECTION ADDITIONAL ++a.gtld-servers.net. IN A 192.5.6.30 ++ENTRY_END ++RANGE_END ++ ++; a.gtld-servers.net. ++RANGE_BEGIN 0 100 ++ ADDRESS 192.5.6.30 ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++example.com. IN NS ++SECTION AUTHORITY ++example.com. IN NS ns.example.com. ++SECTION ADDITIONAL ++ns.example.com. IN A 1.2.3.4 ++ENTRY_END ++RANGE_END ++ ++; ns.example.com. ++RANGE_BEGIN 0 100 ++ ADDRESS 1.2.3.4 ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++example.com. IN NS ++SECTION ANSWER ++example.com. IN NS ns.example.com. ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN A ++SECTION ANSWER ++ns.example.com. IN A 1.2.3.4 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN AAAA ++SECTION ANSWER ++SECTION AUTHORITY ++example.com. IN SOA ns.example.com. host.example.com. 4 86400 3600 86400 3600 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++www.example.com. IN A 10.20.30.40 ++ENTRY_END ++RANGE_END ++ ++STEP 1 QUERY ++ENTRY_BEGIN ++REPLY RD DO ++SECTION QUESTION ++www.example.com. IN A ++ENTRY_END ++ ++; recursion happens here. ++STEP 10 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ednsdata ++REPLY QR RD RA DO NOERROR ++SECTION QUESTION ++www.example.com. IN A ++SECTION ANSWER ++www.example.com. IN A 10.20.30.40 ++ENTRY_END ++SCENARIO_END diff --git a/unbound.spec b/unbound.spec index fed0962..1e47ad3 100644 --- a/unbound.spec +++ b/unbound.spec @@ -2,7 +2,7 @@ ## (rpmautospec version 0.6.5) ## RPMAUTOSPEC: autorelease, autochangelog %define autorelease(e:s:pb:n) %{?-p:0.}%{lua: - release_number = 10; + release_number = 12; base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); print(release_number + base_release_number - 1); }%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} @@ -76,6 +76,9 @@ Source27: unbound-initrd.conf Patch1: unbound-fedora-config.patch # https://github.com/NLnetLabs/unbound/commit/b7c61d7cc256d6a174e6179622c7fa968272c259 Patch2: unbound-1.21-CVE-2024-8508.patch +# https://github.com/NLnetLabs/unbound/commit/5bf82f246481098a6473f296b21fc1229d276c0f +# https://github.com/NLnetLabs/unbound/commit/a1150078f29e14b36c8e4d9d05a263a5e6abbc5b +Patch3: unbound-1.23.1-CVE-2025-5994.patch BuildRequires: gcc, make BuildRequires: flex, openssl-devel @@ -545,6 +548,12 @@ popd %changelog ## START: Generated by rpmautospec +* Tue Jul 22 2025 Tomas Korbar - 1.20.0-12 +- Fix RebirthDay Attack (CVE-2025-5994) + +* Thu Jun 05 2025 psklenar@redhat.com - 1.20.0-11 +- https://issues.redhat.com/browse/RHELMISC-13073 + * Wed May 14 2025 Petr Menšík - 1.20.0-10 - Prevent unbounded name compression (CVE-2024-8508)