]> 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>
Wed, 31 Jan 2024 15:04:59 +0000 (16:04 +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 af8ac3d881ecffbd477537f10bf7e1f14da9062c..22aa552f3f61f2125899ad3a16ad666689c0d666 100644 (file)
@@ -1299,6 +1299,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
                isedns = false;
                issigzero = false;
                istsig = false;
+               found_rdataset = NULL;
 
                name = NULL;
                result = dns_message_gettempname(msg, &name);
@@ -1446,10 +1447,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
                 * Then put the meta-class back into the finished rdata.
                 */
                rdata = newrdata(msg);
-               if (rdata == NULL) {
-                       result = ISC_R_NOMEMORY;
-                       goto cleanup;
-               }
                if (msg->opcode == dns_opcode_update &&
                    update(sectionid, rdclass))
                {
@@ -1608,7 +1605,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);
                        }
 
@@ -1656,18 +1652,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);
                                isc_mempool_put(msg->rdspool, rdataset);
-                               rdataset = found_rdataset;
-
                                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);
@@ -1712,7 +1707,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);
@@ -1723,7 +1717,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;
@@ -1733,9 +1726,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) {
@@ -1744,8 +1737,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
                        free_name = false;
                }
                INSIST(!free_name);
-
-               rdataset = NULL;
        }
 
        /*
@@ -1767,6 +1758,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);
        }