]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
fix another message parsing regression
authorEvan Hunt <each@isc.org>
Mon, 29 Jan 2024 20:26:00 +0000 (12:26 -0800)
committerMichał Kępień <michal@isc.org>
Thu, 22 Feb 2024 11:00:47 +0000 (12:00 +0100)
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)

lib/dns/message.c

index e5ad60bc5585a66a42e400e115d4f4ba232c7d8e..391fef837a618e3d894e785c216bafec6f366a3f 100644 (file)
@@ -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);
        }