From 81203d6e27ee3e629ff5b5bacd4ae52c729bead3 Mon Sep 17 00:00:00 2001 From: Zhao Hang Date: Tue, 5 Dec 2023 14:14:09 +0800 Subject: [PATCH 1/3] update to bind-9.11.36-11.src.rpm Signed-off-by: Zhao Hang --- ...ing.patch => bind-9.11-CVE-2023-2828.patch | 43 +- bind-9.16-CVE-2022-3094-1.patch | 240 ++++++++ bind-9.16-CVE-2022-3094-2.patch | 136 +++++ bind-9.16-CVE-2022-3094-3.patch | 553 ++++++++++++++++++ bind-9.16-CVE-2022-3094-test.patch | 266 +++++++++ ...341.patch => bind-9.16-CVE-2023-3341.patch | 103 ++-- bind.spec | 36 +- dist | 2 +- 8 files changed, 1278 insertions(+), 101 deletions(-) rename Improve-RBT-overmem-cache-cleaning.patch => bind-9.11-CVE-2023-2828.patch (88%) create mode 100644 bind-9.16-CVE-2022-3094-1.patch create mode 100644 bind-9.16-CVE-2022-3094-2.patch create mode 100644 bind-9.16-CVE-2022-3094-3.patch create mode 100644 bind-9.16-CVE-2022-3094-test.patch rename bind-9.11-CVE-2023-3341.patch => bind-9.16-CVE-2023-3341.patch (63%) diff --git a/Improve-RBT-overmem-cache-cleaning.patch b/bind-9.11-CVE-2023-2828.patch similarity index 88% rename from Improve-RBT-overmem-cache-cleaning.patch rename to bind-9.11-CVE-2023-2828.patch index c522151..42c0132 100644 --- a/Improve-RBT-overmem-cache-cleaning.patch +++ b/bind-9.11-CVE-2023-2828.patch @@ -1,7 +1,7 @@ -From 0b12907a1cad9f0f2080965b6fc50e797f908aa5 Mon Sep 17 00:00:00 2001 +From f3aa755ba5ae5148dd0567357f8c538072e2eabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 30 May 2023 08:46:17 +0200 -Subject: [PATCH 1/2] Improve RBT overmem cache cleaning +Subject: [PATCH] Improve RBT overmem cache cleaning When cache memory usage is over the configured cache size (overmem) and we are cleaning unused entries, it might not be enough to clean just two @@ -26,14 +26,14 @@ cache going over the configured memory limit (`max-cache-size`). Additionally, refactor the overmem_purge() function to reduce for-loop nesting for readability. --- - lib/dns/rbtdb.c | 111 ++++++++++++++++++++++++++++-------------------- - 1 file changed, 66 insertions(+), 45 deletions(-) + lib/dns/rbtdb.c | 109 +++++++++++++++++++++++++++++------------------- + 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c -index 3ee18766cdb..ca315028b3b 100644 +index 11203e4..cc40eae 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c -@@ -815,7 +815,7 @@ static void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, +@@ -834,7 +834,7 @@ static void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, static void expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, bool tree_locked, expire_t reason); static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, @@ -42,7 +42,7 @@ index 3ee18766cdb..ca315028b3b 100644 static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader); static void resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, -@@ -6817,6 +6817,16 @@ addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader, +@@ -6937,6 +6937,16 @@ addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader, static dns_dbmethods_t zone_methods; @@ -59,20 +59,17 @@ index 3ee18766cdb..ca315028b3b 100644 static isc_result_t addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, -@@ -6970,8 +6980,10 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); +@@ -7091,7 +7101,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } -- if (cache_is_overmem) + if (cache_is_overmem) - overmem_purge(rbtdb, rbtnode->locknum, now, tree_locked); -+ if (cache_is_overmem) { + overmem_purge(rbtdb, rbtnode->locknum, rdataset_size(newheader), + tree_locked); -+ } NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock, isc_rwlocktype_write); -@@ -6986,9 +6998,14 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, +@@ -7106,9 +7117,19 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, cleanup_dead_nodes(rbtdb, rbtnode->locknum); header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1); @@ -82,6 +79,11 @@ index 3ee18766cdb..ca315028b3b 100644 + if (header != NULL) { + dns_ttl_t rdh_ttl = header->rdh_ttl; + ++ /* Only account for stale TTL if cache is not overmem */ ++ if (!cache_is_overmem) { ++ rdh_ttl += rbtdb->serve_stale_ttl; ++ } ++ + if (rdh_ttl < now - RBTDB_VIRTUAL) { + expire_header(rbtdb, header, tree_locked, + expire_ttl); @@ -90,7 +92,7 @@ index 3ee18766cdb..ca315028b3b 100644 /* * If we've been holding a write lock on the tree just for -@@ -10494,54 +10511,58 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, +@@ -10643,54 +10664,58 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum], header, link); } @@ -142,20 +144,18 @@ index 3ee18766cdb..ca315028b3b 100644 static void -overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, - isc_stdtime_t now, bool tree_locked) --{ -- rdatasetheader_t *header, *header_prev; +overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize, -+ bool tree_locked) { ++ bool tree_locked) + { +- rdatasetheader_t *header, *header_prev; unsigned int locknum; - int purgecount = 2; + size_t purged = 0; for (locknum = (locknum_start + 1) % rbtdb->node_lock_count; - locknum != locknum_start && purgecount > 0; -- locknum = (locknum + 1) % rbtdb->node_lock_count) { + locknum != locknum_start && purged <= purgesize; -+ locknum = (locknum + 1) % rbtdb->node_lock_count) -+ { + locknum = (locknum + 1) % rbtdb->node_lock_count) { NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); @@ -189,4 +189,5 @@ index 3ee18766cdb..ca315028b3b 100644 NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); -- -GitLab +2.40.1 + diff --git a/bind-9.16-CVE-2022-3094-1.patch b/bind-9.16-CVE-2022-3094-1.patch new file mode 100644 index 0000000..3a3e9c0 --- /dev/null +++ b/bind-9.16-CVE-2022-3094-1.patch @@ -0,0 +1,240 @@ +From 128b3b676eb9413b4d25fb29c560895cfbbfa92e Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Thu, 1 Sep 2022 16:05:04 -0700 +Subject: [PATCH] add an update quota + +limit the number of simultaneous DNS UPDATE events that can be +processed by adding a quota for update and update forwarding. +this quota currently, arbitrarily, defaults to 100. + +also add a statistics counter to record when the update quota +has been exceeded. + +(cherry picked from commit 7c47254a140c3e9cf383cda73c7b6a55c4782826) +--- + bin/named/bind9.xsl | 2 +- + bin/named/bind9.xsl.h | 8 +++++++- + bin/named/include/named/server.h | 7 ++++++- + bin/named/server.c | 3 +++ + bin/named/statschannel.c | 5 +++-- + bin/named/update.c | 34 +++++++++++++++++++++++++++++++- + doc/arm/Bv9ARM-book.xml | 15 ++++++++++++++ + 7 files changed, 68 insertions(+), 6 deletions(-) + +diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl +index 9a1c6ff..85fd4c4 100644 +--- a/bin/named/bind9.xsl ++++ b/bin/named/bind9.xsl +@@ -12,7 +12,7 @@ + + + +- ++ + + + +diff --git a/bin/named/bind9.xsl.h b/bin/named/bind9.xsl.h +index 9ce8cd7..5e0a892 100644 +--- a/bin/named/bind9.xsl.h ++++ b/bin/named/bind9.xsl.h +@@ -17,7 +17,13 @@ static char xslmsg[] = + "\n" + "\n" + " \n" +- " \n" ++#if 0 ++ " \n" ++ " \n" ++#endif ++ " \n" + " \n" + " \n" + " \n" +diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h +index 08a02dc..259acc7 100644 +--- a/bin/named/include/named/server.h ++++ b/bin/named/include/named/server.h +@@ -137,6 +137,9 @@ struct ns_server { + + uint16_t transfer_tcp_message_size; + isc_rng_t * rngctx; ++ ++/* CVE-2022-3094 */ ++ isc_quota_t updquota; + }; + + struct ns_altsecret { +@@ -230,7 +233,9 @@ enum { + dns_nsstatscounter_trystale = 59, + dns_nsstatscounter_usedstale = 60, + +- dns_nsstatscounter_max = 61 ++ dns_nsstatscounter_updatequota = 61, ++ ++ dns_nsstatscounter_max = 62 + }; + + /*% +diff --git a/bin/named/server.c b/bin/named/server.c +index 2d2fa0e..f09b895 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -9143,6 +9143,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { + RUNTIME_CHECK(result == ISC_R_SUCCESS); + result = isc_quota_init(&server->recursionquota, 100); + RUNTIME_CHECK(result == ISC_R_SUCCESS); ++ result = isc_quota_init(&server->updquota, 100); ++ RUNTIME_CHECK(result == ISC_R_SUCCESS); + + result = dns_aclenv_init(mctx, &server->aclenv); + RUNTIME_CHECK(result == ISC_R_SUCCESS); +@@ -9410,6 +9412,7 @@ ns_server_destroy(ns_server_t **serverp) { + + dns_aclenv_destroy(&server->aclenv); + ++ isc_quota_destroy(&server->updquota); + isc_quota_destroy(&server->recursionquota); + isc_quota_destroy(&server->tcpquota); + isc_quota_destroy(&server->xfroutquota); +diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c +index 56a9c21..1e8723c 100644 +--- a/bin/named/statschannel.c ++++ b/bin/named/statschannel.c +@@ -300,6 +300,7 @@ init_desc(void) { + SET_NSSTATDESC(reclimitdropped, + "queries dropped due to recursive client limit", + "RecLimitDropped"); ++ SET_NSSTATDESC(updatequota, "Update quota exceeded", "UpdateQuota"); + SET_NSSTATDESC(trystale, + "attempts to use stale cache data after lookup failure", + "QryTryStale"); +@@ -1546,7 +1547,7 @@ generatexml(ns_server_t *server, uint32_t flags, + ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.xsl\"")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version", +- ISC_XMLCHAR "3.8")); ++ ISC_XMLCHAR "3.8.1")); + + /* Set common fields for statistics dump */ + dumparg.type = isc_statsformat_xml; +@@ -2303,7 +2304,7 @@ generatejson(ns_server_t *server, size_t *msglen, + /* + * These statistics are included no matter which URL we use. + */ +- obj = json_object_new_string("1.2"); ++ obj = json_object_new_string("1.2.1"); + CHECKMEM(obj); + json_object_object_add(bindstats, "json-stats-version", obj); + +diff --git a/bin/named/update.c b/bin/named/update.c +index 6ad7d27..dccc543 100644 +--- a/bin/named/update.c ++++ b/bin/named/update.c +@@ -1526,6 +1526,17 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) { + isc_task_t *zonetask = NULL; + ns_client_t *evclient; + ++ result = isc_quota_attach(&ns_g_server->updquota, ++ &(isc_quota_t *){ NULL }); ++ if (result != ISC_R_SUCCESS) { ++ update_log(client, zone, LOGLEVEL_PROTOCOL, ++ "update failed: too many DNS UPDATEs queued (%s)", ++ isc_result_totext(result)); ++ isc_stats_increment(ns_g_server->nsstats, ++ dns_nsstatscounter_updatequota); ++ CHECK(DNS_R_DROP); ++ } ++ + event = (update_event_t *) + isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, + update_action, NULL, sizeof(*event)); +@@ -1652,7 +1663,12 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { + * We are still in the client task context, so we can + * simply give an error response without switching tasks. + */ +- respond(client, result); ++ if (result == DNS_R_DROP) { ++ ns_client_next(client, result); ++ } else { ++ respond(client, result); ++ } ++ + if (zone != NULL) + dns_zone_detach(&zone); + } +@@ -3385,6 +3401,7 @@ updatedone_action(isc_task_t *task, isc_event_t *event) { + dns_zone_detach(&uev->zone); + client->nupdates--; + respond(client, uev->result); ++ isc_quota_detach(&(isc_quota_t *){ &ns_g_server->updquota }); + isc_event_free(&event); + ns_client_detach(&client); + } +@@ -3402,6 +3419,8 @@ forward_fail(isc_task_t *task, isc_event_t *event) { + INSIST(client->nupdates > 0); + client->nupdates--; + respond(client, DNS_R_SERVFAIL); ++ ++ isc_quota_detach(&(isc_quota_t *){ &ns_g_server->updquota }); + isc_event_free(&event); + ns_client_detach(&client); + } +@@ -3439,6 +3458,8 @@ forward_done(isc_task_t *task, isc_event_t *event) { + client->nupdates--; + ns_client_sendraw(client, uev->answer); + dns_message_detach(&uev->answer); ++ ++ isc_quota_detach(&(isc_quota_t *){ &ns_g_server->updquota }); + isc_event_free(&event); + ns_client_detach(&client); + } +@@ -3472,6 +3493,17 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) { + isc_task_t *zonetask = NULL; + ns_client_t *evclient; + ++ result = isc_quota_attach(&ns_g_server->updquota, ++ &(isc_quota_t *){ NULL }); ++ if (result != ISC_R_SUCCESS) { ++ update_log(client, zone, LOGLEVEL_PROTOCOL, ++ "update failed: too many DNS UPDATEs queued (%s)", ++ isc_result_totext(result)); ++ isc_stats_increment(ns_g_server->nsstats, ++ dns_nsstatscounter_updatequota); ++ return (DNS_R_DROP); ++ } ++ + /* + * This may take some time so replace this client. + */ +diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml +index c17f168..9aca6d7 100644 +--- a/doc/arm/Bv9ARM-book.xml ++++ b/doc/arm/Bv9ARM-book.xml +@@ -15105,6 +15105,21 @@ HOST-127.EXAMPLE. MX 0 . + + + ++ ++ ++ UpdateQuota ++ ++ ++ ++ ++ ++ ++ This indicates the number of times a dynamic update or update ++ forwarding request was rejected because the number of pending ++ requests exceeded the update quota. ++ ++ ++ + + + RateDropped +-- +2.39.2 + diff --git a/bind-9.16-CVE-2022-3094-2.patch b/bind-9.16-CVE-2022-3094-2.patch new file mode 100644 index 0000000..f4ec472 --- /dev/null +++ b/bind-9.16-CVE-2022-3094-2.patch @@ -0,0 +1,136 @@ +From d9a03233c6ea11f20c2fbeca87b763673859f8b2 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Thu, 1 Sep 2022 16:22:46 -0700 +Subject: [PATCH] add a configuration option for the update quota + +add an "update-quota" option to configure the update quota. + +(cherry picked from commit f57758a7303ad0034ff2ff08eaaf2ef899630f19) +--- + bin/named/config.c | 1 + + bin/named/named.conf.docbook | 2 ++ + bin/named/server.c | 1 + + bin/tests/system/checkconf/good.conf | 1 + + doc/arm/Bv9ARM-book.xml | 11 +++++++++++ + doc/arm/options.grammar.xml | 1 + + doc/misc/options | 1 + + lib/isccfg/namedconf.c | 1 + + 8 files changed, 19 insertions(+) + +diff --git a/bin/named/config.c b/bin/named/config.c +index 62d1e88..e3731cf 100644 +--- a/bin/named/config.c ++++ b/bin/named/config.c +@@ -134,6 +134,7 @@ options {\n\ + transfers-per-ns 2;\n\ + # treat-cr-as-space ;\n\ + trust-anchor-telemetry yes;\n\ ++ update-quota 100;\n\ + # use-id-pool ;\n\ + # use-ixfr ;\n\ + \n\ +diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook +index 6565fce..5842cb5 100644 +--- a/bin/named/named.conf.docbook ++++ b/bin/named/named.conf.docbook +@@ -455,6 +455,7 @@ options { + trust-anchor-telemetry boolean; // experimental + try-tcp-refresh boolean; + update-check-ksk boolean; ++ update-quota integer; + use-alt-transfer-source boolean; + use-v4-udp-ports { portrange; ... }; + use-v6-udp-ports { portrange; ... }; +@@ -864,6 +865,7 @@ view string [ class ] { + type ( delegation-only | forward | hint | master | redirect + | slave | static-stub | stub ); + update-check-ksk boolean; ++ update-quota integer; + update-policy ( local | { ( deny | grant ) string ( + 6to4-self | external | krb5-self | krb5-selfsub | + krb5-subdomain | ms-self | ms-selfsub | ms-subdomain | +diff --git a/bin/named/server.c b/bin/named/server.c +index f09b895..7af90d0 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -7792,6 +7792,7 @@ load_configuration(const char *filename, ns_server_t *server, + configure_server_quota(maps, "tcp-clients", &server->tcpquota); + configure_server_quota(maps, "recursive-clients", + &server->recursionquota); ++ configure_server_quota(maps, "update-quota", &server->updquota); + + if (server->recursionquota.max > 1000) { + int margin = ISC_MAX(100, ns_g_cpus + 1); +diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf +index 1359cf3..5d9b292 100644 +--- a/bin/tests/system/checkconf/good.conf ++++ b/bin/tests/system/checkconf/good.conf +@@ -63,6 +63,7 @@ options { + serial-queries 10; + serial-query-rate 100; + server-id none; ++ update-quota 200; + max-cache-size 20000000000000; + nta-lifetime 604800; + nta-recheck 604800; +diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml +index 9aca6d7..acf772b 100644 +--- a/doc/arm/Bv9ARM-book.xml ++++ b/doc/arm/Bv9ARM-book.xml +@@ -8599,6 +8599,17 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; + + + ++ ++ update-quota ++ ++ ++ This is the maximum number of simultaneous DNS UPDATE messages that ++ the server will accept for updating local authoritiative zones or ++ forwarding to a primary server. The default is 100. ++ ++ ++ ++ + + + +diff --git a/doc/arm/options.grammar.xml b/doc/arm/options.grammar.xml +index 793ac0b..1d17ea8 100644 +--- a/doc/arm/options.grammar.xml ++++ b/doc/arm/options.grammar.xml +@@ -277,6 +277,7 @@ + trust-anchor-telemetry boolean; // experimental + try-tcp-refresh boolean; + update-check-ksk boolean; ++ update-quota integer; + use-alt-transfer-source boolean; + use-v4-udp-ports { portrange; ... }; + use-v6-udp-ports { portrange; ... }; +diff --git a/doc/misc/options b/doc/misc/options +index fde93c7..e6d6ba6 100644 +--- a/doc/misc/options ++++ b/doc/misc/options +@@ -357,6 +357,7 @@ options { + trust-anchor-telemetry ; // experimental + try-tcp-refresh ; + update-check-ksk ; ++ update-quota ; + use-alt-transfer-source ; + use-id-pool ; // obsolete + use-ixfr ; // obsolete +diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c +index b562f95..667111c 100644 +--- a/lib/isccfg/namedconf.c ++++ b/lib/isccfg/namedconf.c +@@ -1136,6 +1136,7 @@ options_clauses[] = { + { "transfers-out", &cfg_type_uint32, 0 }, + { "transfers-per-ns", &cfg_type_uint32, 0 }, + { "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, ++ { "update-quota", &cfg_type_uint32, 0 }, + { "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, + { "use-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, + { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, +-- +2.39.2 + diff --git a/bind-9.16-CVE-2022-3094-3.patch b/bind-9.16-CVE-2022-3094-3.patch new file mode 100644 index 0000000..1d39423 --- /dev/null +++ b/bind-9.16-CVE-2022-3094-3.patch @@ -0,0 +1,553 @@ +From cba333b262b7ee0034a66cc93cf27f6c4918eea2 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Tue, 8 Nov 2022 17:32:41 -0800 +Subject: [PATCH] move update ACL and update-policy checks before quota + +check allow-update, update-policy, and allow-update-forwarding before +consuming quota slots, so that unauthorized clients can't fill the +quota. + +(this moves the access check before the prerequisite check, which +violates the precise wording of RFC 2136. however, RFC co-author Paul +Vixie has stated that the RFC is mistaken on this point; it should have +said that access checking must happen *no later than* the completion of +prerequisite checks, not that it must happen exactly then.) + +(cherry picked from commit 964f559edb5036880b8e463b8f190b9007ee055d) +--- + bin/named/update.c | 440 ++++++++++++++++++++++++++++++--------------- + 1 file changed, 298 insertions(+), 142 deletions(-) + +diff --git a/bin/named/update.c b/bin/named/update.c +index 8853ee7..4d1fe78 100644 +--- a/bin/named/update.c ++++ b/bin/named/update.c +@@ -251,6 +251,9 @@ static void updatedone_action(isc_task_t *task, isc_event_t *event); + static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone); + static void forward_done(isc_task_t *task, isc_event_t *event); + static isc_result_t add_rr_prepare_action(void *data, rr_t *rr); ++static isc_result_t ++rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, ++ const dns_rdata_t *rdata, bool *flag); + + /**************************************************************************/ + +@@ -328,23 +331,24 @@ checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename, + { + char namebuf[DNS_NAME_FORMATSIZE]; + char classbuf[DNS_RDATACLASS_FORMATSIZE]; +- int level; + isc_result_t result; ++ bool update_possible = ++ ((updateacl != NULL && !dns_acl_isnone(updateacl)) || ++ ssutable != NULL); + + result = ns_client_checkaclsilent(client, NULL, queryacl, true); + if (result != ISC_R_SUCCESS) { ++ int level = update_possible ? ISC_LOG_ERROR : ISC_LOG_INFO; ++ + dns_name_format(zonename, namebuf, sizeof(namebuf)); + dns_rdataclass_format(client->view->rdclass, classbuf, + sizeof(classbuf)); + +- level = (updateacl == NULL && ssutable == NULL) ? +- ISC_LOG_INFO : ISC_LOG_ERROR; +- + ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, + NS_LOGMODULE_UPDATE, level, + "update '%s/%s' denied due to allow-query", + namebuf, classbuf); +- } else if (updateacl == NULL && ssutable == NULL) { ++ } else if (!update_possible) { + dns_name_format(zonename, namebuf, sizeof(namebuf)); + dns_rdataclass_format(client->view->rdclass, classbuf, + sizeof(classbuf)); +@@ -1525,6 +1529,277 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) { + update_event_t *event = NULL; + isc_task_t *zonetask = NULL; + ns_client_t *evclient; ++#if 1 ++ dns_ssutable_t *ssutable = NULL; ++ dns_message_t *request = client->message; ++ dns_rdataclass_t zoneclass; ++ dns_rdatatype_t covers; ++ dns_name_t *zonename = NULL; ++ dns_db_t *db = NULL; ++ dns_dbversion_t *ver = NULL; ++ ++ CHECK(dns_zone_getdb(zone, &db)); ++ zonename = dns_db_origin(db); ++ zoneclass = dns_db_class(db); ++ dns_zone_getssutable(zone, &ssutable); ++ dns_db_currentversion(db, &ver); ++ ++ /* ++ * Update message processing can leak record existence information ++ * so check that we are allowed to query this zone. Additionally, ++ * if we would refuse all updates for this zone, we bail out here. ++ */ ++ CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), ++ dns_zone_getorigin(zone), ++ dns_zone_getupdateacl(zone), ssutable)); ++ ++ /* ++ * Check requestor's permissions. ++ */ ++ if (ssutable == NULL) ++ CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone), ++ "update", zonename, false, false)); ++ else if (client->signer == NULL && !TCPCLIENT(client)) ++ CHECK(checkupdateacl(client, NULL, "update", zonename, ++ false, true)); ++ ++ if (dns_zone_getupdatedisabled(zone)) ++ FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled " ++ "because the zone is frozen. Use " ++ "'rndc thaw' to re-enable updates."); ++ ++ /* ++ * Perform the Update Section Prescan. ++ */ ++ ++ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); ++ result == ISC_R_SUCCESS; ++ result = dns_message_nextname(request, DNS_SECTION_UPDATE)) ++ { ++ dns_name_t *name = NULL; ++ dns_rdata_t rdata = DNS_RDATA_INIT; ++ dns_ttl_t ttl; ++ dns_rdataclass_t update_class; ++ get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, ++ &name, &rdata, &covers, &ttl, &update_class); ++ ++ if (! dns_name_issubdomain(name, zonename)) ++ FAILC(DNS_R_NOTZONE, ++ "update RR is outside zone"); ++ if (update_class == zoneclass) { ++ /* ++ * Check for meta-RRs. The RFC2136 pseudocode says ++ * check for ANY|AXFR|MAILA|MAILB, but the text adds ++ * "or any other QUERY metatype" ++ */ ++ if (dns_rdatatype_ismeta(rdata.type)) { ++ FAILC(DNS_R_FORMERR, ++ "meta-RR in update"); ++ } ++ result = dns_zone_checknames(zone, name, &rdata); ++ if (result != ISC_R_SUCCESS) ++ FAIL(DNS_R_REFUSED); ++ } else if (update_class == dns_rdataclass_any) { ++ if (ttl != 0 || rdata.length != 0 || ++ (dns_rdatatype_ismeta(rdata.type) && ++ rdata.type != dns_rdatatype_any)) ++ FAILC(DNS_R_FORMERR, ++ "meta-RR in update"); ++ } else if (update_class == dns_rdataclass_none) { ++ if (ttl != 0 || ++ dns_rdatatype_ismeta(rdata.type)) ++ FAILC(DNS_R_FORMERR, ++ "meta-RR in update"); ++ } else { ++ update_log(client, zone, ISC_LOG_WARNING, ++ "update RR has incorrect class %d", ++ update_class); ++ FAIL(DNS_R_FORMERR); ++ } ++ ++ /* ++ * draft-ietf-dnsind-simple-secure-update-01 says ++ * "Unlike traditional dynamic update, the client ++ * is forbidden from updating NSEC records." ++ */ ++ if (rdata.type == dns_rdatatype_nsec3) { ++ FAILC(DNS_R_REFUSED, ++ "explicit NSEC3 updates are not allowed " ++ "in secure zones"); ++ } else if (rdata.type == dns_rdatatype_nsec) { ++ FAILC(DNS_R_REFUSED, ++ "explicit NSEC updates are not allowed " ++ "in secure zones"); ++ } else if (rdata.type == dns_rdatatype_rrsig && ++ !dns_name_equal(name, zonename)) { ++ FAILC(DNS_R_REFUSED, ++ "explicit RRSIG updates are currently " ++ "not supported in secure zones except " ++ "at the apex"); ++ } ++ ++ if (ssutable != NULL) { ++ isc_netaddr_t netaddr; ++ dst_key_t *tsigkey = NULL; ++ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); ++ ++ if (client->message->tsigkey != NULL) ++ tsigkey = client->message->tsigkey->key; ++ ++ if (rdata.type != dns_rdatatype_any) { ++ if (!dns_ssutable_checkrules2 ++ (ssutable, client->signer, name, &netaddr, ++ TCPCLIENT(client), ++ &ns_g_server->aclenv, ++ rdata.type, tsigkey)) ++ { ++ FAILC(DNS_R_REFUSED, ++ "rejected by secure update"); ++ } ++ } else { ++ if (!ssu_checkall(db, ver, name, ssutable, ++ client->signer, ++ &netaddr, ++ TCPCLIENT(client), ++ tsigkey)) ++ { ++ FAILC(DNS_R_REFUSED, ++ "rejected by secure update"); ++ } ++ } ++ } ++ } ++ if (result != ISC_R_NOMORE) ++ FAIL(result); ++ ++ update_log(client, zone, LOGLEVEL_DEBUG, ++ "update section prescan OK"); ++#if 0 ++ if (ssutable == NULL) { ++ CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone), ++ // zonename ++ "update", dns_zone_getorigin(zone), false, ++ false)); ++ } else if (client->signer == NULL && !TCPCLIENT(client)) { ++ CHECK(checkupdateacl(client, NULL, "update", ++ dns_zone_getorigin(zone), false, true)); ++ } ++ ++ if (dns_zone_getupdatedisabled(zone)) { ++ FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled " ++ "because the zone is frozen. Use " ++ "'rndc thaw' to re-enable updates."); ++ } ++ ++ /* ++ * Prescan the update section, checking for updates that ++ * are illegal or violate policy. ++ */ ++ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); ++ result == ISC_R_SUCCESS; ++ result = dns_message_nextname(request, DNS_SECTION_UPDATE)) ++ { ++ dns_name_t *name = NULL; ++ dns_rdata_t rdata = DNS_RDATA_INIT; ++ dns_ttl_t ttl; ++ dns_rdataclass_t update_class; ++ ++ get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name, ++ &rdata, &covers, &ttl, &update_class); ++ ++ if (!dns_name_issubdomain(name, zonename)) { ++ FAILC(DNS_R_NOTZONE, "update RR is outside zone"); ++ } ++ if (update_class == zoneclass) { ++ /* ++ * Check for meta-RRs. The RFC2136 pseudocode says ++ * check for ANY|AXFR|MAILA|MAILB, but the text adds ++ * "or any other QUERY metatype" ++ */ ++ if (dns_rdatatype_ismeta(rdata.type)) { ++ FAILC(DNS_R_FORMERR, "meta-RR in update"); ++ } ++ result = dns_zone_checknames(zone, name, &rdata); ++ if (result != ISC_R_SUCCESS) { ++ FAIL(DNS_R_REFUSED); ++ } ++ } else if (update_class == dns_rdataclass_any) { ++ if (ttl != 0 || rdata.length != 0 || ++ (dns_rdatatype_ismeta(rdata.type) && ++ rdata.type != dns_rdatatype_any)) ++ { ++ FAILC(DNS_R_FORMERR, "meta-RR in update"); ++ } ++ } else if (update_class == dns_rdataclass_none) { ++ if (ttl != 0 || dns_rdatatype_ismeta(rdata.type)) { ++ FAILC(DNS_R_FORMERR, "meta-RR in update"); ++ } ++ } else { ++ update_log(client, zone, ISC_LOG_WARNING, ++ "update RR has incorrect class %d", ++ update_class); ++ FAIL(DNS_R_FORMERR); ++ } ++ ++ /* ++ * draft-ietf-dnsind-simple-secure-update-01 says ++ * "Unlike traditional dynamic update, the client ++ * is forbidden from updating NSEC records." ++ */ ++ if (rdata.type == dns_rdatatype_nsec3) { ++ FAILC(DNS_R_REFUSED, "explicit NSEC3 updates are not " ++ "allowed " ++ "in secure zones"); ++ } else if (rdata.type == dns_rdatatype_nsec) { ++ FAILC(DNS_R_REFUSED, "explicit NSEC updates are not " ++ "allowed " ++ "in secure zones"); ++ } else if (rdata.type == dns_rdatatype_rrsig && ++ !dns_name_equal(name, zonename)) ++ { ++ FAILC(DNS_R_REFUSED, "explicit RRSIG updates are " ++ "currently " ++ "not supported in secure zones " ++ "except " ++ "at the apex"); ++ } ++ ++ if (ssutable != NULL) { ++ isc_netaddr_t netaddr; ++ dst_key_t *tsigkey = NULL; ++ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); ++ ++ if (client->message->tsigkey != NULL) { ++ tsigkey = client->message->tsigkey->key; ++ } ++ ++ if (rdata.type != dns_rdatatype_any) { ++ if (!dns_ssutable_checkrules( ++ ssutable, client->signer, name, ++ &netaddr, TCPCLIENT(client), env, ++ rdata.type, tsigkey)) ++ { ++ FAILC(DNS_R_REFUSED, "rejected by " ++ "secure update"); ++ } ++ } else { ++ if (!ssu_checkall(db, ver, name, ssutable, ++ client->signer, &netaddr, env, ++ TCPCLIENT(client), tsigkey)) ++ { ++ FAILC(DNS_R_REFUSED, "rejected by " ++ "secure update"); ++ } ++ } ++ } ++ } ++ if (result != ISC_R_NOMORE) { ++ FAIL(result); ++ } ++ ++ update_log(client, zone, LOGLEVEL_DEBUG, "update section prescan OK"); ++#endif ++#endif + + result = isc_quota_attach(&ns_g_server->updquota, + &(isc_quota_t *){ NULL }); +@@ -1558,6 +1833,15 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) { + failure: + if (event != NULL) + isc_event_free(ISC_EVENT_PTR(&event)); ++ if (db != NULL) { ++ dns_db_closeversion(db, &ver, false); ++ dns_db_detach(&db); ++ } ++ ++ if (ssutable != NULL) { ++ dns_ssutable_detach(&ssutable); ++ } ++ + return (result); + } + +@@ -1644,9 +1928,6 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { + CHECK(send_update_event(client, zone)); + break; + case dns_zone_slave: +- CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone), +- "update forwarding", zonename, true, +- false)); + CHECK(send_forward_event(client, zone)); + break; + default: +@@ -1656,7 +1937,6 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { + + failure: + if (result == DNS_R_REFUSED) { +- INSIST(dns_zone_gettype(zone) == dns_zone_slave); + inc_stats(zone, dns_nsstatscounter_updaterej); + } + /* +@@ -2520,7 +2800,7 @@ update_action(isc_task_t *task, isc_event_t *event) { + dns_rdatatype_t covers; + dns_message_t *request = client->message; + dns_rdataclass_t zoneclass; +- dns_name_t *zonename; ++ dns_name_t *zonename = NULL; + dns_ssutable_t *ssutable = NULL; + dns_fixedname_t tmpnamefixed; + dns_name_t *tmpname = NULL; +@@ -2542,14 +2822,7 @@ update_action(isc_task_t *task, isc_event_t *event) { + zonename = dns_db_origin(db); + zoneclass = dns_db_class(db); + dns_zone_getssutable(zone, &ssutable); +- +- /* +- * Update message processing can leak record existence information +- * so check that we are allowed to query this zone. Additionally +- * if we would refuse all updates for this zone we bail out here. +- */ +- CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename, +- dns_zone_getupdateacl(zone), ssutable)); ++ options = dns_zone_getoptions(zone); + + /* + * Get old and new versions now that queryacl has been checked. +@@ -2673,134 +2946,10 @@ update_action(isc_task_t *task, isc_event_t *event) { + update_log(client, zone, LOGLEVEL_DEBUG, + "prerequisites are OK"); + +- /* +- * Check Requestor's Permissions. It seems a bit silly to do this +- * only after prerequisite testing, but that is what RFC2136 says. +- */ +- if (ssutable == NULL) +- CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone), +- "update", zonename, false, false)); +- else if (client->signer == NULL && !TCPCLIENT(client)) +- CHECK(checkupdateacl(client, NULL, "update", zonename, +- false, true)); +- +- if (dns_zone_getupdatedisabled(zone)) +- FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled " +- "because the zone is frozen. Use " +- "'rndc thaw' to re-enable updates."); +- +- /* +- * Perform the Update Section Prescan. +- */ +- +- for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); +- result == ISC_R_SUCCESS; +- result = dns_message_nextname(request, DNS_SECTION_UPDATE)) +- { +- dns_name_t *name = NULL; +- dns_rdata_t rdata = DNS_RDATA_INIT; +- dns_ttl_t ttl; +- dns_rdataclass_t update_class; +- get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, +- &name, &rdata, &covers, &ttl, &update_class); +- +- if (! dns_name_issubdomain(name, zonename)) +- FAILC(DNS_R_NOTZONE, +- "update RR is outside zone"); +- if (update_class == zoneclass) { +- /* +- * Check for meta-RRs. The RFC2136 pseudocode says +- * check for ANY|AXFR|MAILA|MAILB, but the text adds +- * "or any other QUERY metatype" +- */ +- if (dns_rdatatype_ismeta(rdata.type)) { +- FAILC(DNS_R_FORMERR, +- "meta-RR in update"); +- } +- result = dns_zone_checknames(zone, name, &rdata); +- if (result != ISC_R_SUCCESS) +- FAIL(DNS_R_REFUSED); +- } else if (update_class == dns_rdataclass_any) { +- if (ttl != 0 || rdata.length != 0 || +- (dns_rdatatype_ismeta(rdata.type) && +- rdata.type != dns_rdatatype_any)) +- FAILC(DNS_R_FORMERR, +- "meta-RR in update"); +- } else if (update_class == dns_rdataclass_none) { +- if (ttl != 0 || +- dns_rdatatype_ismeta(rdata.type)) +- FAILC(DNS_R_FORMERR, +- "meta-RR in update"); +- } else { +- update_log(client, zone, ISC_LOG_WARNING, +- "update RR has incorrect class %d", +- update_class); +- FAIL(DNS_R_FORMERR); +- } +- +- /* +- * draft-ietf-dnsind-simple-secure-update-01 says +- * "Unlike traditional dynamic update, the client +- * is forbidden from updating NSEC records." +- */ +- if (rdata.type == dns_rdatatype_nsec3) { +- FAILC(DNS_R_REFUSED, +- "explicit NSEC3 updates are not allowed " +- "in secure zones"); +- } else if (rdata.type == dns_rdatatype_nsec) { +- FAILC(DNS_R_REFUSED, +- "explicit NSEC updates are not allowed " +- "in secure zones"); +- } else if (rdata.type == dns_rdatatype_rrsig && +- !dns_name_equal(name, zonename)) { +- FAILC(DNS_R_REFUSED, +- "explicit RRSIG updates are currently " +- "not supported in secure zones except " +- "at the apex"); +- } +- +- if (ssutable != NULL) { +- isc_netaddr_t netaddr; +- dst_key_t *tsigkey = NULL; +- isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); +- +- if (client->message->tsigkey != NULL) +- tsigkey = client->message->tsigkey->key; +- +- if (rdata.type != dns_rdatatype_any) { +- if (!dns_ssutable_checkrules2 +- (ssutable, client->signer, name, &netaddr, +- TCPCLIENT(client), +- &ns_g_server->aclenv, +- rdata.type, tsigkey)) +- { +- FAILC(DNS_R_REFUSED, +- "rejected by secure update"); +- } +- } else { +- if (!ssu_checkall(db, ver, name, ssutable, +- client->signer, +- &netaddr, +- TCPCLIENT(client), +- tsigkey)) +- { +- FAILC(DNS_R_REFUSED, +- "rejected by secure update"); +- } +- } +- } +- } +- if (result != ISC_R_NOMORE) +- FAIL(result); +- +- update_log(client, zone, LOGLEVEL_DEBUG, +- "update section prescan OK"); +- + /* + * Process the Update Section. + */ + +- options = dns_zone_getoptions(zone); + options2 = dns_zone_getoptions2(zone); + for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); + result == ISC_R_SUCCESS; +@@ -3494,6 +3643,13 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) { + isc_task_t *zonetask = NULL; + ns_client_t *evclient; + ++ result = checkupdateacl(client, dns_zone_getforwardacl(zone), ++ "update forwarding", dns_zone_getorigin(zone), ++ true, false); ++ if (result != ISC_R_SUCCESS) { ++ return (result); ++ } ++ + result = isc_quota_attach(&ns_g_server->updquota, + &(isc_quota_t *){ NULL }); + if (result != ISC_R_SUCCESS) { +-- +2.39.2 + diff --git a/bind-9.16-CVE-2022-3094-test.patch b/bind-9.16-CVE-2022-3094-test.patch new file mode 100644 index 0000000..fe93e26 --- /dev/null +++ b/bind-9.16-CVE-2022-3094-test.patch @@ -0,0 +1,266 @@ +From 3d84c651f823cb90b73fd736d32ad6de57b11610 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Wed, 9 Nov 2022 21:56:16 -0800 +Subject: [PATCH] test failure conditions + +verify that updates are refused when the client is disallowed by +allow-query, and update forwarding is refused when the client is +is disallowed by update-forwarding. + +verify that "too many DNS UPDATEs" appears in the log file when too +many simultaneous updates are processing. + +(cherry picked from commit b91339b80e5b82a56622c93cc1e3cca2d0c11bc0) +--- + bin/tests/system/nsupdate/ns1/named.conf.in | 2 + + bin/tests/system/nsupdate/tests.sh | 28 +++++++++++++ + bin/tests/system/upforwd/clean.sh | 2 + + .../ns3/{named.conf.in => named1.conf.in} | 7 +++- + bin/tests/system/upforwd/ns3/named2.conf.in | 41 +++++++++++++++++++ + bin/tests/system/upforwd/setup.sh | 2 +- + bin/tests/system/upforwd/tests.sh | 40 ++++++++++++++++++ + 7 files changed, 120 insertions(+), 2 deletions(-) + rename bin/tests/system/upforwd/ns3/{named.conf.in => named1.conf.in} (85%) + create mode 100644 bin/tests/system/upforwd/ns3/named2.conf.in + +diff --git a/bin/tests/system/nsupdate/ns1/named.conf.in b/bin/tests/system/nsupdate/ns1/named.conf.in +index cb80269..228ad6a 100644 +--- a/bin/tests/system/nsupdate/ns1/named.conf.in ++++ b/bin/tests/system/nsupdate/ns1/named.conf.in +@@ -20,6 +20,7 @@ options { + listen-on-v6 { none; }; + recursion no; + notify yes; ++ update-quota 1; + }; + + key rndc_key { +@@ -76,6 +77,7 @@ zone "other.nil" { + check-integrity no; + check-mx warn; + update-policy local; ++ allow-query { !10.53.0.2; any; }; + allow-query-on { 10.53.0.1; 127.0.0.1; }; + allow-transfer { any; }; + }; +diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh +index f8994ff..4cabf8d 100755 +--- a/bin/tests/system/nsupdate/tests.sh ++++ b/bin/tests/system/nsupdate/tests.sh +@@ -1069,6 +1069,34 @@ END + grep "NSEC3PARAM has excessive iterations (> 150)" nsupdate.out-$n >/dev/null || ret=1 + [ $ret = 0 ] || { echo_i "failed"; status=1; } + ++n=$((n + 1)) ++ret=0 ++echo_i "check that update is rejected if query is not allowed ($n)" ++{ ++ $NSUPDATE -d < nsupdate.out.test$n 2>&1 ++grep 'status: REFUSED' nsupdate.out.test$n > /dev/null || ret=1 ++[ $ret = 0 ] || { echo_i "failed"; status=1; } ++ ++n=$((n + 1)) ++ret=0 ++echo_i "check that update is rejected if quota is exceeded ($n)" ++for loop in 1 2 3 4 5 6 7 8 9 10; do ++{ ++ $NSUPDATE -l -p ${PORT} -k ns1/session.key > nsupdate.out.test$n-${loop} 2>&1 < nsupdate.out.$n 2>&1 ++grep REFUSED nsupdate.out.$n > /dev/null || ret=1 ++if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi ++n=`expr $n + 1` ++ ++n=$((n + 1)) ++ret=0 ++echo_i "attempting updates that should exceed quota ($n)" ++# lower the update quota to 1. ++copy_setports ns3/named2.conf.in ns3/named.conf ++$RNDCCMD 10.53.0.3 reconfig ++nextpart ns3/named.run > /dev/null ++for loop in 1 2 3 4 5 6 7 8 9 10; do ++{ ++ $NSUPDATE -- - > /dev/null 2>&1 < -Date: Tue, 20 Jun 2023 15:21:36 +1000 -Subject: [PATCH] Limit isccc_cc_fromwire recursion depth +From 3883ec072e5feed1237dc864854ab95ded7302d6 Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Tue, 19 Sep 2023 13:14:52 +0200 +Subject: [PATCH] Backport of CVE-2023-3341 fix -Named and rndc do not need a lot of recursion so the depth is -set to 10. - -(cherry picked from commit 820b0cceef0b67b041973da4041ea53d5e276363) +Taken from BIND 9.16.44 change. --- - lib/isccc/cc.c | 60 +++++++++++++++++++++++++++------------- - lib/isccc/include/isccc/result.h | 4 ++- - lib/isccc/result.c | 4 ++- - 3 files changed, 47 insertions(+), 21 deletions(-) + lib/isccc/cc.c | 36 +++++++++++++++++++++++--------- + lib/isccc/include/isccc/result.h | 4 +++- + lib/isccc/result.c | 4 +++- + 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c -index e012685..7e1a6cd 100644 +index 463a053..a54e60c 100644 --- a/lib/isccc/cc.c +++ b/lib/isccc/cc.c -@@ -51,8 +51,12 @@ - #include - #include - --#define MAX_TAGS 256 --#define DUP_LIFETIME 900 -+#define MAX_TAGS 256 -+#define DUP_LIFETIME 900 +@@ -53,6 +53,10 @@ + + #define MAX_TAGS 256 + #define DUP_LIFETIME 900 +#ifndef ISCCC_MAXDEPTH +#define ISCCC_MAXDEPTH \ + 10 /* Big enough for rndc which just sends a string each way. */ @@ -32,7 +25,7 @@ index e012685..7e1a6cd 100644 typedef isccc_sexpr_t *sexpr_ptr; -@@ -561,21 +565,28 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, +@@ -573,19 +577,23 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, static isc_result_t table_fromwire(isccc_region_t *source, isccc_region_t *secret, @@ -41,63 +34,46 @@ index e012685..7e1a6cd 100644 static isc_result_t -list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp); -+list_fromwire(isccc_region_t *source, unsigned int depth, -+ isccc_sexpr_t **listp); ++list_fromwire(isccc_region_t *source, unsigned int depth, isccc_sexpr_t **listp); static isc_result_t -value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) { -+value_fromwire(isccc_region_t *source, unsigned int depth, -+ isccc_sexpr_t **valuep) { ++value_fromwire(isccc_region_t *source, unsigned int depth, isccc_sexpr_t **valuep) { unsigned int msgtype; uint32_t len; isccc_sexpr_t *value; isccc_region_t active; isc_result_t result; -- if (REGION_SIZE(*source) < 1 + 4) + if (depth > ISCCC_MAXDEPTH) { + return (ISCCC_R_MAXDEPTH); + } + -+ if (REGION_SIZE(*source) < 1 + 4) { + if (REGION_SIZE(*source) < 1 + 4) return (ISC_R_UNEXPECTEDEND); -+ } GET8(msgtype, source->rstart); - GET32(len, source->rstart); - if (REGION_SIZE(*source) < len) -@@ -588,22 +599,23 @@ value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) { - if (value != NULL) { - *valuep = value; - result = ISC_R_SUCCESS; -- } else -+ } else { +@@ -603,9 +611,9 @@ value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) { + } else result = ISC_R_NOMEMORY; -- } else if (msgtype == ISCCC_CCMSGTYPE_TABLE) + } else if (msgtype == ISCCC_CCMSGTYPE_TABLE) - result = table_fromwire(&active, NULL, 0, valuep); -- else if (msgtype == ISCCC_CCMSGTYPE_LIST) -- result = list_fromwire(&active, valuep); -- else -+ } -+ } else if (msgtype == ISCCC_CCMSGTYPE_TABLE) { + result = table_fromwire(&active, NULL, 0, depth + 1, valuep); -+ } else if (msgtype == ISCCC_CCMSGTYPE_LIST) { + else if (msgtype == ISCCC_CCMSGTYPE_LIST) +- result = list_fromwire(&active, valuep); + result = list_fromwire(&active, depth + 1, valuep); -+ } else { + else result = ISCCC_R_SYNTAX; -+ } - return (result); - } +@@ -614,7 +622,7 @@ value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) { static isc_result_t table_fromwire(isccc_region_t *source, isccc_region_t *secret, - uint32_t algorithm, isccc_sexpr_t **alistp) --{ -+ uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp) { ++ uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp) + { char key[256]; uint32_t len; - isc_result_t result; -@@ -613,6 +625,10 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret, +@@ -625,6 +633,10 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret, REQUIRE(alistp != NULL && *alistp == NULL); @@ -108,26 +84,21 @@ index e012685..7e1a6cd 100644 checksum_rstart = NULL; first_tag = true; alist = isccc_alist_create(); -@@ -628,9 +644,10 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret, +@@ -640,7 +652,7 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret, GET_MEM(key, len, source->rstart); key[len] = '\0'; /* Ensure NUL termination. */ value = NULL; - result = value_fromwire(source, &value); -- if (result != ISC_R_SUCCESS) + result = value_fromwire(source, depth + 1, &value); -+ if (result != ISC_R_SUCCESS) { + if (result != ISC_R_SUCCESS) goto bad; -+ } if (isccc_alist_define(alist, key, value) == NULL) { - result = ISC_R_NOMEMORY; - goto bad; -@@ -661,14 +678,19 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret, +@@ -673,14 +685,18 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret, } static isc_result_t -list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp) { -+list_fromwire(isccc_region_t *source, unsigned int depth, -+ isccc_sexpr_t **listp) { ++list_fromwire(isccc_region_t *source, unsigned int depth, isccc_sexpr_t **listp) { isccc_sexpr_t *list, *value; isc_result_t result; @@ -143,7 +114,7 @@ index e012685..7e1a6cd 100644 if (result != ISC_R_SUCCESS) { isccc_sexpr_free(&list); return (result); -@@ -699,7 +721,7 @@ isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp, +@@ -711,7 +727,7 @@ isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp, if (version != 1) return (ISCCC_R_UNKNOWNVERSION); @@ -169,7 +140,7 @@ index 6c79dd7..b30b08a 100644 ISC_LANG_BEGINDECLS diff --git a/lib/isccc/result.c b/lib/isccc/result.c -index 8419bbb..1ebd5d4 100644 +index 8419bbb..a3a3b9a 100644 --- a/lib/isccc/result.c +++ b/lib/isccc/result.c @@ -40,7 +40,8 @@ static const char *text[ISCCC_R_NRESULTS] = { @@ -178,7 +149,7 @@ index 8419bbb..1ebd5d4 100644 "clock skew", /* 5 */ - "duplicate" /* 6 */ + "duplicate", /* 6 */ -+ "max depth" /* 7 */ ++ "max depth", /* 7 */ }; static const char *ids[ISCCC_R_NRESULTS] = { @@ -186,10 +157,10 @@ index 8419bbb..1ebd5d4 100644 "ISCCC_R_EXPIRED", "ISCCC_R_CLOCKSKEW", "ISCCC_R_DUPLICATE", -+ "ISCCC_R_MAXDEPTH", ++ "ISCCC_R_MAXDEPTH" }; #define ISCCC_RESULT_RESULTSET 2 -- -1.8.3.1 +2.41.0 diff --git a/bind.spec b/bind.spec index 6d067f5..b0d0f91 100644 --- a/bind.spec +++ b/bind.spec @@ -68,7 +68,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv Name: bind License: MPLv2.0 Version: 9.11.36 -Release: 8%{?PATCHVER:.%{PATCHVER}}%{?PREVER:.%{PREVER}}%{?dist}.2 +Release: 11%{?PATCHVER:.%{PATCHVER}}%{?PREVER:.%{PREVER}}%{?dist} Epoch: 32 Url: https://www.isc.org/downloads/bind/ # @@ -167,6 +167,14 @@ Patch190: bind-9.11-rh2101712.patch Patch191: bind-9.11-CVE-2022-2795.patch # https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/7376 Patch192: bind-9.11-rh2133889.patch +# https://gitlab.isc.org/isc-projects/bind9/commit/82185f4f80d2fa39a4569f6740cb360ffff8f5c4 +Patch193: bind-9.16-CVE-2022-3094-1.patch +Patch194: bind-9.16-CVE-2022-3094-2.patch +Patch195: bind-9.16-CVE-2022-3094-3.patch +Patch196: bind-9.16-CVE-2022-3094-test.patch +# https://gitlab.isc.org/isc-projects/bind9/commit/f1d9e9ee3859976f403914d20ad2a10855343702 +Patch197: bind-9.11-CVE-2023-2828.patch +Patch198: bind-9.16-CVE-2023-3341.patch # SDB patches Patch11: bind-9.3.2b2-sdbsrc.patch @@ -176,11 +184,6 @@ Patch12: bind-9.10-sdb.patch Patch17: bind-9.3.2b1-fix_sdb_ldap.patch Patch18: bind-9.11-zone2ldap.patch -# https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/8059 -Patch1000: Improve-RBT-overmem-cache-cleaning.patch -# https://downloads.isc.org/isc/bind9/9.16.44/patches/0001-CVE-2023-3341.patch -Patch1001: bind-9.11-CVE-2023-3341.patch - Requires(post): systemd Requires(preun): systemd Requires(postun): systemd @@ -574,6 +577,12 @@ are used for building ISC DHCP. %patch190 -p1 -b .rh2101712 %patch191 -p1 -b .CVE-2022-2795 %patch192 -p1 -b .rh2133889 +%patch193 -p1 -b .CVE-2022-3094 +%patch194 -p1 -b .CVE-2022-3094 +%patch195 -p1 -b .CVE-2022-3094 +%patch196 -p1 -b .CVE-2022-3094-test +%patch197 -p1 -b .CVE-2023-2828 +%patch198 -p1 -b .CVE-2023-3341 mkdir lib/dns/tests/testdata/dstrandom cp -a %{SOURCE50} lib/dns/tests/testdata/dstrandom/random.data @@ -630,9 +639,6 @@ cp -fp contrib/sdb/sqlite/zone2sqlite.c bin/sdb_tools %patch133 -p1 -b .rh640538 %patch134 -p1 -b .rh669163 -%patch1000 -p1 -%patch1001 -p1 - # Sparc and s390 arches need to use -fPIE %ifarch sparcv9 sparc64 s390 s390x for i in bin/named{,-sdb}/{,unix}/Makefile.in; do @@ -1629,11 +1635,15 @@ rm -rf ${RPM_BUILD_ROOT} %endif %changelog -* Mon Oct 11 2023 Liu Xiaoyang 32:9.11.36-8.2 -- Fix CVE-2023-3341 +* Tue Sep 19 2023 Petr Menšík - 32:9.11.36-11 +- Prevent exahustion of memory from control channel (CVE-2023-3341) + +* Thu Jun 22 2023 Petr Menšík - 32:9.11.36-10 +- Prevent the cache going over the configured limit (CVE-2023-2828) -* Tue Jul 18 2023 Liwei Ge - 32:9.11.36-8.1 -- fix CVE-2023-2828 +* Wed Feb 08 2023 Petr Menšík - 32:9.11.36-9 +- Prevent flooding with UPDATE requests (CVE-2022-3094) +- include upstream test for that change * Thu Oct 13 2022 Petr Menšík - 32:9.11.36-8 - Correct regression preventing bind-dyndb-ldap build (#2133889) diff --git a/dist b/dist index 9c0e36e..37a6f9c 100644 --- a/dist +++ b/dist @@ -1 +1 @@ -an8 +an8_9 -- Gitee From 0828e2680d74c05265fe6494ada9537a209e6448 Mon Sep 17 00:00:00 2001 From: Liwei Ge Date: Tue, 18 Jul 2023 11:13:21 +0800 Subject: [PATCH 2/3] fix CVE-2023-2828 Signed-off-by: Liwei Ge --- bind.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bind.spec b/bind.spec index b0d0f91..6be7623 100644 --- a/bind.spec +++ b/bind.spec @@ -1,4 +1,4 @@ -# +%define anolis_release .0.1 # Red Hat BIND package .spec file # # vim:expandtab ts=2: @@ -68,7 +68,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv Name: bind License: MPLv2.0 Version: 9.11.36 -Release: 11%{?PATCHVER:.%{PATCHVER}}%{?PREVER:.%{PREVER}}%{?dist} +Release: 11%{?PATCHVER:.%{PATCHVER}}%{?PREVER:.%{PREVER}}%{anolis_release}%{?dist} Epoch: 32 Url: https://www.isc.org/downloads/bind/ # @@ -1635,6 +1635,9 @@ rm -rf ${RPM_BUILD_ROOT} %endif %changelog +* Thu Dec 14 2023 Liwei Ge - 32:9.11.36-11.0.1 +- fix CVE-2023-2828 + * Tue Sep 19 2023 Petr Menšík - 32:9.11.36-11 - Prevent exahustion of memory from control channel (CVE-2023-3341) -- Gitee From d1ba6da31f7a0e011053afc3bed313008a3c594e Mon Sep 17 00:00:00 2001 From: "liu.xiaoyang" Date: Wed, 11 Oct 2023 11:18:08 +0800 Subject: [PATCH 3/3] Fix CVE-2023-3341 --- bind.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/bind.spec b/bind.spec index 6be7623..7471f4d 100644 --- a/bind.spec +++ b/bind.spec @@ -1637,6 +1637,7 @@ rm -rf ${RPM_BUILD_ROOT} %changelog * Thu Dec 14 2023 Liwei Ge - 32:9.11.36-11.0.1 - fix CVE-2023-2828 +- Fix CVE-2023-3341 (Liu Xiaoyang) * Tue Sep 19 2023 Petr Menšík - 32:9.11.36-11 - Prevent exahustion of memory from control channel (CVE-2023-3341) -- Gitee