Le 01/09/2026 à 12:44 PM, Manu Nicolas a écrit :
  static int resolv_validate_dns_response(unsigned char *resp, unsigned char 
*bufend,
-                                        struct resolv_resolution *resolution, 
int max_answer_records)
+                                        struct resolv_resolution *resolution, 
int max_answer_records,
+                                        int allow_truncated_srv)
  {
        unsigned char *reader;
        char *previous_dname, tmpname[DNS_MAX_NAME_SIZE];
@@ -1148,10 +1185,20 @@ static int resolv_validate_dns_response(unsigned char 
*resp, unsigned char *bufe
        query->class = reader[0] * 256 + reader[1];
        reader += 2;
+ /* A and AAAA responses may arrive after the query type switched. */
+       if (query->class != DNS_RCLASS_IN ||
+           (query->type != resolution->query_type &&
+            !((query->type == DNS_RTYPE_A || query->type == DNS_RTYPE_AAAA) &&
+              (resolution->query_type == DNS_RTYPE_A ||
+               resolution->query_type == DNS_RTYPE_AAAA))))
+               goto invalid_resp;
+
        /* TRUNCATED flag must be checked after we could read the query type
         * because a TRUNCATED SRV query type response can still be exploited
+        * when TCP fallback is disabled.
         */

Should be updated I guess: these reponses can be exploited when no TCP fallback can be performed (see my next comment).

-       if (query->type != DNS_RTYPE_SRV && flags & DNS_FLAG_TRUNCATED) {
+       if ((flags & DNS_FLAG_TRUNCATED) &&
+           (query->type != DNS_RTYPE_SRV || !allow_truncated_srv)) {
                cause = RSLV_RESP_TRUNCATED;
                goto return_error;
        }
@@ -2377,11 +2424,16 @@ static int resolv_process_responses(struct 
dns_nameserver *ns, enum dns_server_t
/* known query id means a resolution in progress */
                res = eb32_entry(eb, struct resolv_resolution, qid);
+               if (dns_server_type_is_stream(type) &&
+                   dns_nameserver_has_fallback(ns) && res->nb_tcp_fallback)
+                       res->nb_tcp_fallback--;
                /* number of responses received */
                res->nb_responses++;
max_answer_records = (max_payload_size - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE;
-               dns_resp = resolv_validate_dns_response(buf, bufend, res, 
max_answer_records);
+               dns_resp = resolv_validate_dns_response(buf, bufend, res, 
max_answer_records,
+                                                      dns_server_type_is_dgram(type) 
&&
+                                                      
!dns_nameserver_has_fallback(ns));
Here the condition to parse truncated SRV response is not correct. It must be allowed for TCP nameservers and for explicit UPD ones. In fact, it means truncated SRV responses can be parsed when fallback cannot be performed. So:

  !(dns_server_type_is_dgram(type) && dns_nameserver_has_fallback(ns))

Because with your version, truncated SRV responses are no longer parsed for TCP nameservers. It looks like a regression. If I'm right, your reg-test script must be adapted.

Otherwise, all other commits are good and can be merged. I will just wait for this fix (if I'm right) and for the DNS_TCP_MSG_RING_MAX_SIZE renaming, except if you want to handle it in a dedicated patch. Just let me know.


--
Christopher Faulet


Reply via email to