diff --git a/unbound-1.25.1-CVE-2026-33278.patch b/unbound-1.25.1-CVE-2026-33278.patch new file mode 100644 index 0000000..2b9ce66 --- /dev/null +++ b/unbound-1.25.1-CVE-2026-33278.patch @@ -0,0 +1,273 @@ +diff --git a/unbound-1.24.2/services/cache/dns.c b/unbound-1.24.2/services/cache/dns.c +index 351b356..8dae2ff 100644 +--- a/unbound-1.24.2/services/cache/dns.c ++++ b/unbound-1.24.2/services/cache/dns.c +@@ -675,10 +675,16 @@ struct dns_msg* + dns_msg_deepcopy_region(struct dns_msg* origin, struct regional* region) + { + size_t i; ++ struct ub_packed_rrset_key** saved_rrsets; + struct dns_msg* res = NULL; ++ size_t rep_alloc_size = sizeof(struct reply_info) ++ - sizeof(struct rrset_ref); /* this is the size of res->rep ++ allocated in gen_dns_msg() */ + res = gen_dns_msg(region, &origin->qinfo, origin->rep->rrset_count); + if(!res) return NULL; +- *res->rep = *origin->rep; ++ saved_rrsets = res->rep->rrsets; /* save rrsets alloc by gen_dns_msg */ ++ memcpy(res->rep, origin->rep, rep_alloc_size); ++ res->rep->rrsets = saved_rrsets; + if(origin->rep->reason_bogus_str) { + res->rep->reason_bogus_str = regional_strdup(region, + origin->rep->reason_bogus_str); +diff --git a/unbound-1.24.2/testdata/val_nsec3_iter_high.rpl b/unbound-1.24.2/testdata/val_nsec3_iter_high.rpl +index 2b78f0b..703092d 100644 +--- a/unbound-1.24.2/testdata/val_nsec3_iter_high.rpl ++++ b/unbound-1.24.2/testdata/val_nsec3_iter_high.rpl +@@ -120,12 +120,12 @@ example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 720 + example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} + + ; closest encloser, H(example.com). +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} ++b6fuorg741ufili49mg9j4328ig53sqg.example.com. NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig53sqh SOA NS MX DNSKEY RRSIG ++b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AJlV5car66lq5f0ASx7W47A/OADkARAXzKt9ZLojXze+FWK9JjAX+eA= + +-; wildcard denial, H(*.example.com.) = 4f3cnt8cu22tngec382jj4gde4rb47ub +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854} ++; wildcard denial, H(*.example.com.) = k1a2vr9c269jummpru5d68qllbfmtdcb. ++k1a2vr9c269jummpru5d68qllbfmtacb.example.com. NSEC3 1 1 123 aabb00123456bbccdd k1a2vr9c269jummpru5d68qllbfmtgcb A MX RRSIG ++k1a2vr9c269jummpru5d68qllbfmtacb.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AARB9z4C1WZUI3WP3QAR7RJXFnN0qEBkEt8ocudxXzms4/7/2l6NNWc= + + ; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. + s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +@@ -152,10 +152,10 @@ SECTION ANSWER + SECTION AUTHORITY + example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 + example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854} ++b6fuorg741ufili49mg9j4328ig53sqg.example.com. NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig53sqh SOA NS MX DNSKEY RRSIG ++b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AJlV5car66lq5f0ASx7W47A/OADkARAXzKt9ZLojXze+FWK9JjAX+eA= ++k1a2vr9c269jummpru5d68qllbfmtacb.example.com. NSEC3 1 1 123 aabb00123456bbccdd k1a2vr9c269jummpru5d68qllbfmtgcb A MX RRSIG ++k1a2vr9c269jummpru5d68qllbfmtacb.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AARB9z4C1WZUI3WP3QAR7RJXFnN0qEBkEt8ocudxXzms4/7/2l6NNWc= + s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG + s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +diff --git a/unbound-1.24.2/testdata/val_nx_nsec3_collision.rpl b/unbound-1.24.2/testdata/val_nx_nsec3_collision.rpl +index 87a55f5..1b1f49e 100644 +--- a/unbound-1.24.2/testdata/val_nx_nsec3_collision.rpl ++++ b/unbound-1.24.2/testdata/val_nx_nsec3_collision.rpl +@@ -89,6 +89,17 @@ ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} + ENTRY_END + ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN AAAA ++SECTION AUTHORITY ++example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 ++example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} ++ENTRY_END ++ + ; response to DNSKEY priming query + ENTRY_BEGIN + MATCH opcode qtype qname +@@ -163,29 +174,11 @@ STEP 2 TIME_PASSES ELAPSE 0.05 + STEP 10 CHECK_ANSWER + ENTRY_BEGIN + MATCH all +-REPLY QR RD RA DO NXDOMAIN ++REPLY QR RD RA DO SERVFAIL + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + SECTION AUTHORITY +-example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +-example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 123 aabb00123456bbccdd 6md8numosa4q9ugkffdo1bmm82t5j49s A RRSIG +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHndWrEEbuzezs/4lxeiMgEuUsUbAhR72gJgd/Zmhf80yoxCauw9k5OkCw== ;{id = 2854} +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 18 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 19 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDRwji51WCXJg7W/3+Jx586af5qgAhQPxHegtzu1I/QbvCNrOOON05N1rw== ;{id = 2854} +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 18 - s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 19 - s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 00 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 01 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 02 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 03 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDLy4GbR8ZaKHATVJGnGxzpsuq60AhQ1/pRbXi1ZbcYohzHgWzNC50fC5A== ;{id = 2854} +- + SECTION ADDITIONAL + ENTRY_END + +diff --git a/unbound-1.24.2/testdata/val_nx_nsec3_params.rpl b/unbound-1.24.2/testdata/val_nx_nsec3_params.rpl +index dd3ab6b..59bef2b 100644 +--- a/unbound-1.24.2/testdata/val_nx_nsec3_params.rpl ++++ b/unbound-1.24.2/testdata/val_nx_nsec3_params.rpl +@@ -88,6 +88,17 @@ ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} + ENTRY_END + ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.example.com. IN AAAA ++SECTION AUTHORITY ++example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 ++example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} ++ENTRY_END ++ + ; response to DNSKEY priming query + ENTRY_BEGIN + MATCH opcode qtype qname +@@ -144,20 +155,11 @@ ENTRY_END + STEP 10 CHECK_ANSWER + ENTRY_BEGIN + MATCH all +-REPLY QR RD RA DO NXDOMAIN ++REPLY QR RD RA DO SERVFAIL + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + SECTION AUTHORITY +-example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +-example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854} +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} +- + SECTION ADDITIONAL + ENTRY_END + +diff --git a/unbound-1.24.2/validator/val_nsec3.c b/unbound-1.24.2/validator/val_nsec3.c +index 998fcc4..92d8538 100644 +--- a/unbound-1.24.2/validator/val_nsec3.c ++++ b/unbound-1.24.2/validator/val_nsec3.c +@@ -456,6 +456,67 @@ filter_init(struct nsec3_filter* filter, struct ub_packed_rrset_key** list, + } + } + ++/** Check if the NSEC3s have the same parameter set. */ ++static int ++param_set_same(struct nsec3_filter* flt, char** reason) ++{ ++ size_t rrsetnum; ++ int rrnum; ++ struct ub_packed_rrset_key* rrset; ++ int have_params = 0; ++ int first_algo = 0; ++ size_t first_iter = 0; ++ uint8_t* first_salt = NULL; ++ size_t first_saltlen = 0; ++ ++ /* If the NSEC3 parameter sets have distinct values, then they are ++ * from different NSEC3 chains, and we do not want that. */ ++ for(rrset=filter_first(flt, &rrsetnum, &rrnum); rrset; ++ rrset=filter_next(flt, &rrsetnum, &rrnum)) { ++ if(!have_params) { ++ first_algo = nsec3_get_algo(rrset, rrnum); ++ first_iter = nsec3_get_iter(rrset, rrnum); ++ if(!nsec3_get_salt(rrset, rrnum, &first_salt, ++ &first_saltlen)) { ++ verbose(VERB_ALGO, "NSEC3 salt malformed"); ++ if(reason) ++ *reason = "NSEC3 salt malformed"; ++ return 0; ++ } ++ have_params = 1; ++ } else { ++ uint8_t* salt = NULL; ++ size_t saltlen = 0; ++ if(nsec3_get_algo(rrset, rrnum) != first_algo) { ++ verbose(VERB_ALGO, "NSEC3 algorithm mismatch"); ++ if(reason) ++ *reason = "NSEC3 algorithm mismatch"; ++ return 0; ++ } ++ if(nsec3_get_iter(rrset, rrnum) != first_iter) { ++ verbose(VERB_ALGO, "NSEC3 iterations mismatch"); ++ if(reason) ++ *reason = "NSEC3 iterations mismatch"; ++ return 0; ++ } ++ if(!nsec3_get_salt(rrset, rrnum, &salt, &saltlen)) { ++ verbose(VERB_ALGO, "NSEC3 salt malformed"); ++ if(reason) ++ *reason = "NSEC3 salt malformed"; ++ return 0; ++ } ++ if(saltlen != first_saltlen || ++ memcmp(salt, first_salt, saltlen) != 0) { ++ verbose(VERB_ALGO, "NSEC3 salt mismatch"); ++ if(reason) ++ *reason = "NSEC3 salt mismatch"; ++ return 0; ++ } ++ } ++ } ++ return 1; ++} ++ + /** + * Find max iteration count using config settings and key size + * @param ve: validator environment with iteration count config settings. +@@ -1192,6 +1253,8 @@ nsec3_prove_nameerror(struct module_env* env, struct val_env* ve, + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ ++ if(!param_set_same(&flt, NULL)) ++ return sec_status_bogus; /* nsec3 params from distinct chains*/ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + log_nametypeclass(VERB_ALGO, "start nsec3 nameerror proof, zone", +@@ -1378,6 +1441,8 @@ nsec3_prove_nodata(struct module_env* env, struct val_env* ve, + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ ++ if(!param_set_same(&flt, NULL)) ++ return sec_status_bogus; /* nsec3 params from distinct chains*/ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + return nsec3_do_prove_nodata(env, &flt, ct, qinfo, calc); +@@ -1401,6 +1466,8 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve, + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ ++ if(!param_set_same(&flt, NULL)) ++ return sec_status_bogus; /* nsec3 params from distinct chains*/ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + +@@ -1503,6 +1570,8 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve, + *reason = "no NSEC3 records"; + return sec_status_bogus; /* no RRs */ + } ++ if(!param_set_same(&flt, reason)) ++ return sec_status_bogus; /* nsec3 params from distinct chains*/ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + +@@ -1596,6 +1665,8 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve, + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ ++ if(!param_set_same(&flt, NULL)) ++ return sec_status_bogus; /* nsec3 params from distinct chains*/ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + diff --git a/unbound-1.25.1-CVE-2026-42944.patch b/unbound-1.25.1-CVE-2026-42944.patch new file mode 100644 index 0000000..56639e8 --- /dev/null +++ b/unbound-1.25.1-CVE-2026-42944.patch @@ -0,0 +1,222 @@ +diff --git a/unbound-1.24.2/testcode/unitmain.c b/unbound-1.24.2/testcode/unitmain.c +index 07c016d..beb10ba 100644 +--- a/unbound-1.24.2/testcode/unitmain.c ++++ b/unbound-1.24.2/testcode/unitmain.c +@@ -1092,7 +1092,7 @@ static void edns_ede_encode_notxt_fit_test( struct query_info* qinfo, + { + struct edns_data edns; + sldns_buffer* pkt; +- uint16_t edns_field_size, ede_txt_size; ++ size_t edns_field_size, ede_txt_size; + int found_ede = 0, found_ede_other = 0, found_ede_txt = 0; + int found_other_edns = 0; + edns_ede_encode_setup(&edns, region); +@@ -1123,7 +1123,7 @@ static void edns_ede_encode_no_fit_test( struct query_info* qinfo, + { + struct edns_data edns; + sldns_buffer* pkt; +- uint16_t edns_field_size, ede_size, ede_txt_size; ++ size_t edns_field_size, ede_size, ede_txt_size; + int found_ede = 0, found_ede_other = 0, found_ede_txt = 0; + int found_other_edns = 0; + edns_ede_encode_setup(&edns, region); +diff --git a/unbound-1.24.2/util/data/msgencode.c b/unbound-1.24.2/util/data/msgencode.c +index 84aa3b9..7bc55a5 100644 +--- a/unbound-1.24.2/util/data/msgencode.c ++++ b/unbound-1.24.2/util/data/msgencode.c +@@ -804,7 +804,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep, + return 1; + } + +-uint16_t ++size_t + calc_edns_field_size(struct edns_data* edns) + { + size_t rdatalen = 0; +@@ -840,7 +840,7 @@ calc_edns_option_size(struct edns_data* edns, uint16_t code) + } + + uint16_t +-calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size) ++calc_ede_option_size(struct edns_data* edns, size_t* txt_size) + { + size_t rdatalen = 0; + struct edns_option* opt; +@@ -942,6 +942,10 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns, + padding_option = opt; + continue; + } ++ if(sldns_buffer_position(pkt) + opt->opt_len + 4 > max_msg_sz) ++ break; /* no space for it */ ++ if(!sldns_buffer_available(pkt, 4 + opt->opt_len)) ++ break; + sldns_buffer_write_u16(pkt, opt->opt_code); + sldns_buffer_write_u16(pkt, opt->opt_len); + if(opt->opt_len != 0) +@@ -952,12 +956,18 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns, + padding_option = opt; + continue; + } ++ if(sldns_buffer_position(pkt) + opt->opt_len + 4 > max_msg_sz) ++ break; /* no space for it */ ++ if(!sldns_buffer_available(pkt, 4 + opt->opt_len)) ++ break; + sldns_buffer_write_u16(pkt, opt->opt_code); + sldns_buffer_write_u16(pkt, opt->opt_len); + if(opt->opt_len != 0) + sldns_buffer_write(pkt, opt->opt_data, opt->opt_len); + } +- if (padding_option && edns->padding_block_size ) { ++ if (padding_option && edns->padding_block_size && ++ sldns_buffer_position(pkt)+4 <= max_msg_sz && ++ sldns_buffer_available(pkt, 4) /* if there is space for it */) { + size_t pad_pos = sldns_buffer_position(pkt); + size_t msg_sz = ((pad_pos + 3) / edns->padding_block_size + 1) + * edns->padding_block_size; +@@ -1001,7 +1011,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, + { + uint16_t flags; + unsigned int attach_edns = 0; +- uint16_t edns_field_size, ede_size, ede_txt_size; ++ size_t edns_field_size, ede_size, ede_txt_size; + + if(!cached || rep->authoritative) { + /* original flags, copy RD and CD bits from query. */ +@@ -1028,12 +1038,12 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, + * calculate sizes once here */ + edns_field_size = calc_edns_field_size(edns); + ede_size = calc_ede_option_size(edns, &ede_txt_size); +- if(sldns_buffer_capacity(pkt) < udpsize) ++ if(sldns_buffer_capacity(pkt) < (size_t)udpsize) + udpsize = sldns_buffer_capacity(pkt); + if(!edns || !edns->edns_present) { + attach_edns = 0; + /* EDEs are optional, try to fit anything else before them */ +- } else if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) { ++ } else if((size_t)udpsize < (size_t)LDNS_HEADER_SIZE + edns_field_size - ede_size) { + /* packet too small to contain edns, omit it. */ + attach_edns = 0; + } else { +@@ -1047,13 +1057,13 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, + return 0; + } + if(attach_edns) { +- if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size) ++ if((size_t)udpsize >= sldns_buffer_limit(pkt) + edns_field_size) + attach_edns_record_max_msg_sz(pkt, edns, udpsize); +- else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_txt_size) { ++ else if((size_t)udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_txt_size) { + ede_trim_text(&edns->opt_list_inplace_cb_out); + ede_trim_text(&edns->opt_list_out); + attach_edns_record_max_msg_sz(pkt, edns, udpsize); +- } else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_size) { ++ } else if((size_t)udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_size) { + edns_opt_list_remove(&edns->opt_list_inplace_cb_out, LDNS_EDNS_EDE); + edns_opt_list_remove(&edns->opt_list_out, LDNS_EDNS_EDE); + attach_edns_record_max_msg_sz(pkt, edns, udpsize); +@@ -1115,22 +1125,30 @@ extended_error_encode(sldns_buffer* buf, uint16_t rcode, + sldns_buffer_write_u16(buf, qinfo->qclass); + } + sldns_buffer_flip(buf); +- if(edns) { ++ if(edns && edns->edns_present) { ++ size_t edns_field_size, ede_size, ede_txt_size; + struct edns_data es = *edns; + es.edns_version = EDNS_ADVERTISED_VERSION; + es.udp_size = EDNS_ADVERTISED_SIZE; + es.ext_rcode = (uint8_t)(rcode >> 4); + es.bits &= EDNS_DO; +- if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) > +- edns->udp_size) { ++ /* EDEs are optional. If space is a concern try in order: ++ * - removing any EXTRA-TEXT fields from explicit EDEs, or ++ * - removing all EDEs, ++ * to see if EDNS can fit. */ ++ edns_field_size = calc_edns_field_size(&es); ++ ede_size = calc_ede_option_size(&es, &ede_txt_size); ++ if((size_t)edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size) ++ attach_edns_record_max_msg_sz(buf, &es, edns->udp_size); ++ else if((size_t)edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size - ede_txt_size) { ++ ede_trim_text(&es.opt_list_inplace_cb_out); ++ ede_trim_text(&es.opt_list_out); ++ attach_edns_record_max_msg_sz(buf, &es, edns->udp_size); ++ } else if((size_t)edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size - ede_size) { + edns_opt_list_remove(&es.opt_list_inplace_cb_out, LDNS_EDNS_EDE); + edns_opt_list_remove(&es.opt_list_out, LDNS_EDNS_EDE); +- if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) > +- edns->udp_size) { +- return; +- } ++ attach_edns_record_max_msg_sz(buf, &es, edns->udp_size); + } +- attach_edns_record(buf, &es); + } + } + +diff --git a/unbound-1.24.2/util/data/msgencode.h b/unbound-1.24.2/util/data/msgencode.h +index 08fcb59..6456955 100644 +--- a/unbound-1.24.2/util/data/msgencode.h ++++ b/unbound-1.24.2/util/data/msgencode.h +@@ -106,7 +106,7 @@ void qinfo_query_encode(struct sldns_buffer* pkt, struct query_info* qinfo); + * @param edns: edns data or NULL. + * @return octets to reserve for EDNS. + */ +-uint16_t calc_edns_field_size(struct edns_data* edns); ++size_t calc_edns_field_size(struct edns_data* edns); + + /** + * Calculate the size of a specific EDNS option in packet. +@@ -127,7 +127,7 @@ uint16_t calc_edns_option_size(struct edns_data* edns, uint16_t code); + * extra text. + * @return octets the option will take up. + */ +-uint16_t calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size); ++uint16_t calc_ede_option_size(struct edns_data* edns, size_t* txt_size); + + /** + * Attach EDNS record to buffer. Buffer has complete packet. There must +diff --git a/unbound-1.24.2/util/data/msgparse.c b/unbound-1.24.2/util/data/msgparse.c +index 6963d85..2d09556 100644 +--- a/unbound-1.24.2/util/data/msgparse.c ++++ b/unbound-1.24.2/util/data/msgparse.c +@@ -950,6 +950,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, + struct comm_reply* repinfo, uint32_t now, struct regional* region, + struct cookie_secrets* cookie_secrets) + { ++ int nsid_seen = 0, cookie_seen = 0, padding_seen = 0; + /* To respond with a Keepalive option, the client connection must have + * received one message with a TCP Keepalive EDNS option, and that + * option must have 0 length data. Subsequent messages sent on that +@@ -984,8 +985,9 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, + /* handle parse time edns options here */ + switch(opt_code) { + case LDNS_EDNS_NSID: +- if (!cfg || !cfg->nsid) ++ if (!cfg || !cfg->nsid || nsid_seen) + break; ++ nsid_seen = 1; + if(!edns_opt_list_append(&edns->opt_list_out, + LDNS_EDNS_NSID, cfg->nsid_len, + cfg->nsid, region)) { +@@ -1027,8 +1029,9 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, + + case LDNS_EDNS_PADDING: + if(!cfg || !cfg->pad_responses || +- !c || c->type != comm_tcp ||!c->ssl) ++ !c || c->type != comm_tcp ||!c->ssl || padding_seen) + break; ++ padding_seen = 1; + if(!edns_opt_list_append(&edns->opt_list_out, + LDNS_EDNS_PADDING, + 0, NULL, region)) { +@@ -1039,8 +1042,9 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, + break; + + case LDNS_EDNS_COOKIE: +- if(!cfg || !cfg->do_answer_cookie || !repinfo) ++ if(!cfg || !cfg->do_answer_cookie || !repinfo || cookie_seen) + break; ++ cookie_seen = 1; + if(opt_len != 8 && (opt_len < 16 || opt_len > 40)) { + verbose(VERB_ALGO, "worker request: " + "badly formatted cookie"); diff --git a/unbound-1.25.1-CVE-2026-42959.patch b/unbound-1.25.1-CVE-2026-42959.patch new file mode 100644 index 0000000..f500835 --- /dev/null +++ b/unbound-1.25.1-CVE-2026-42959.patch @@ -0,0 +1,17 @@ +diff --git a/unbound-1.24.2/validator/val_utils.c b/unbound-1.24.2/validator/val_utils.c +index 549264d..4495695 100644 +--- a/unbound-1.24.2/validator/val_utils.c ++++ b/unbound-1.24.2/validator/val_utils.c +@@ -1066,10 +1066,10 @@ val_fill_reply(struct reply_info* chase, struct reply_info* orig, + if(query_dname_compare(name, + orig->rrsets[i]->rk.dname) == 0) + chase->rrsets[chase->an_numrrsets +- +orig->ns_numrrsets+chase->ar_numrrsets++] ++ +chase->ns_numrrsets+chase->ar_numrrsets++] + = orig->rrsets[i]; + } else if(rrset_has_signer(orig->rrsets[i], name, len)) { +- chase->rrsets[chase->an_numrrsets+orig->ns_numrrsets+ ++ chase->rrsets[chase->an_numrrsets+chase->ns_numrrsets+ + chase->ar_numrrsets++] = orig->rrsets[i]; + } + } diff --git a/unbound.spec b/unbound.spec index c7895d6..bd73ff8 100644 --- a/unbound.spec +++ b/unbound.spec @@ -1,11 +1,6 @@ ## START: Set by rpmautospec -## (rpmautospec version 0.8.3) -## RPMAUTOSPEC: autorelease, autochangelog -%define autorelease(e:s:pb:n) %{?-p:0.}%{lua: - release_number = 7; - base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); - print(release_number + base_release_number - 1); -}%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} +## (rpmautospec version 0.8.4) +## RPMAUTOSPEC: autochangelog ## END: Set by rpmautospec %{?!with_python2: %global with_python2 0} @@ -42,7 +37,7 @@ Summary: Validating, recursive, and caching DNS(SEC) resolver Name: unbound Version: 1.24.2 -Release: %autorelease %{?extra_version:-e %{extra_version}} +Release: 7%{?extra_version:-e %{extra_version}}%{?dist}.1 License: BSD-3-Clause Url: https://nlnetlabs.nl/projects/unbound/ Source: https://nlnetlabs.nl/downloads/%{name}/%{name}-%{version}%{?extra_version}.tar.gz @@ -81,6 +76,13 @@ Patch1: unbound-fedora-config.patch Patch2: %{forgeurl}/pull/1349.patch#/unbound-1.25-tls-crypto-policy.patch # https://github.com/NLnetLabs/unbound/pull/1401 Patch3: %{forgeurl}/pull/1401.patch#/unbound-1.25-tls-crypto-policy-default.patch +# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-33278_with.diff +Patch4: unbound-1.25.1-CVE-2026-33278.patch +# https://github.com/NLnetLabs/unbound/commit/44659cb3bf4601d2daa19a0d51ac5af54bc698bc +# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-42944_with.diff +Patch5: unbound-1.25.1-CVE-2026-42944.patch +# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-42959.diff +Patch6: unbound-1.25.1-CVE-2026-42959.patch BuildRequires: gcc BuildRequires: make @@ -560,6 +562,15 @@ popd %changelog ## START: Generated by rpmautospec +* Mon May 25 2026 Fedor Vorobev - 1.24.2-10 +- Fix CVE-2026-42959 + +* Mon May 25 2026 Fedor Vorobev - 1.24.2-9 +- Fix CVE-2026-42944 + +* Mon May 25 2026 Fedor Vorobev - 1.24.2-8 +- Fix CVE-2026-33278 + * Fri Feb 13 2026 Petr Menšík - 1.24.2-7 - Recreate configure unconditionally