From ca09910f6736d8e7dcbdb0b20b1df8efdfec7dbd Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Wed, 8 Jul 2026 11:30:58 -0400 Subject: [PATCH] import UBI unbound-1.24.2-3.el9_8.2 --- .../unbound-1.25.1-CVE-2026-40622-test.patch | 305 ++++++++++++++++++ SOURCES/unbound-1.25.1-CVE-2026-40622.patch | 36 +++ SOURCES/unbound-1.25.1-CVE-2026-41292.patch | 64 ++++ SOURCES/unbound-1.25.1-CVE-2026-42534.patch | 51 +++ SOURCES/unbound-1.25.1-CVE-2026-44390.patch | 20 ++ SPECS/unbound.spec | 20 +- 6 files changed, 494 insertions(+), 2 deletions(-) create mode 100644 SOURCES/unbound-1.25.1-CVE-2026-40622-test.patch create mode 100644 SOURCES/unbound-1.25.1-CVE-2026-40622.patch create mode 100644 SOURCES/unbound-1.25.1-CVE-2026-41292.patch create mode 100644 SOURCES/unbound-1.25.1-CVE-2026-42534.patch create mode 100644 SOURCES/unbound-1.25.1-CVE-2026-44390.patch diff --git a/SOURCES/unbound-1.25.1-CVE-2026-40622-test.patch b/SOURCES/unbound-1.25.1-CVE-2026-40622-test.patch new file mode 100644 index 0000000..e2ae0f6 --- /dev/null +++ b/SOURCES/unbound-1.25.1-CVE-2026-40622-test.patch @@ -0,0 +1,305 @@ +diff --git a/unbound-1.24.2/testdata/iter_ghost_ns_childapex.rpl b/unbound-1.24.2/testdata/iter_ghost_ns_childapex.rpl +new file mode 100644 +index 0000000..2b046a8 +--- /dev/null ++++ b/unbound-1.24.2/testdata/iter_ghost_ns_childapex.rpl +@@ -0,0 +1,299 @@ ++; config options ++server: ++ target-fetch-policy: "0 0 0 0 0" ++ qname-minimisation: no ++ minimal-responses: yes ++ log-servfail: yes ++ module-config: "iterator" ++ ++stub-zone: ++ name: "." ++ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. ++CONFIG_END ++ ++SCENARIO_BEGIN Test for ghost domain with a child apex NS query. ++ ++; 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 ++tld. IN NS ++SECTION AUTHORITY ++tld. IN NS ns.tld. ++SECTION ADDITIONAL ++ns.tld. IN A 1.2.3.5 ++ENTRY_END ++RANGE_END ++ ++; ns.tld ++RANGE_BEGIN 0 15 ++ ADDRESS 1.2.3.5 ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++tld. IN NS ++SECTION ANSWER ++tld. IN NS ns.tld ++SECTION ADDITIONAL ++ns.tld. IN A 1.2.3.5 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.tld. IN A ++SECTION ANSWER ++ns.tld. IN A 1.2.3.5 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.tld. IN AAAA ++SECTION AUTHORITY ++tld. 3600 IN SOA ns.tld. host.tld. 20201 3600 1800 604800 3600 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++mid.tld. IN NS ++SECTION AUTHORITY ++mid.tld. 5 IN NS ns.mid.tld. ++SECTION ADDITIONAL ++ns.mid.tld. 5 IN A 1.2.3.4 ++ENTRY_END ++RANGE_END ++ ++; ns.tld ++RANGE_BEGIN 20 100 ++ ADDRESS 1.2.3.5 ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++tld. IN NS ++SECTION ANSWER ++tld. IN NS ns.tld ++SECTION ADDITIONAL ++ns.tld. IN A 1.2.3.5 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.tld. IN A ++SECTION ANSWER ++ns.tld. IN A 1.2.3.5 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.tld. IN AAAA ++SECTION AUTHORITY ++tld. 3600 IN SOA ns.tld. host.tld. 20201 3600 1800 604800 3600 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR AA NXDOMAIN ++SECTION QUESTION ++mid.tld. IN NS ++SECTION AUTHORITY ++tld. 3600 IN SOA ns.tld. host.tld. 20201 3600 1800 604800 3600 ++ENTRY_END ++RANGE_END ++ ++; ns.mid.tld. ++RANGE_BEGIN 0 100 ++ ADDRESS 1.2.3.4 ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR NOERROR ++SECTION QUESTION ++mid.tld. IN NS ++SECTION ANSWER ++mid.tld. 86400 IN NS ns.mid.tld. ++SECTION ADDITIONAL ++ns.mid.tld. 86400 IN A 1.2.3.4 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.mid.tld. IN A ++SECTION ANSWER ++ns.mid.tld. IN A 1.2.3.4 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.mid.tld. IN AAAA ++SECTION AUTHORITY ++mid.tld. 3600 IN SOA ns.mid.tld. host.mid.tld. 20301 3600 1800 604800 3600 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode subdomain ++ADJUST copy_id copy_query ++REPLY QR NOERROR ++SECTION QUESTION ++sub.mid.tld. IN NS ++SECTION AUTHORITY ++sub.mid.tld. 3600 IN NS ns.sub.mid.tld. ++SECTION ADDITIONAL ++ns.sub.mid.tld. 3600 IN A 1.2.3.6 ++ENTRY_END ++RANGE_END ++ ++; ns.sub.mid.tld. ++RANGE_BEGIN 0 100 ++ ADDRESS 1.2.3.6 ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR NOERROR ++SECTION QUESTION ++sub.mid.tld. IN NS ++SECTION ANSWER ++sub.mid.tld. IN NS ns.sub.mid.tld. ++SECTION ADDITIONAL ++ns.sub.mid.tld. IN A 1.2.3.6 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.sub.mid.tld. IN A ++SECTION ANSWER ++ns.sub.mid.tld. IN A 1.2.3.6 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++ns.sub.mid.tld. IN AAAA ++SECTION AUTHORITY ++sub.mid.tld. 3600 IN SOA ns.sub.mid.tld. host.sub.mid.tld. 20301 3600 1800 604800 3600 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++a.sub.mid.tld. IN A ++SECTION ANSWER ++a.sub.mid.tld. 3600 IN A 10.20.30.40 ++ENTRY_END ++ ++ENTRY_BEGIN ++MATCH opcode qtype qname ++ADJUST copy_id ++REPLY QR AA NOERROR ++SECTION QUESTION ++b.sub.mid.tld. IN A ++SECTION ANSWER ++b.sub.mid.tld. 3600 IN A 10.20.30.41 ++ENTRY_END ++RANGE_END ++ ++STEP 1 QUERY ++ENTRY_BEGIN ++REPLY RD NOERROR ++SECTION QUESTION ++a.sub.mid.tld. IN A ++ENTRY_END ++ ++STEP 2 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ++REPLY QR RD RA NOERROR ++SECTION QUESTION ++a.sub.mid.tld. IN A ++SECTION ANSWER ++a.sub.mid.tld. 3600 IN A 10.20.30.40 ++ENTRY_END ++ ++STEP 10 QUERY ++ENTRY_BEGIN ++REPLY RD NOERROR ++SECTION QUESTION ++mid.tld. IN NS ++ENTRY_END ++ ++STEP 11 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ++REPLY QR RD RA NOERROR ++SECTION QUESTION ++mid.tld. IN NS ++SECTION ANSWER ++mid.tld. 86400 IN NS ns.mid.tld. ++SECTION ADDITIONAL ++ns.mid.tld. 86400 IN A 1.2.3.4 ++ENTRY_END ++ ++STEP 20 TIME_PASSES ELAPSE 10 ++; The authority for .tld switches to NXDOMAIN for mid.tld. ++ ++STEP 30 QUERY ++ENTRY_BEGIN ++REPLY RD NOERROR ++SECTION QUESTION ++b.sub.mid.tld. IN A ++ENTRY_END ++ ++STEP 31 CHECK_ANSWER ++ENTRY_BEGIN ++MATCH all ++REPLY QR RD RA NXDOMAIN ++SECTION QUESTION ++b.sub.mid.tld. IN A ++SECTION ANSWER ++SECTION AUTHORITY ++tld. 3600 IN SOA ns.tld. host.tld. 20201 3600 1800 604800 3600 ++ENTRY_END ++ ++SCENARIO_END diff --git a/SOURCES/unbound-1.25.1-CVE-2026-40622.patch b/SOURCES/unbound-1.25.1-CVE-2026-40622.patch new file mode 100644 index 0000000..005ab3b --- /dev/null +++ b/SOURCES/unbound-1.25.1-CVE-2026-40622.patch @@ -0,0 +1,36 @@ +diff --git a/unbound-1.24.2/services/cache/rrset.c b/unbound-1.24.2/services/cache/rrset.c +index 6d5c24f..81f4e28 100644 +--- a/unbound-1.24.2/services/cache/rrset.c ++++ b/unbound-1.24.2/services/cache/rrset.c +@@ -149,6 +149,16 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns) + if(equal && cached->ttl >= timenow && + cached->security == sec_status_bogus) + return 0; ++ /* ghost-domain: never let an NS overwrite extend lifetime ++ * past the entry it replaces, regardless of trust. */ ++ if(ns && !TTL_IS_EXPIRED(cached->ttl, timenow) && ++ newd->ttl > cached->ttl) { ++ size_t i; ++ newd->ttl = cached->ttl; ++ for(i=0; i<(newd->count+newd->rrsig_count); i++) ++ if(newd->rr_ttl[i] > newd->ttl) ++ newd->rr_ttl[i] = newd->ttl; ++ } + return 1; + } + /* o item in cache has expired */ +diff --git a/unbound-1.24.2/util/data/msgparse.h b/unbound-1.24.2/util/data/msgparse.h +index 7de4e39..d6e459d 100644 +--- a/unbound-1.24.2/util/data/msgparse.h ++++ b/unbound-1.24.2/util/data/msgparse.h +@@ -98,6 +98,10 @@ extern time_t SERVE_EXPIRED_REPLY_TTL; + /** If we serve the original TTL or decrementing TTLs */ + extern int SERVE_ORIGINAL_TTL; + ++/** Check if TTL is expired. 0 TTL is considered expired. ++ * Used mainly to identify parts of the code that do this comparison. */ ++#define TTL_IS_EXPIRED(ttl, now) ((ttl) <= (now)) ++ + /** + * Data stored in scratch pad memory during parsing. + * Stores the data that will enter into the msgreply and packet result. diff --git a/SOURCES/unbound-1.25.1-CVE-2026-41292.patch b/SOURCES/unbound-1.25.1-CVE-2026-41292.patch new file mode 100644 index 0000000..e855c39 --- /dev/null +++ b/SOURCES/unbound-1.25.1-CVE-2026-41292.patch @@ -0,0 +1,64 @@ +diff --git a/unbound-1.24.2/util/data/msgparse.c b/unbound-1.24.2/util/data/msgparse.c +index 2d09556..169709b 100644 +--- a/unbound-1.24.2/util/data/msgparse.c ++++ b/unbound-1.24.2/util/data/msgparse.c +@@ -53,6 +53,8 @@ + #include "sldns/parseutil.h" + #include "sldns/wire2str.h" + ++#define MAX_PARSED_EDNS_OPTIONS 100 ++ + /** smart comparison of (compressed, valid) dnames from packet */ + static int + smart_compare(sldns_buffer* pkt, uint8_t* dnow, +@@ -950,7 +952,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; ++ int i = 0, 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 +@@ -970,7 +972,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, + + /* while still more options, and have code+len to read */ + /* ignores partial content (i.e. rdata len 3) */ +- while(rdata_len >= 4) { ++ while(rdata_len >= 4 && i < MAX_PARSED_EDNS_OPTIONS) { + uint16_t opt_code = sldns_read_uint16(rdata_ptr); + uint16_t opt_len = sldns_read_uint16(rdata_ptr+2); + uint8_t server_cookie[40]; +@@ -1150,6 +1152,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, + } + rdata_ptr += opt_len; + rdata_len -= opt_len; ++ i++; + } + return LDNS_RCODE_NOERROR; + } +@@ -1164,6 +1167,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg, + struct rrset_parse* found_prev = 0; + size_t rdata_len; + uint8_t* rdata_ptr; ++ int i = 0; + /* since the class encodes the UDP size, we cannot use hash table to + * find the EDNS OPT record. Scan the packet. */ + while(rrset) { +@@ -1223,7 +1227,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg, + + /* while still more options, and have code+len to read */ + /* ignores partial content (i.e. rdata len 3) */ +- while(rdata_len >= 4) { ++ while(rdata_len >= 4 && i < MAX_PARSED_EDNS_OPTIONS) { + uint16_t opt_code = sldns_read_uint16(rdata_ptr); + uint16_t opt_len = sldns_read_uint16(rdata_ptr+2); + rdata_ptr += 4; +@@ -1238,6 +1242,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg, + } + rdata_ptr += opt_len; + rdata_len -= opt_len; ++ i++; + } + /* ignore rrsigs */ + return LDNS_RCODE_NOERROR; diff --git a/SOURCES/unbound-1.25.1-CVE-2026-42534.patch b/SOURCES/unbound-1.25.1-CVE-2026-42534.patch new file mode 100644 index 0000000..ed6164c --- /dev/null +++ b/SOURCES/unbound-1.25.1-CVE-2026-42534.patch @@ -0,0 +1,51 @@ +diff --git a/unbound-1.24.2/services/mesh.c b/unbound-1.24.2/services/mesh.c +index 3212a6a..23499dc 100644 +--- a/unbound-1.24.2/services/mesh.c ++++ b/unbound-1.24.2/services/mesh.c +@@ -296,12 +296,14 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf) + if(mesh->num_reply_states < mesh->max_reply_states) + return 1; + /* try to kick out a jostle-list item */ +- if(m && m->reply_list && m->list_select == mesh_jostle_list) { ++ if(m && m->list_select == mesh_jostle_list) { + /* how old is it? */ + struct timeval age; +- timeval_subtract(&age, mesh->env->now_tv, +- &m->reply_list->start_time); +- if(timeval_smaller(&mesh->jostle_max, &age)) { ++ if(m->has_first_reply_time) ++ timeval_subtract(&age, mesh->env->now_tv, ++ &m->first_reply_time); ++ if(!m->has_first_reply_time || ++ timeval_smaller(&mesh->jostle_max, &age)) { + /* its a goner */ + log_nametypeclass(VERB_ALGO, "query jostled out to " + "make space for a new one", +@@ -1960,6 +1962,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, + r->qid = qid; + r->qflags = qflags; + r->start_time = *s->s.env->now_tv; ++ if(s->reply_list == NULL && !s->has_first_reply_time) { ++ s->first_reply_time = r->start_time; ++ s->has_first_reply_time = 1; ++ } + r->next = s->reply_list; + r->qname = regional_alloc_init(s->s.region, qinfo->qname, + s->s.qinfo.qname_len); +diff --git a/unbound-1.24.2/services/mesh.h b/unbound-1.24.2/services/mesh.h +index f19f423..a61f909 100644 +--- a/unbound-1.24.2/services/mesh.h ++++ b/unbound-1.24.2/services/mesh.h +@@ -189,6 +189,12 @@ struct mesh_state { + struct module_qstate s; + /** the list of replies to clients for the results */ + struct mesh_reply* reply_list; ++ /** if it has a first reply time */ ++ int has_first_reply_time; ++ /** wall-clock time the first client reply was attached; ++ * used by mesh_make_new_space() so duplicate retransmits ++ * cannot reset jostle aging. */ ++ struct timeval first_reply_time; + /** the list of callbacks for the results */ + struct mesh_cb* cb_list; + /** set of superstates (that want this state's result) diff --git a/SOURCES/unbound-1.25.1-CVE-2026-44390.patch b/SOURCES/unbound-1.25.1-CVE-2026-44390.patch new file mode 100644 index 0000000..c000ad0 --- /dev/null +++ b/SOURCES/unbound-1.25.1-CVE-2026-44390.patch @@ -0,0 +1,20 @@ +diff --git a/unbound-1.24.2/util/data/msgencode.c b/unbound-1.24.2/util/data/msgencode.c +index 7bc55a5..f84c491 100644 +--- a/unbound-1.24.2/util/data/msgencode.c ++++ b/unbound-1.24.2/util/data/msgencode.c +@@ -352,7 +352,6 @@ compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs, + (p = compress_tree_lookup(tree, dname, labs, &insertpt))) { + if(!write_compressed_dname(pkt, dname, labs, p)) + return RETVAL_TRUNC; +- (*compress_count)++; + } else { + if(!dname_buffer_write(pkt, dname)) + return RETVAL_TRUNC; +@@ -360,6 +359,7 @@ compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs, + if(*compress_count < MAX_COMPRESSION_PER_MESSAGE && + !compress_tree_store(dname, labs, pos, region, p, insertpt)) + return RETVAL_OUTMEM; ++ (*compress_count)++; + return RETVAL_OK; + } + diff --git a/SPECS/unbound.spec b/SPECS/unbound.spec index 620dcf4..70c8ed9 100644 --- a/SPECS/unbound.spec +++ b/SPECS/unbound.spec @@ -31,7 +31,7 @@ Summary: Validating, recursive, and caching DNS(SEC) resolver Name: unbound Version: 1.24.2 -Release: 3%{?extra_version:.%{extra_version}}%{?dist}.1 +Release: 3%{?extra_version:.%{extra_version}}%{?dist}.2 License: BSD Url: https://nlnetlabs.nl/projects/unbound/ Source: https://nlnetlabs.nl/downloads/%{name}/%{name}-%{version}%{?extra_version}.tar.gz @@ -75,6 +75,16 @@ Patch4: unbound-1.25.1-CVE-2026-33278.patch 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 +# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-40622.diff +Patch7: unbound-1.25.1-CVE-2026-40622.patch +# https://github.com/NLnetLabs/unbound/commit/b5f21f41658f65d6143df6a3208e8ccf1a01604d +Patch8: unbound-1.25.1-CVE-2026-40622-test.patch +# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-44390.diff +Patch9: unbound-1.25.1-CVE-2026-44390.patch +# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-41292.diff +Patch10: unbound-1.25.1-CVE-2026-41292.patch +# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-42534.diff +Patch11: unbound-1.25.1-CVE-2026-42534.patch BuildRequires: gcc BuildRequires: make @@ -516,8 +526,14 @@ popd %{_prefix}/lib/dracut/modules.d/99unbound %changelog +* Mon Jun 22 2026 Fedor Vorobev - 1.24.2-3.2 +- Fix CVE-2026-40622 (RHEL-184840) + Fix CVE-2026-44390 (RHEL-186688) + Fix CVE-2026-41292 (RHEL-187352) + Fix CVE-2026-42534 (RHEL-187095) + * Mon May 25 2026 Fedor Vorobev - 1.24.2-3.1 -- Fix CVE-2026-33278 (RHEL‑177822) +- Fix CVE-2026-33278 (RHEL-177822) Fix CVE-2026-42944 (RHEL-177936) Fix CVE-2026-42959 (RHEL-177797)