From: Evan Hunt Date: Mon, 29 Jan 2024 20:26:00 +0000 (-0800) Subject: fix another message parsing regression X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bbbcaf8b2ec17d2cad28841ea86078168072ae2f;p=thirdparty%2Fbind9.git fix another message parsing regression The fix for CVE-2023-4408 introduced a regression in the message parser, which could cause a crash if an rdata type that can only occur in the question was found in another section. (cherry picked from commit 510f1de8a6add516b842a55750366944701d3d9a) --- diff --git a/lib/dns/message.c b/lib/dns/message.c index e5ad60bc558..391fef837a6 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -1354,7 +1354,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_name_t *name2 = NULL; dns_offsets_t *offsets; dns_rdataset_t *rdataset = NULL; - dns_rdataset_t *rdataset2 = NULL; + dns_rdataset_t *found_rdataset = NULL; dns_rdatalist_t *rdatalist; isc_result_t result = ISC_R_SUCCESS; dns_rdatatype_t rdtype, covers; @@ -1387,6 +1387,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, isedns = false; issigzero = false; istsig = false; + found_rdataset = NULL; name = isc_mempool_get(msg->namepool); if (name == NULL) @@ -1679,7 +1680,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * the question section, fail. */ if (dns_rdatatype_questiononly(rdtype)) { - dns_message_puttemprdataset(msg, &rdataset); DO_ERROR(DNS_R_FORMERR); } @@ -1692,9 +1692,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, ISC_HT_CASE_SENSITIVE); free_ht = true; } - rdataset2 = NULL; result = rds_hash_add(name->ht, rdataset, - &rdataset2); + &found_rdataset); /* * If we found an rdataset that matches, we need to @@ -1715,19 +1714,17 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, /* Free the rdataset we used as the key */ dns_rdataset_disassociate(rdataset); dns__message_puttemprdataset(msg, &rdataset); - rdataset = rdataset2; - rdataset2 = NULL; - result = ISC_R_SUCCESS; + rdataset = found_rdataset; if (!dns_rdatatype_issingleton(rdtype)) { break; } - dns_rdata_t *first; dns_rdatalist_fromrdataset(rdataset, &rdatalist); - first = ISC_LIST_HEAD(rdatalist->rdata); + dns_rdata_t *first = + ISC_LIST_HEAD(rdatalist->rdata); INSIST(first != NULL); if (dns_rdata_compare(rdata, first) != 0) { DO_ERROR(DNS_R_FORMERR); @@ -1771,7 +1768,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_rcode_t ercode; msg->opt = rdataset; - rdataset = NULL; ercode = (dns_rcode_t) ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) >> 20); @@ -1782,7 +1778,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, msg->sig0 = rdataset; msg->sig0name = name; msg->sigstart = recstart; - rdataset = NULL; free_name = false; } else if (istsig) { msg->tsig = rdataset; @@ -1792,9 +1787,9 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * Windows doesn't like TSIG names to be compressed. */ msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; - rdataset = NULL; free_name = false; } + rdataset = NULL; if (seen_problem) { if (free_name) @@ -1802,8 +1797,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, free_name = false; } INSIST(free_name == false); - - rdataset = NULL; } /* @@ -1824,6 +1817,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, } cleanup: + if (rdataset != NULL && rdataset != found_rdataset) { + dns_rdataset_disassociate(rdataset); + isc_mempool_put(msg->rdspool, rdataset); + } if (free_name) { dns_message_puttempname(msg, &name); }