diff options
Diffstat (limited to 'bind-9.16-CVE-2022-3094-1.patch')
-rw-r--r-- | bind-9.16-CVE-2022-3094-1.patch | 241 |
1 files changed, 241 insertions, 0 deletions
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..53f6629 --- /dev/null +++ b/bind-9.16-CVE-2022-3094-1.patch @@ -0,0 +1,241 @@ +From 0c0dc08d3ef26b7411cfe089e8144454831e8af5 Mon Sep 17 00:00:00 2001 +From: Evan Hunt <each@isc.org> +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 | 4 +++- + bin/named/bind9.xsl.h | 6 +++++- + bin/named/statschannel.c | 5 +++-- + doc/arm/reference.rst | 5 +++++ + lib/ns/include/ns/server.h | 1 + + lib/ns/include/ns/stats.h | 4 +++- + lib/ns/server.c | 2 ++ + lib/ns/update.c | 38 +++++++++++++++++++++++++++++++++++++- + 8 files changed, 59 insertions(+), 6 deletions(-) + +diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl +index 5078115..194625b 100644 +--- a/bin/named/bind9.xsl ++++ b/bin/named/bind9.xsl +@@ -12,7 +12,9 @@ + + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0"> + <xsl:output method="html" indent="yes" version="4.0"/> +- <xsl:template match="statistics[@version="3.11"]"> ++ <!-- the version number **below** must match version in bin/named/statschannel.c --> ++ <!-- don't forget to update "/xml/v<STATS_XML_VERSION_MAJOR>" in the HTTP endpoints listed below --> ++ <xsl:template match="statistics[@version="3.11.1"]"> + <html> + <head> + <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> +diff --git a/bin/named/bind9.xsl.h b/bin/named/bind9.xsl.h +index e30f7f5..b182742 100644 +--- a/bin/named/bind9.xsl.h ++++ b/bin/named/bind9.xsl.h +@@ -20,7 +20,11 @@ static char xslmsg[] = + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" " + "xmlns=\"http://www.w3.org/1999/xhtml\" version=\"1.0\">\n" + " <xsl:output method=\"html\" indent=\"yes\" version=\"4.0\"/>\n" +- " <xsl:template match=\"statistics[@version="3.11"]\">\n" ++ " <!-- the version number **below** must match version in " ++ "bin/named/statschannel.c -->\n" ++ " <!-- don't forget to update \"/xml/v<STATS_XML_VERSION_MAJOR>\" in " ++ "the HTTP endpoints listed below -->\n" ++ " <xsl:template match=\"statistics[@version="3.11.1"]\">\n" + " <html>\n" + " <head>\n" + " <script type=\"text/javascript\" " +diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c +index 832ce93..7361ead 100644 +--- a/bin/named/statschannel.c ++++ b/bin/named/statschannel.c +@@ -335,6 +335,7 @@ init_desc(void) { + SET_NSSTATDESC(reclimitdropped, + "queries dropped due to recursive client limit", + "RecLimitDropped"); ++ SET_NSSTATDESC(updatequota, "Update quota exceeded", "UpdateQuota"); + + INSIST(i == ns_statscounter_max); + +@@ -2007,7 +2008,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen, + "href=\"/bind9.xsl\"")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version", +- ISC_XMLCHAR "3.11")); ++ ISC_XMLCHAR "3.11.1")); + + /* Set common fields for statistics dump */ + dumparg.type = isc_statsformat_xml; +@@ -2876,7 +2877,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg, + /* + * These statistics are included no matter which URL we use. + */ +- obj = json_object_new_string("1.5"); ++ obj = json_object_new_string("1.5.1"); + CHECKMEM(obj); + json_object_object_add(bindstats, "json-stats-version", obj); + +diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst +index 2d05aec..25c20d7 100644 +--- a/doc/arm/reference.rst ++++ b/doc/arm/reference.rst +@@ -6705,6 +6705,11 @@ Name Server Statistics Counters + ``UpdateBadPrereq`` + This indicates the number of dynamic updates rejected due to a prerequisite failure. + ++``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`` + This indicates the number of responses dropped due to rate limits. + +diff --git a/lib/ns/include/ns/server.h b/lib/ns/include/ns/server.h +index 6a1f345..0abb579 100644 +--- a/lib/ns/include/ns/server.h ++++ b/lib/ns/include/ns/server.h +@@ -84,6 +84,7 @@ struct ns_server { + isc_quota_t recursionquota; + isc_quota_t tcpquota; + isc_quota_t xfroutquota; ++ isc_quota_t updquota; + + /*% Test options and other configurables */ + uint32_t options; +diff --git a/lib/ns/include/ns/stats.h b/lib/ns/include/ns/stats.h +index 3c08799..95b15d0 100644 +--- a/lib/ns/include/ns/stats.h ++++ b/lib/ns/include/ns/stats.h +@@ -106,7 +106,9 @@ enum { + + ns_statscounter_reclimitdropped = 66, + +- ns_statscounter_max = 67, ++ ns_statscounter_updatequota = 67, ++ ++ ns_statscounter_max = 68, + }; + + void +diff --git a/lib/ns/server.c b/lib/ns/server.c +index a970a28..540bc2e 100644 +--- a/lib/ns/server.c ++++ b/lib/ns/server.c +@@ -52,6 +52,7 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview, + isc_quota_init(&sctx->xfroutquota, 10); + isc_quota_init(&sctx->tcpquota, 10); + isc_quota_init(&sctx->recursionquota, 100); ++ isc_quota_init(&sctx->updquota, 100); + + CHECKFATAL(dns_tkeyctx_create(mctx, &sctx->tkeyctx)); + +@@ -131,6 +132,7 @@ ns_server_detach(ns_server_t **sctxp) { + isc_mem_put(sctx->mctx, altsecret, sizeof(*altsecret)); + } + ++ isc_quota_destroy(&sctx->updquota); + isc_quota_destroy(&sctx->recursionquota); + isc_quota_destroy(&sctx->tcpquota); + isc_quota_destroy(&sctx->xfroutquota); +diff --git a/lib/ns/update.c b/lib/ns/update.c +index 546b70a..9a8c309 100644 +--- a/lib/ns/update.c ++++ b/lib/ns/update.c +@@ -1544,6 +1544,19 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) { + update_event_t *event = NULL; + isc_task_t *zonetask = NULL; + ++ result = isc_quota_attach(&client->manager->sctx->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)); ++ ns_stats_increment(client->manager->sctx->nsstats, ++ ns_statscounter_updatequota); ++ ns_client_drop(client, result); ++ isc_nmhandle_detach(&client->reqhandle); ++ return (DNS_R_DROP); ++ } ++ + event = (update_event_t *)isc_event_allocate( + client->mctx, client, DNS_EVENT_UPDATE, update_action, NULL, + sizeof(*event)); +@@ -1676,12 +1689,19 @@ failure: + dns_zone_gettype(zone) == dns_zone_mirror); + inc_stats(client, zone, ns_statscounter_updaterej); + } ++ + /* + * We failed without having sent an update event to the zone. + * 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_drop(client, result); ++ isc_nmhandle_detach(&client->reqhandle); ++ } else { ++ respond(client, result); ++ } ++ + if (zone != NULL) { + dns_zone_detach(&zone); + } +@@ -3489,6 +3509,7 @@ updatedone_action(isc_task_t *task, isc_event_t *event) { + + respond(client, uev->result); + ++ isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota }); + isc_event_free(&event); + isc_nmhandle_detach(&client->updatehandle); + } +@@ -3505,6 +3526,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 *){ &client->manager->sctx->updquota }); + isc_event_free(&event); + isc_nmhandle_detach(&client->updatehandle); + } +@@ -3542,6 +3565,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 *){ &client->manager->sctx->updquota }); + isc_event_free(&event); + isc_nmhandle_detach(&client->updatehandle); + } +@@ -3576,6 +3601,17 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) { + update_event_t *event = NULL; + isc_task_t *zonetask = NULL; + ++ result = isc_quota_attach(&client->manager->sctx->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)); ++ ns_stats_increment(client->manager->sctx->nsstats, ++ ns_statscounter_updatequota); ++ return (DNS_R_DROP); ++ } ++ + event = (update_event_t *)isc_event_allocate( + client->mctx, client, DNS_EVENT_UPDATE, forward_action, NULL, + sizeof(*event)); +-- +2.39.1 + |