2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 23:25:38 +00:00

fix: dev: Fix error path bugs in the manager's "recursing-clients" list management

In two places, after linking the client to the manager's
"recursing-clients" list using the check_recursionquota()
function, the query.c module fails to unlink it on error
paths. Fix the bugs by unlinking the client from the list.

Merge branch 'aram/unlink-recursing-clients-on-error-paths' into 'main'

See merge request isc-projects/bind9!9586
This commit is contained in:
Arаm Sаrgsyаn
2024-10-09 11:38:35 +00:00

View File

@@ -238,6 +238,12 @@ query_addanswer(query_ctx_t *qctx);
static isc_result_t static isc_result_t
query_prepare_delegation_response(query_ctx_t *qctx); query_prepare_delegation_response(query_ctx_t *qctx);
static isc_result_t
acquire_recursionquota(ns_client_t *client);
static void
release_recursionquota(ns_client_t *client);
/* /*
* Return the hooktable in use with 'qctx', or if there isn't one * Return the hooktable in use with 'qctx', or if there isn't one
* set, return the default hooktable. * set, return the default hooktable.
@@ -5996,14 +6002,7 @@ fetch_callback(void *arg) {
* We're done recursing, detach from quota and unlink from * We're done recursing, detach from quota and unlink from
* the manager's recursing-clients list. * the manager's recursing-clients list.
*/ */
release_recursionquota(client);
recursionquotatype_detach(client);
LOCK(&client->manager->reclock);
if (ISC_LINK_LINKED(client, rlink)) {
ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
}
UNLOCK(&client->manager->reclock);
isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client)); isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client));
@@ -6104,6 +6103,7 @@ recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype,
dns_name_copy(qdomain, param->qdomain); dns_name_copy(qdomain, param->qdomain);
} }
} }
static void static void
recursionquota_log(ns_client_t *client, atomic_uint_fast32_t *last_log_time, recursionquota_log(ns_client_t *client, atomic_uint_fast32_t *last_log_time,
const char *format, isc_quota_t *quota) { const char *format, isc_quota_t *quota) {
@@ -6121,10 +6121,10 @@ recursionquota_log(ns_client_t *client, atomic_uint_fast32_t *last_log_time,
static atomic_uint_fast32_t last_soft, last_hard; static atomic_uint_fast32_t last_soft, last_hard;
/*% /*%
* Check recursion quota before making the current client "recursing". * Acquire recursion quota before making the current client "recursing".
*/ */
static isc_result_t static isc_result_t
check_recursionquota(ns_client_t *client) { acquire_recursionquota(ns_client_t *client) {
isc_result_t result; isc_result_t result;
result = recursionquotatype_attach_soft(client); result = recursionquotatype_attach_soft(client);
@@ -6154,6 +6154,20 @@ check_recursionquota(ns_client_t *client) {
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
/*%
* Release recursion quota and remove the client from the "recursing" list.
*/
static void
release_recursionquota(ns_client_t *client) {
recursionquotatype_detach(client);
LOCK(&client->manager->reclock);
if (ISC_LINK_LINKED(client, rlink)) {
ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
}
UNLOCK(&client->manager->reclock);
}
isc_result_t isc_result_t
ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
dns_name_t *qdomain, dns_rdataset_t *nameservers, dns_name_t *qdomain, dns_rdataset_t *nameservers,
@@ -6180,7 +6194,7 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
inc_stats(client, ns_statscounter_recursion); inc_stats(client, ns_statscounter_recursion);
} }
result = check_recursionquota(client); result = acquire_recursionquota(client);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return (result); return (result);
} }
@@ -6214,12 +6228,14 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
0, NULL, client->manager->loop, fetch_callback, client, 0, NULL, client->manager->loop, fetch_callback, client,
rdataset, sigrdataset, &FETCH_RECTYPE_NORMAL(client)); rdataset, sigrdataset, &FETCH_RECTYPE_NORMAL(client));
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client)); release_recursionquota(client);
ns_client_putrdataset(client, &rdataset); ns_client_putrdataset(client, &rdataset);
if (sigrdataset != NULL) { if (sigrdataset != NULL) {
ns_client_putrdataset(client, &sigrdataset); ns_client_putrdataset(client, &sigrdataset);
} }
recursionquotatype_detach(client);
isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client));
} }
/* /*
@@ -6449,13 +6465,7 @@ query_hookresume(void *arg) {
UNLOCK(&client->query.fetchlock); UNLOCK(&client->query.fetchlock);
SAVE(hctx, rev->ctx); SAVE(hctx, rev->ctx);
recursionquotatype_detach(client); release_recursionquota(client);
LOCK(&client->manager->reclock);
if (ISC_LINK_LINKED(client, rlink)) {
ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
}
UNLOCK(&client->manager->reclock);
/* /*
* The fetch handle should be detached before resuming query processing * The fetch handle should be detached before resuming query processing
@@ -6580,7 +6590,7 @@ ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync,
REQUIRE(client->query.hookactx == NULL); REQUIRE(client->query.hookactx == NULL);
REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL); REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL);
result = check_recursionquota(client); result = acquire_recursionquota(client);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto cleanup; goto cleanup;
} }
@@ -6609,7 +6619,7 @@ ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
cleanup_and_detach_from_quota: cleanup_and_detach_from_quota:
recursionquotatype_detach(client); release_recursionquota(client);
cleanup: cleanup:
/* /*
* If we fail, send SERVFAIL now. It may be better to let the caller * If we fail, send SERVFAIL now. It may be better to let the caller