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