File bind-CVE-2021-25215.patch of Package bind.20643

Index: bind-9.16.6/lib/ns/query.c
===================================================================
--- bind-9.16.6.orig/lib/ns/query.c
+++ bind-9.16.6/lib/ns/query.c
@@ -132,6 +132,9 @@
 
 #define REDIRECT(c) (((c)->query.attributes & NS_QUERYATTR_REDIRECT) != 0)
 
+/*% Was the query already answered due to stale-answer-client-timeout? */
+#define QUERY_ANSWERED(q) (((q)->attributes & NS_QUERYATTR_ANSWERED) != 0)
+
 /*% Does the rdataset 'r' have an attached 'No QNAME Proof'? */
 #define NOQNAME(r) (((r)->attributes & DNS_RDATASETATTR_NOQNAME) != 0)
 
@@ -7430,10 +7433,17 @@ query_respond(query_ctx_t *qctx) {
 	query_addnoqnameproof(qctx);
 
 	/*
-	 * We shouldn't ever fail to add 'rdataset'
-	 * because it's already in the answer.
+	 * 'qctx->rdataset' will only be non-NULL here if the ANSWER section of
+	 * the message to be sent to the client already contains an RRset with
+	 * the same owner name and the same type as 'qctx->rdataset'.  This
+	 * should never happen, with one exception: when chasing DNAME records,
+	 * one of the DNAME records placed in the ANSWER section may turn out
+	 * to be the final answer to the client's query, but we have no way of
+	 * knowing that until now.  In such a case, 'qctx->rdataset' will be
+	 * freed later, so we do not need to free it here.
 	 */
-	INSIST(qctx->rdataset == NULL);
+	INSIST(qctx->rdataset == NULL || qctx->qtype == dns_rdatatype_dname ||
+	       QUERY_ANSWERED(&qctx->client->query));
 
 	query_addauth(qctx);
 
Index: bind-9.16.6/lib/ns/client.c
===================================================================
--- bind-9.16.6.orig/lib/ns/client.c
+++ bind-9.16.6/lib/ns/client.c
@@ -410,6 +410,11 @@ ns_client_send(ns_client_t *client) {
 	 */
 
 	REQUIRE(NS_CLIENT_VALID(client));
+
+	if ((client->query.attributes & NS_QUERYATTR_ANSWERED) != 0) {
+		return;
+	}
+
 	/*
 	 * We need to do it to make sure the client and handle
 	 * won't disappear from under us with client_senddone.
@@ -670,6 +675,7 @@ renderend:
 	}
 
 	if (result == ISC_R_SUCCESS) {
+		client->query.attributes |= NS_QUERYATTR_ANSWERED;
 		return;
 	}
 
@@ -2316,6 +2322,7 @@ ns__client_setup(ns_client_t *client, ns
 					 .query = query };
 	}
 
+	client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
 	client->state = NS_CLIENTSTATE_INACTIVE;
 	client->udpsize = 512;
 	client->ednsversion = -1;
Index: bind-9.16.6/lib/ns/include/ns/query.h
===================================================================
--- bind-9.16.6.orig/lib/ns/include/ns/query.h
+++ bind-9.16.6/lib/ns/include/ns/query.h
@@ -115,6 +115,7 @@ struct ns_query {
 #define NS_QUERYATTR_DNS64EXCLUDE    0x08000
 #define NS_QUERYATTR_RRL_CHECKED     0x10000
 #define NS_QUERYATTR_REDIRECT	     0x20000
+#define NS_QUERYATTR_ANSWERED        0x40000
 
 typedef struct query_ctx query_ctx_t;
 
openSUSE Build Service is sponsored by