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;