summaryrefslogtreecommitdiff
path: root/bind-9.16-CVE-2022-3094-1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bind-9.16-CVE-2022-3094-1.patch')
-rw-r--r--bind-9.16-CVE-2022-3094-1.patch241
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=&quot;3.11&quot;]">
++ <!-- 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=&quot;3.11.1&quot;]">
+ <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=&quot;3.11&quot;]\">\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=&quot;3.11.1&quot;]\">\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
+