9b4944
commit f1f00c072138af90ae6da180f260111f09afe7a3
9b4944
Author: Florian Weimer <fweimer@redhat.com>
9b4944
Date:   Wed Oct 14 10:54:39 2020 +0200
9b4944
9b4944
    resolv: Handle transaction ID collisions in parallel queries (bug 26600)
9b4944
    
9b4944
    If the transaction IDs are equal, the old check attributed both
9b4944
    responses to the first query, not recognizing the second response.
9b4944
    This fixes bug 26600.
9b4944
9b4944
[dj: stripped out testsuite parts]
9b4944
9b4944
diff --git a/resolv/res_send.c b/resolv/res_send.c
9b4944
index c9b02cca130bc20d..ac19627634281c2f 100644
9b4944
--- a/resolv/res_send.c
9b4944
+++ b/resolv/res_send.c
9b4944
@@ -1315,15 +1315,6 @@ send_dg(res_state statp,
9b4944
 			*terrno = EMSGSIZE;
9b4944
 			return close_and_return_error (statp, resplen2);
9b4944
 		}
9b4944
-		if ((recvresp1 || hp->id != anhp->id)
9b4944
-		    && (recvresp2 || hp2->id != anhp->id)) {
9b4944
-			/*
9b4944
-			 * response from old query, ignore it.
9b4944
-			 * XXX - potential security hazard could
9b4944
-			 *	 be detected here.
9b4944
-			 */
9b4944
-			goto wait;
9b4944
-		}
9b4944
 
9b4944
 		/* Paranoia check.  Due to the connected UDP socket,
9b4944
 		   the kernel has already filtered invalid addresses
9b4944
@@ -1333,15 +1324,24 @@ send_dg(res_state statp,
9b4944
 
9b4944
 		/* Check for the correct header layout and a matching
9b4944
 		   question.  */
9b4944
-		if ((recvresp1 || !res_queriesmatch(buf, buf + buflen,
9b4944
-						       *thisansp,
9b4944
-						       *thisansp
9b4944
-						       + *thisanssizp))
9b4944
-		    && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
9b4944
-						       *thisansp,
9b4944
-						       *thisansp
9b4944
-						       + *thisanssizp)))
9b4944
-		  goto wait;
9b4944
+		int matching_query = 0; /* Default to no matching query.  */
9b4944
+		if (!recvresp1
9b4944
+		    && anhp->id == hp->id
9b4944
+		    && res_queriesmatch (buf, buf + buflen,
9b4944
+					 *thisansp, *thisansp + *thisanssizp))
9b4944
+		  matching_query = 1;
9b4944
+		if (!recvresp2
9b4944
+		    && anhp->id == hp2->id
9b4944
+		    && res_queriesmatch (buf2, buf2 + buflen2,
9b4944
+					 *thisansp, *thisansp + *thisanssizp))
9b4944
+		  matching_query = 2;
9b4944
+		if (matching_query == 0)
9b4944
+		  /* Spurious UDP packet.  Drop it and continue
9b4944
+		     waiting.  */
9b4944
+		  {
9b4944
+		    need_recompute = 1;
9b4944
+		    goto wait;
9b4944
+		  }
9b4944
 
9b4944
 		if (anhp->rcode == SERVFAIL ||
9b4944
 		    anhp->rcode == NOTIMP ||
9b4944
@@ -1356,7 +1356,7 @@ send_dg(res_state statp,
9b4944
 			    /* No data from the first reply.  */
9b4944
 			    resplen = 0;
9b4944
 			    /* We are waiting for a possible second reply.  */
9b4944
-			    if (hp->id == anhp->id)
9b4944
+			    if (matching_query == 1)
9b4944
 			      recvresp1 = 1;
9b4944
 			    else
9b4944
 			      recvresp2 = 1;
9b4944
@@ -1387,7 +1387,7 @@ send_dg(res_state statp,
9b4944
 			return (1);
9b4944
 		}
9b4944
 		/* Mark which reply we received.  */
9b4944
-		if (recvresp1 == 0 && hp->id == anhp->id)
9b4944
+		if (matching_query == 1)
9b4944
 			recvresp1 = 1;
9b4944
 		else
9b4944
 			recvresp2 = 1;