Blame SOURCES/bind-9.16-CVE-2022-3094-1.patch

7a7026
From 18036bb3f435eaa20d60093738c61e5da42a6cfe Mon Sep 17 00:00:00 2001
7a7026
From: Evan Hunt <each@isc.org>
7a7026
Date: Thu, 1 Sep 2022 16:05:04 -0700
7a7026
Subject: [PATCH] add an update quota
7a7026
7a7026
limit the number of simultaneous DNS UPDATE events that can be
7a7026
processed by adding a quota for update and update forwarding.
7a7026
this quota currently, arbitrarily, defaults to 100.
7a7026
7a7026
also add a statistics counter to record when the update quota
7a7026
has been exceeded.
7a7026
7a7026
(cherry picked from commit 7c47254a140c3e9cf383cda73c7b6a55c4782826)
7a7026
---
7a7026
 bin/named/bind9.xsl        |  4 +++-
7a7026
 bin/named/bind9.xsl.h      |  6 +++++-
7a7026
 bin/named/statschannel.c   |  5 +++--
7a7026
 doc/arm/reference.rst      |  5 +++++
7a7026
 lib/ns/include/ns/server.h |  1 +
7a7026
 lib/ns/include/ns/stats.h  |  4 +++-
7a7026
 lib/ns/server.c            |  2 ++
7a7026
 lib/ns/update.c            | 37 ++++++++++++++++++++++++++++++++++++-
7a7026
 8 files changed, 58 insertions(+), 6 deletions(-)
7a7026
7a7026
diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl
7a7026
index 5078115..194625b 100644
7a7026
--- a/bin/named/bind9.xsl
7a7026
+++ b/bin/named/bind9.xsl
7a7026
@@ -12,7 +12,9 @@
7a7026
 
7a7026
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0">
7a7026
   <xsl:output method="html" indent="yes" version="4.0"/>
7a7026
-  <xsl:template match="statistics[@version="3.11"]">
7a7026
+  
7a7026
+  
7a7026
+  <xsl:template match="statistics[@version="3.11.1"]">
7a7026
     <html>
7a7026
       <head>
7a7026
         <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
7a7026
diff --git a/bin/named/bind9.xsl.h b/bin/named/bind9.xsl.h
7a7026
index e30f7f5..b182742 100644
7a7026
--- a/bin/named/bind9.xsl.h
7a7026
+++ b/bin/named/bind9.xsl.h
7a7026
@@ -20,7 +20,11 @@ static char xslmsg[] =
7a7026
 	"
7a7026
 	"xmlns=\"http://www.w3.org/1999/xhtml\" version=\"1.0\">\n"
7a7026
 	" <xsl:output method=\"html\" indent=\"yes\" version=\"4.0\"/>\n"
7a7026
-	" <xsl:template match=\"statistics[@version="3.11"]\">\n"
7a7026
+	" 
7a7026
+	"bin/named/statschannel.c -->\n"
7a7026
+	" 
7a7026
+	"the HTTP endpoints listed below -->\n"
7a7026
+	" <xsl:template match=\"statistics[@version="3.11.1"]\">\n"
7a7026
 	" <html>\n"
7a7026
 	" <head>\n"
7a7026
 	" 
7a7026
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
7a7026
index 832ce93..7361ead 100644
7a7026
--- a/bin/named/statschannel.c
7a7026
+++ b/bin/named/statschannel.c
7a7026
@@ -335,6 +335,7 @@ init_desc(void) {
7a7026
 	SET_NSSTATDESC(reclimitdropped,
7a7026
 		       "queries dropped due to recursive client limit",
7a7026
 		       "RecLimitDropped");
7a7026
+	SET_NSSTATDESC(updatequota, "Update quota exceeded", "UpdateQuota");
7a7026
 
7a7026
 	INSIST(i == ns_statscounter_max);
7a7026
 
7a7026
@@ -2007,7 +2008,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
7a7026
 					      "href=\"/bind9.xsl\""));
7a7026
 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
7a7026
 	TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
7a7026
-					 ISC_XMLCHAR "3.11"));
7a7026
+					 ISC_XMLCHAR "3.11.1"));
7a7026
 
7a7026
 	/* Set common fields for statistics dump */
7a7026
 	dumparg.type = isc_statsformat_xml;
7a7026
@@ -2876,7 +2877,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
7a7026
 	/*
7a7026
 	 * These statistics are included no matter which URL we use.
7a7026
 	 */
7a7026
-	obj = json_object_new_string("1.5");
7a7026
+	obj = json_object_new_string("1.5.1");
7a7026
 	CHECKMEM(obj);
7a7026
 	json_object_object_add(bindstats, "json-stats-version", obj);
7a7026
 
7a7026
diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst
7a7026
index 2d05aec..25c20d7 100644
7a7026
--- a/doc/arm/reference.rst
7a7026
+++ b/doc/arm/reference.rst
7a7026
@@ -6705,6 +6705,11 @@ Name Server Statistics Counters
7a7026
 ``UpdateBadPrereq``
7a7026
     This indicates the number of dynamic updates rejected due to a prerequisite failure.
7a7026
 
7a7026
+``UpdateQuota``
7a7026
+    This indicates the number of times a dynamic update or update
7a7026
+    forwarding request was rejected because the number of pending
7a7026
+    requests exceeded the update quota.
7a7026
+
7a7026
 ``RateDropped``
7a7026
     This indicates the number of responses dropped due to rate limits.
7a7026
 
7a7026
diff --git a/lib/ns/include/ns/server.h b/lib/ns/include/ns/server.h
7a7026
index 6a1f345..0abb579 100644
7a7026
--- a/lib/ns/include/ns/server.h
7a7026
+++ b/lib/ns/include/ns/server.h
7a7026
@@ -84,6 +84,7 @@ struct ns_server {
7a7026
 	isc_quota_t recursionquota;
7a7026
 	isc_quota_t tcpquota;
7a7026
 	isc_quota_t xfroutquota;
7a7026
+	isc_quota_t updquota;
7a7026
 
7a7026
 	/*% Test options and other configurables */
7a7026
 	uint32_t options;
7a7026
diff --git a/lib/ns/include/ns/stats.h b/lib/ns/include/ns/stats.h
7a7026
index 3c08799..95b15d0 100644
7a7026
--- a/lib/ns/include/ns/stats.h
7a7026
+++ b/lib/ns/include/ns/stats.h
7a7026
@@ -106,7 +106,9 @@ enum {
7a7026
 
7a7026
 	ns_statscounter_reclimitdropped = 66,
7a7026
 
7a7026
-	ns_statscounter_max = 67,
7a7026
+	ns_statscounter_updatequota = 67,
7a7026
+
7a7026
+	ns_statscounter_max = 68,
7a7026
 };
7a7026
 
7a7026
 void
7a7026
diff --git a/lib/ns/server.c b/lib/ns/server.c
7a7026
index a970a28..540bc2e 100644
7a7026
--- a/lib/ns/server.c
7a7026
+++ b/lib/ns/server.c
7a7026
@@ -52,6 +52,7 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
7a7026
 	isc_quota_init(&sctx->xfroutquota, 10);
7a7026
 	isc_quota_init(&sctx->tcpquota, 10);
7a7026
 	isc_quota_init(&sctx->recursionquota, 100);
7a7026
+	isc_quota_init(&sctx->updquota, 100);
7a7026
 
7a7026
 	CHECKFATAL(dns_tkeyctx_create(mctx, &sctx->tkeyctx));
7a7026
 
7a7026
@@ -131,6 +132,7 @@ ns_server_detach(ns_server_t **sctxp) {
7a7026
 			isc_mem_put(sctx->mctx, altsecret, sizeof(*altsecret));
7a7026
 		}
7a7026
 
7a7026
+		isc_quota_destroy(&sctx->updquota);
7a7026
 		isc_quota_destroy(&sctx->recursionquota);
7a7026
 		isc_quota_destroy(&sctx->tcpquota);
7a7026
 		isc_quota_destroy(&sctx->xfroutquota);
7a7026
diff --git a/lib/ns/update.c b/lib/ns/update.c
7a7026
index 546b70a..1871438 100644
7a7026
--- a/lib/ns/update.c
7a7026
+++ b/lib/ns/update.c
7a7026
@@ -1544,6 +1544,19 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
7a7026
 	update_event_t *event = NULL;
7a7026
 	isc_task_t *zonetask = NULL;
7a7026
 
7a7026
+	result = isc_quota_attach(&client->manager->sctx->updquota,
7a7026
+				  &(isc_quota_t *){ NULL });
7a7026
+	if (result != ISC_R_SUCCESS) {
7a7026
+		update_log(client, zone, LOGLEVEL_PROTOCOL,
7a7026
+			   "update failed: too many DNS UPDATEs queued (%s)",
7a7026
+			   isc_result_totext(result));
7a7026
+		ns_stats_increment(client->manager->sctx->nsstats,
7a7026
+				   ns_statscounter_updatequota);
7a7026
+		ns_client_drop(client, result);
7a7026
+		isc_nmhandle_detach(&client->reqhandle);
7a7026
+		return (DNS_R_DROP);
7a7026
+	}
7a7026
+
7a7026
 	event = (update_event_t *)isc_event_allocate(
7a7026
 		client->mctx, client, DNS_EVENT_UPDATE, update_action, NULL,
7a7026
 		sizeof(*event));
7a7026
@@ -1676,12 +1689,18 @@ failure:
7a7026
 		       dns_zone_gettype(zone) == dns_zone_mirror);
7a7026
 		inc_stats(client, zone, ns_statscounter_updaterej);
7a7026
 	}
7a7026
+
7a7026
 	/*
7a7026
 	 * We failed without having sent an update event to the zone.
7a7026
 	 * We are still in the client task context, so we can
7a7026
 	 * simply give an error response without switching tasks.
7a7026
 	 */
7a7026
-	respond(client, result);
7a7026
+	if (result == DNS_R_DROP) {
7a7026
+		ns_client_drop(client, result);
7a7026
+	} else {
7a7026
+		respond(client, result);
7a7026
+	}
7a7026
+
7a7026
 	if (zone != NULL) {
7a7026
 		dns_zone_detach(&zone);
7a7026
 	}
7a7026
@@ -3489,6 +3508,7 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
7a7026
 
7a7026
 	respond(client, uev->result);
7a7026
 
7a7026
+	isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
7a7026
 	isc_event_free(&event);
7a7026
 	isc_nmhandle_detach(&client->updatehandle);
7a7026
 }
7a7026
@@ -3505,6 +3525,8 @@ forward_fail(isc_task_t *task, isc_event_t *event) {
7a7026
 	INSIST(client->nupdates > 0);
7a7026
 	client->nupdates--;
7a7026
 	respond(client, DNS_R_SERVFAIL);
7a7026
+
7a7026
+	isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
7a7026
 	isc_event_free(&event);
7a7026
 	isc_nmhandle_detach(&client->updatehandle);
7a7026
 }
7a7026
@@ -3542,6 +3564,8 @@ forward_done(isc_task_t *task, isc_event_t *event) {
7a7026
 	client->nupdates--;
7a7026
 	ns_client_sendraw(client, uev->answer);
7a7026
 	dns_message_detach(&uev->answer);
7a7026
+
7a7026
+	isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
7a7026
 	isc_event_free(&event);
7a7026
 	isc_nmhandle_detach(&client->updatehandle);
7a7026
 }
7a7026
@@ -3576,6 +3600,17 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) {
7a7026
 	update_event_t *event = NULL;
7a7026
 	isc_task_t *zonetask = NULL;
7a7026
 
7a7026
+	result = isc_quota_attach(&client->manager->sctx->updquota,
7a7026
+				  &(isc_quota_t *){ NULL });
7a7026
+	if (result != ISC_R_SUCCESS) {
7a7026
+		update_log(client, zone, LOGLEVEL_PROTOCOL,
7a7026
+			   "update failed: too many DNS UPDATEs queued (%s)",
7a7026
+			   isc_result_totext(result));
7a7026
+		ns_stats_increment(client->manager->sctx->nsstats,
7a7026
+				   ns_statscounter_updatequota);
7a7026
+		return (DNS_R_DROP);
7a7026
+	}
7a7026
+
7a7026
 	event = (update_event_t *)isc_event_allocate(
7a7026
 		client->mctx, client, DNS_EVENT_UPDATE, forward_action, NULL,
7a7026
 		sizeof(*event));
7a7026
-- 
7a7026
2.39.2
7a7026