From 7e2f50c36958f8c98d54e6d131f088a4837ce269 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Fri, 1 Apr 2022 13:12:40 +0000 Subject: [PATCH 1/2] Fix dig hanging issue in cases when the lookup's next query can't start In recv_done(), when dig decides to start the lookup's next query in the line using `start_udp()` or `start_tcp()`, and for some reason, no queries get started, dig doesn't cancel the lookup. This can occur, for example, when there are two queries in the lookup, one with a regular IP address, and another with a IPv4 mapped IPv6 address. When the regular IP address fails to serve the query, its `recv_done()` callback starts the next query in the line (in this case the one with a mapped IP address), but because `dig` doesn't connect to such IP addresses, and there are no other queries in the list, no new queries are being started, and the lookup keeps hanging. After calling `start_udp()` or `start_tcp()` in `recv_done()`, check if there are no pending/working queries then cancel the lookup instead of only detaching from the current query. --- bin/dig/dighost.c | 15 +++++++++++++++ bin/tests/system/digdelv/tests.sh | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 6f99f54064..166358b348 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -3881,6 +3881,9 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, l->retries); start_udp(newq); } + if (check_if_queries_done(l, query)) { + goto cancel_lookup; + } goto detach_query; } else if (l->retries > 1 && l->tcp_mode) { @@ -3917,6 +3920,10 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, start_udp(next); } } + if (check_if_queries_done(l, query)) { + goto cancel_lookup; + } + goto detach_query; } @@ -3958,6 +3965,10 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, start_udp(next); } } + if (check_if_queries_done(l, query)) { + goto cancel_lookup; + } + goto detach_query; } @@ -4234,6 +4245,10 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, ? "SERVFAIL reply" : "recursion not available", query->servname); + if (check_if_queries_done(l, query)) { + goto cancel_lookup; + } + goto detach_query; } } diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh index 2e735c66ea..05ee710522 100644 --- a/bin/tests/system/digdelv/tests.sh +++ b/bin/tests/system/digdelv/tests.sh @@ -1071,6 +1071,16 @@ if [ -x "$DIG" ] ; then grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status+ret)) + + # See [GL #3248] for more information + n=$((n+1)) + echo_i "check that dig correctly refuses to use a server with a IPv4 mapped IPv6 address after failing with a regular IP address ($n)" + ret=0 + dig_with_opts @10.53.0.8 @::ffff:10.53.0.8 a.example > dig.out.test$n 2>&1 || ret=1 + grep -F ";; Skipping mapped address" dig.out.test$n > /dev/null || ret=1 + grep -F ";; No acceptable nameservers" dig.out.test$n > /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status+ret)) else echo_i "$DIG is needed, so skipping these dig tests" fi From 438e9b55877435fe3a3507d0a59be6b06d123274 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Fri, 1 Apr 2022 13:39:06 +0000 Subject: [PATCH 2/2] Add CHANGES note for [GL #3248] --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index cf0ef79ef8..b4503afc1a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +5848. [bug] dig could hang in some cases involving multiple servers + in a lookup, when a request fails and the next one + refuses to start for some reason, for example if it was + an IPv4 mapped IPv6 address. [GL #3248] + 5847. [cleanup] Remove task privileged mode in favor of processing all events in the loadzone task in a single run by setting the quantum to UINT_MAX. [GL #3253]