prevent a reference leak from the ns_query_done hooks

if the NS_QUERY_DONE_BEGIN or NS_QUERY_DONE_SEND hook is
used in a plugin and returns NS_HOOK_RETURN, some of the
cleanup in ns_query_done() can be skipped over, leading
to reference leaks that can cause named to hang on shut
down.

this has been addressed by adding more housekeeping
code after the cleanup: tag in ns_query_done().

(cherry picked from commit c2e4358267)
This commit is contained in:
Evan Hunt
2025-02-26 00:55:51 +00:00
parent 455080866c
commit 4f1f958d6d
2 changed files with 18 additions and 4 deletions
+1
View File
@@ -212,6 +212,7 @@ struct query_ctx {
ns_client_t *client; /* client object */
bool detach_client; /* client needs detaching */
bool async; /* asynchronous hook running */
dns_fetchresponse_t *fresp; /* recursion response */
+17 -4
View File
@@ -5480,6 +5480,9 @@ qctx_clean(query_ctx_t *qctx) {
if (qctx->db != NULL && qctx->node != NULL) {
dns_db_detachnode(qctx->db, &qctx->node);
}
if (qctx->client != NULL && qctx->client->query.gluedb != NULL) {
dns_db_detach(&qctx->client->query.gluedb);
}
}
/*%
@@ -6978,6 +6981,9 @@ ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync,
goto cleanup_and_detach_from_quota;
}
/* Record that an asynchronous copy of the qctx has been started */
qctx->async = true;
/*
* Typically the runasync() function will trigger recursion, but
* there is no need to set NS_QUERYATTR_RECURSING. The calling hook
@@ -11678,10 +11684,6 @@ ns_query_done(query_ctx_t *qctx) {
qctx_clean(qctx);
qctx_freedata(qctx);
if (qctx->client->query.gluedb != NULL) {
dns_db_detach(&qctx->client->query.gluedb);
}
/*
* Clear the AA bit if we're not authoritative.
*/
@@ -11820,6 +11822,17 @@ ns_query_done(query_ctx_t *qctx) {
return qctx->result;
cleanup:
/*
* We'd only get here if one of the hooks above
* (NS_QUERY_DONE_BEGIN or NS_QUERY_DONE_SEND) returned
* NS_HOOK_RETURN. Some housekeeping may be needed.
*/
qctx_clean(qctx);
qctx_freedata(qctx);
if (!qctx->async) {
qctx->detach_client = true;
query_error(qctx->client, DNS_R_SERVFAIL, __LINE__);
}
return result;
}