From: W.C.A. Wijngaards Date: Wed, 3 Jun 2026 10:14:30 +0000 (+0200) Subject: - Fix that the processing of class responses does not have X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7f4beb846e691d022c3e3defe8cfac405a07d3c2;p=thirdparty%2Funbound.git - Fix that the processing of class responses does not have a heap use-after-free. That could happen if at least two distinct classes are configured for resolution. Thanks to Qifan Zhang, Palo Alto Networks for the report. In addition, thanks to Xin Wang, Jiapeng Li, and Jiajia Liu, Northwestern Polytechnical University, for also reporting this. --- diff --git a/doc/Changelog b/doc/Changelog index 0cf9f7b4a..25fd8266c 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,12 @@ +3 June 2026: Wouter + - Fix that the processing of class responses does not have + a heap use-after-free. That could happen if at least two + distinct classes are configured for resolution. Thanks + to Qifan Zhang, Palo Alto Networks for the report. + In addition, thanks to Xin Wang, Jiapeng Li, and Jiajia + Liu, Northwestern Polytechnical University, for also + reporting this. + 29 May 2026: Wouter - Fix header_seen detection for trust anchor files, so that it detects the id line. diff --git a/iterator/iterator.c b/iterator/iterator.c index 25b4401bf..723590955 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -3990,7 +3990,7 @@ processClassResponse(struct module_qstate* qstate, int id, /* if there are records, copy RCODE */ /* lower sec_state if this message is lower */ if(from->rep->rrset_count != 0) { - size_t n = from->rep->rrset_count+to->rep->rrset_count; + size_t i, n = from->rep->rrset_count+to->rep->rrset_count; struct ub_packed_rrset_key** dest, **d; /* copy appropriate rcode */ to->rep->flags = from->rep->flags; @@ -4012,24 +4012,49 @@ processClassResponse(struct module_qstate* qstate, int id, memcpy(dest, to->rep->rrsets, to->rep->an_numrrsets * sizeof(dest[0])); dest += to->rep->an_numrrsets; - memcpy(dest, from->rep->rrsets, from->rep->an_numrrsets - * sizeof(dest[0])); + for(i=0; irep->an_numrrsets; i++) { + dest[i] = packed_rrset_copy_region( + from->rep->rrsets[i], forq->region, 0); + if(!dest[i]) { + log_err("malloc failed in collect ANY"); + foriq->state = FINISHED_STATE; + return; + } + } dest += from->rep->an_numrrsets; /* copy NS */ memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets, to->rep->ns_numrrsets * sizeof(dest[0])); dest += to->rep->ns_numrrsets; - memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets, - from->rep->ns_numrrsets * sizeof(dest[0])); + for(i=0; irep->ns_numrrsets; i++) { + dest[i] = packed_rrset_copy_region( + from->rep->rrsets[ + from->rep->an_numrrsets+i], + forq->region, 0); + if(!dest[i]) { + log_err("malloc failed in collect ANY"); + foriq->state = FINISHED_STATE; + return; + } + } dest += from->rep->ns_numrrsets; /* copy AR */ memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets+ to->rep->ns_numrrsets, to->rep->ar_numrrsets * sizeof(dest[0])); dest += to->rep->ar_numrrsets; - memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets+ - from->rep->ns_numrrsets, - from->rep->ar_numrrsets * sizeof(dest[0])); + for(i=0; irep->ar_numrrsets; i++) { + dest[i] = packed_rrset_copy_region( + from->rep->rrsets[ + from->rep->an_numrrsets+ + from->rep->ns_numrrsets+i], + forq->region, 0); + if(!dest[i]) { + log_err("malloc failed in collect ANY"); + foriq->state = FINISHED_STATE; + return; + } + } /* update counts */ to->rep->rrsets = d; to->rep->an_numrrsets += from->rep->an_numrrsets; diff --git a/testdata/iter_class_any_merge.rpl b/testdata/iter_class_any_merge.rpl new file mode 100644 index 000000000..19ad5d2bc --- /dev/null +++ b/testdata/iter_class_any_merge.rpl @@ -0,0 +1,195 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: "no" + fake-sha1: yes + trust-anchor-signaling: no + minimal-responses: no + iter-scrub-promiscuous: no + root-hints: +TEMPFILE_NAME class_in.hints +TEMPFILE_CONTENTS class_in.hints +; hints for dns CLASS IN +. 3600 NS k.root-servers.net. +k.root-servers.net. 3600 IN A 193.0.14.129 +TEMPFILE_END + + root-hints: +TEMPFILE_NAME class_ch.hints +TEMPFILE_CONTENTS class_ch.hints +; hints for dns CLASS CH +. 3600 CH NS ns.ch.test. +ns.ch.test. 3600 CH A 1.2.3.5 +TEMPFILE_END + +CONFIG_END + +SCENARIO_BEGIN Test lookup of class any responses from several classes. +; It merges the responses. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.ch.test. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. CH NS +SECTION ANSWER +. CH NS ns.ch.test. +SECTION ADDITIONAL +ns.ch.test. CH A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. CH A +SECTION ANSWER +www.example.com. CH A 3.4.5.6 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. ANY A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. ANY A +SECTION ANSWER +www.example.com. CH A 3.4.5.6 +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END