From 69fb85d9946b71297978135bee24db7bb99ade5f Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Tue, 31 Mar 2026 13:00:00 +0000 Subject: [PATCH] Apply XFR-out quota after ACL is checked Unauthorized clients can consume XFR-out quota and block authorized XFR clients. Apply the quota after ACL is checked. (cherry picked from commit 5615e6c47a2cd00d82d48b568cc55a4b89daa330) --- lib/ns/xfrout.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/ns/xfrout.c b/lib/ns/xfrout.c index 71085df787..9772767b00 100644 --- a/lib/ns/xfrout.c +++ b/lib/ns/xfrout.c @@ -744,6 +744,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { bool is_poll = false; bool is_dlz = false; bool is_ixfr = false; + bool is_quota_applied = false; bool useviewacl = false; uint32_t begin_serial = 0, current_serial; @@ -760,16 +761,6 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(6), "%s request", mnemonic); - /* - * Apply quota. - */ - result = isc_quota_acquire(&client->manager->sctx->xfroutquota); - if (result != ISC_R_SUCCESS) { - isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, - "%s request denied: %s", mnemonic, - isc_result_totext(result)); - goto max_quota; - } /* * Interpret the question section. @@ -940,6 +931,19 @@ got_soa: FAILC(DNS_R_FORMERR, "attempted AXFR over UDP"); } + /* + * Apply quota after ACL is checked, so that unauthorized clients + * can not starve the authorized clients. + */ + result = isc_quota_acquire(&client->manager->sctx->xfroutquota); + if (result != ISC_R_SUCCESS) { + isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, + "%s request denied: %s", mnemonic, + isc_result_totext(result)); + goto cleanup; + } + is_quota_applied = true; + /* * Look up the requesting server in the peer table. */ @@ -1078,7 +1082,7 @@ have_stream: CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf)); /* * Create the xfrout context object. This transfers the ownership - * of "stream", "db", "ver", and "quota" to the xfrout context object. + * of "stream", "db" and "ver" to the xfrout context object. */ if (is_dlz) { @@ -1193,10 +1197,13 @@ cleanup: } if (xfr != NULL) { + /* The quota will be released in xfrout_ctx_destroy(). */ + INSIST(is_quota_applied); xfrout_fail(xfr, result, "setting up zone transfer"); } else if (result != ISC_R_SUCCESS) { - isc_quota_release(&client->manager->sctx->xfroutquota); - max_quota: + if (is_quota_applied) { + isc_quota_release(&client->manager->sctx->xfroutquota); + } ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3), "zone transfer setup failed");