]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a crash in dig NS search mode
authorAram Sargsyan <aram@isc.org>
Thu, 19 May 2022 20:44:32 +0000 (20:44 +0000)
committerAram Sargsyan <aram@isc.org>
Tue, 14 Jun 2022 13:20:25 +0000 (13:20 +0000)
In special NS search mode, after the initial lookup, dig starts the
followup lookup with discovered NS servers in the queries list. If one
of those queries then fail, dig, as usual, tries to start the next query
in the list, which results in a crash, because the NS search mode is
special in a way that the queries are running in parallel, so the next
query is usually already started.

Apply some special logic in `recv_done()` function to deal with the
described situation when handling the query result for the NS search
mode. Particularly, print a warning message for the failed query,
and do not try to start the next query in the list. Also, set a non-zero
exit code if all the queries in the followup lookup fail.

bin/dig/dighost.c
bin/dig/dighost.h

index 40d004c1ef5f833ea446edb1837a06712a05cebf..9b5e1c730982f7553315a3942011837ee02aea29 100644 (file)
@@ -3879,6 +3879,51 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
                goto next_lookup;
        }
 
+       /*
+        * NSSEARCH mode is special, because the queries in the followup lookup
+        * are independent and they are being started in parallel, so if one of
+        * them fails there is no need to start the next query in the lookup,
+        * and this failure can be treated as a soft error (with a warning
+        * message), because there are usually more than one NS servers in the
+        * lookup's queries list. However, if there was not a single successful
+        * query in the followup lookup, then print an error message and exit
+        * with a non-zero exit code.
+        */
+       if (l->ns_search_only && !l->trace_root) {
+               if (eresult == ISC_R_SUCCESS) {
+                       l->ns_search_success = true;
+               } else {
+                       char sockstr[ISC_SOCKADDR_FORMATSIZE];
+                       isc_sockaddr_format(&query->sockaddr, sockstr,
+                                           sizeof(sockstr));
+
+                       dighost_warning("communications error to %s: %s",
+                                       sockstr, isc_result_totext(eresult));
+
+                       /*
+                        * If this is not the last query, then we detach the
+                        * query, but keep the lookup running.
+                        */
+                       if (!check_if_queries_done(l, query)) {
+                               goto detach_query;
+                       }
+
+                       /*
+                        * This is the last query, and if there was not a
+                        * single successful query in the whole lookup, then
+                        * treat the situation as an error.
+                        */
+                       if (!l->ns_search_success) {
+                               dighost_error("no NS servers could be reached");
+                               if (exitcode < 9) {
+                                       exitcode = 9;
+                               }
+                       }
+
+                       goto cancel_lookup;
+               }
+       }
+
        if (eresult == ISC_R_TIMEDOUT) {
                if (l->retries > 1 && !l->tcp_mode) {
                        dig_query_t *newq = NULL;
index d79cc6fc1a6567bf2d30c853701fce5007490d43..d7246333e09189eb728caf9e0e4b7bf25be7943a 100644 (file)
@@ -114,8 +114,8 @@ struct dig_lookup {
                idnin, idnout, ignore, multiline, need_search, new_search,
                noclass, nocrypto, nottl, ns_search_only, /*%< dig +nssearch,
                                                             host -C */
-               nsid,            /*% Name Server ID (RFC 5001) */
-               onesoa, pending, /*%< Pending a successful answer */
+               ns_search_success, nsid, /*% Name Server ID (RFC 5001) */
+               onesoa, pending,         /*%< Pending a successful answer */
                print_unknown_format, qr, raflag, recurse, section_additional,
                section_answer, section_authority, section_question,
                seenbadcookie, sendcookie, servfail_stops,