bind/backport-0031-Fix-dig-nssearch-race-between-recv_done-and-send_don.patch
2023-01-09 16:44:23 +08:00

78 lines
2.6 KiB
Diff

From 1f2d2611ee23f0b9200dbea8a7b65fa9f3b86e3f Mon Sep 17 00:00:00 2001
From: Aram Sargsyan <aram@isc.org>
Date: Tue, 12 Apr 2022 13:00:45 +0000
Subject: [PATCH] Fix dig +nssearch race between recv_done() and send_done()
The `send_done()` callback needs to access query's `link.next` pointer
when running in `+nssearch` mode, even if the query is already canceled
or serviced, which can happen when `recv_done()` happens to be called
earlier than `send_done()`.
Keep the next query's pointer before unlinking the query from the
lookup's queries list in `clear_query()` so that `send_done()` can
use it even if the query is cleared.
Conflict: NA
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/1f2d2611ee23f0b9200dbea8a7b65fa9f3b86e3f
---
bin/dig/dighost.c | 8 ++++++--
bin/dig/include/dig/dig.h | 1 +
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 27af3c80f1..e0ba9c2aae 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -1591,6 +1591,7 @@ clear_query(dig_query_t *query) {
}
if (ISC_LINK_LINKED(query, link)) {
+ query->saved_next = ISC_LIST_NEXT(query, link);
ISC_LIST_UNLINK(lookup->q, query, link);
}
if (ISC_LINK_LINKED(query, clink)) {
@@ -1609,6 +1610,7 @@ clear_query(dig_query_t *query) {
isc_buffer_invalidate(&query->lengthbuf);
if (query->waiting_senddone) {
+ debug("waiting senddone, delay freeing query");
query->pending_free = true;
} else {
query->magic = 0;
@@ -2583,6 +2585,7 @@ setup_lookup(dig_lookup_t *lookup) {
ISC_LINK_INIT(query, clink);
ISC_LINK_INIT(query, link);
+ query->saved_next = NULL;
query->magic = DIG_QUERY_MAGIC;
@@ -2617,10 +2620,11 @@ send_done(isc_task_t *_task, isc_event_t *event) {
query->waiting_senddone = false;
l = query->lookup;
- if (!query->pending_free && l->ns_search_only && !l->trace_root &&
+ if (l == current_lookup && l->ns_search_only && !l->trace_root &&
!l->tcp_mode) {
debug("sending next, since searching");
- next = ISC_LIST_NEXT(query, link);
+ next = query->pending_free ? query->saved_next
+ : ISC_LIST_NEXT(query, link);
if (next != NULL) {
send_udp(next);
}
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
index 79a868d1ef..9683e39892 100644
--- a/bin/dig/include/dig/dig.h
+++ b/bin/dig/include/dig/dig.h
@@ -183,6 +183,7 @@ struct dig_query {
isc_socket_t *sock;
ISC_LINK(dig_query_t) link;
ISC_LINK(dig_query_t) clink;
+ dig_query_t *saved_next;
isc_sockaddr_t sockaddr;
isc_time_t time_sent;
isc_time_t time_recv;
--
2.23.0