| From 8259daad7242ab2af8731681177ef7e948a15ece Mon Sep 17 00:00:00 2001 |
| From: Mark Andrews <marka@isc.org> |
| Date: Mon, 16 Nov 2015 13:12:20 +1100 |
| Subject: [PATCH] 4260. [security] Insufficient testing when parsing a |
| message allowed records with an incorrect class to be |
| be accepted, triggering a REQUIRE failure when those |
| records were subsequently cached. (CVE-2015-8000) [RT |
| #4098] |
| |
| (cherry picked from commit c8821d124c532e0a65752b378f924d4259499fd3) |
| (cherry picked from commit 3a4c24c4a52d4a2d21d2decbde3d4e514e27d51c) |
| |
| |
| Upstream-Status: Backport |
| |
| https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=8259daad7242ab2af8731681177ef7e948a15ece |
| |
| CVE: CVE-2015-8000 |
| |
| Signed-off-by: Armin Kuster <akuster@mvista.com> |
| |
| --- |
| CHANGES | 5 +++++ |
| bin/tests/system/start.pl | 5 ++++- |
| doc/arm/notes.xml | 9 +++++++++ |
| lib/dns/include/dns/message.h | 13 +++++++++++-- |
| lib/dns/message.c | 45 ++++++++++++++++++++++++++++++++++++++----- |
| lib/dns/resolver.c | 9 +++++++++ |
| lib/dns/xfrin.c | 2 ++ |
| 7 files changed, 80 insertions(+), 8 deletions(-) |
| |
| Index: bind-9.10.2-P4/bin/tests/system/start.pl |
| =================================================================== |
| --- bind-9.10.2-P4.orig/bin/tests/system/start.pl |
| +++ bind-9.10.2-P4/bin/tests/system/start.pl |
| @@ -68,6 +68,7 @@ my $NAMED = $ENV{'NAMED'}; |
| my $LWRESD = $ENV{'LWRESD'}; |
| my $DIG = $ENV{'DIG'}; |
| my $PERL = $ENV{'PERL'}; |
| +my $PYTHON = $ENV{'PYTHON'}; |
| |
| # Start the server(s) |
| |
| @@ -213,7 +214,9 @@ sub start_server { |
| $pid_file = "lwresd.pid"; |
| } elsif ($server =~ /^ans/) { |
| $cleanup_files = "{ans.run}"; |
| - if (-e "$testdir/$server/ans.pl") { |
| + if (-e "$testdir/$server/ans.py") { |
| + $command = "$PYTHON ans.py 10.53.0.$' 5300"; |
| + } elsif (-e "$testdir/$server/ans.pl") { |
| $command = "$PERL ans.pl"; |
| } else { |
| $command = "$PERL $topdir/ans.pl 10.53.0.$'"; |
| Index: bind-9.10.2-P4/doc/arm/notes.xml |
| =================================================================== |
| --- bind-9.10.2-P4.orig/doc/arm/notes.xml |
| +++ bind-9.10.2-P4/doc/arm/notes.xml |
| @@ -62,6 +62,15 @@ |
| <itemizedlist> |
| <listitem> |
| <para> |
| + Insufficient testing when parsing a message allowed |
| + records with an incorrect class to be be accepted, |
| + triggering a REQUIRE failure when those records |
| + were subsequently cached. This flaw is disclosed |
| + in CVE-2015-8000. [RT #4098] |
| + </para> |
| + </listitem> |
| + <listitem> |
| + <para> |
| An incorrect boundary check in the OPENPGPKEY rdatatype |
| could trigger an assertion failure. This flaw is disclosed |
| in CVE-2015-5986. [RT #40286] |
| Index: bind-9.10.2-P4/lib/dns/include/dns/message.h |
| =================================================================== |
| --- bind-9.10.2-P4.orig/lib/dns/include/dns/message.h |
| +++ bind-9.10.2-P4/lib/dns/include/dns/message.h |
| @@ -15,8 +15,6 @@ |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| -/* $Id$ */ |
| - |
| #ifndef DNS_MESSAGE_H |
| #define DNS_MESSAGE_H 1 |
| |
| @@ -221,6 +219,8 @@ struct dns_message { |
| unsigned int free_saved : 1; |
| unsigned int sitok : 1; |
| unsigned int sitbad : 1; |
| + unsigned int tkey : 1; |
| + unsigned int rdclass_set : 1; |
| |
| unsigned int opt_reserved; |
| unsigned int sig_reserved; |
| @@ -1400,6 +1400,15 @@ dns_message_buildopt(dns_message_t *msg, |
| * \li other. |
| */ |
| |
| +void |
| +dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass); |
| +/*%< |
| + * Set the expected class of records in the response. |
| + * |
| + * Requires: |
| + * \li msg be a valid message with parsing intent. |
| + */ |
| + |
| ISC_LANG_ENDDECLS |
| |
| #endif /* DNS_MESSAGE_H */ |
| Index: bind-9.10.2-P4/lib/dns/message.c |
| =================================================================== |
| --- bind-9.10.2-P4.orig/lib/dns/message.c |
| +++ bind-9.10.2-P4/lib/dns/message.c |
| @@ -439,6 +439,8 @@ msginit(dns_message_t *m) { |
| m->free_saved = 0; |
| m->sitok = 0; |
| m->sitbad = 0; |
| + m->tkey = 0; |
| + m->rdclass_set = 0; |
| m->querytsig = NULL; |
| } |
| |
| @@ -1091,13 +1093,19 @@ getquestions(isc_buffer_t *source, dns_m |
| * If this class is different than the one we already read, |
| * this is an error. |
| */ |
| - if (msg->state == DNS_SECTION_ANY) { |
| - msg->state = DNS_SECTION_QUESTION; |
| + if (msg->rdclass_set == 0) { |
| msg->rdclass = rdclass; |
| + msg->rdclass_set = 1; |
| } else if (msg->rdclass != rdclass) |
| DO_FORMERR; |
| |
| /* |
| + * Is this a TKEY query? |
| + */ |
| + if (rdtype == dns_rdatatype_tkey) |
| + msg->tkey = 1; |
| + |
| + /* |
| * Can't ask the same question twice. |
| */ |
| result = dns_message_find(name, rdclass, rdtype, 0, NULL); |
| @@ -1241,12 +1249,12 @@ getsection(isc_buffer_t *source, dns_mes |
| * If there was no question section, we may not yet have |
| * established a class. Do so now. |
| */ |
| - if (msg->state == DNS_SECTION_ANY && |
| + if (msg->rdclass_set == 0 && |
| rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ |
| rdtype != dns_rdatatype_tsig && /* class is ANY */ |
| rdtype != dns_rdatatype_tkey) { /* class is undefined */ |
| msg->rdclass = rdclass; |
| - msg->state = DNS_SECTION_QUESTION; |
| + msg->rdclass_set = 1; |
| } |
| |
| /* |
| @@ -1256,7 +1264,7 @@ getsection(isc_buffer_t *source, dns_mes |
| if (msg->opcode != dns_opcode_update |
| && rdtype != dns_rdatatype_tsig |
| && rdtype != dns_rdatatype_opt |
| - && rdtype != dns_rdatatype_dnskey /* in a TKEY query */ |
| + && rdtype != dns_rdatatype_key /* in a TKEY query */ |
| && rdtype != dns_rdatatype_sig /* SIG(0) */ |
| && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ |
| && msg->rdclass != dns_rdataclass_any |
| @@ -1264,6 +1272,16 @@ getsection(isc_buffer_t *source, dns_mes |
| DO_FORMERR; |
| |
| /* |
| + * If this is not a TKEY query/response then the KEY |
| + * record's class needs to match. |
| + */ |
| + if (msg->opcode != dns_opcode_update && !msg->tkey && |
| + rdtype == dns_rdatatype_key && |
| + msg->rdclass != dns_rdataclass_any && |
| + msg->rdclass != rdclass) |
| + DO_FORMERR; |
| + |
| + /* |
| * Special type handling for TSIG, OPT, and TKEY. |
| */ |
| if (rdtype == dns_rdatatype_tsig) { |
| @@ -1377,6 +1395,10 @@ getsection(isc_buffer_t *source, dns_mes |
| skip_name_search = ISC_TRUE; |
| skip_type_search = ISC_TRUE; |
| issigzero = ISC_TRUE; |
| + } else { |
| + if (msg->rdclass != dns_rdataclass_any && |
| + msg->rdclass != rdclass) |
| + DO_FORMERR; |
| } |
| } else |
| covers = 0; |
| @@ -1625,6 +1647,7 @@ dns_message_parse(dns_message_t *msg, is |
| msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); |
| |
| msg->header_ok = 1; |
| + msg->state = DNS_SECTION_QUESTION; |
| |
| /* |
| * -1 means no EDNS. |
| @@ -3706,3 +3729,15 @@ dns_message_buildopt(dns_message_t *mess |
| dns_message_puttemprdatalist(message, &rdatalist); |
| return (result); |
| } |
| + |
| +void |
| +dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) { |
| + |
| + REQUIRE(DNS_MESSAGE_VALID(msg)); |
| + REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); |
| + REQUIRE(msg->state == DNS_SECTION_ANY); |
| + REQUIRE(msg->rdclass_set == 0); |
| + |
| + msg->rdclass = rdclass; |
| + msg->rdclass_set = 1; |
| +} |
| Index: bind-9.10.2-P4/lib/dns/resolver.c |
| =================================================================== |
| --- bind-9.10.2-P4.orig/lib/dns/resolver.c |
| +++ bind-9.10.2-P4/lib/dns/resolver.c |
| @@ -7309,6 +7309,8 @@ resquery_response(isc_task_t *task, isc_ |
| goto done; |
| } |
| |
| + dns_message_setclass(message, fctx->res->rdclass); |
| + |
| if ((options & DNS_FETCHOPT_TCP) == 0) { |
| if ((options & DNS_FETCHOPT_NOEDNS0) == 0) |
| dns_adb_setudpsize(fctx->adb, query->addrinfo, |
| @@ -7391,6 +7393,13 @@ resquery_response(isc_task_t *task, isc_ |
| &dns_master_style_comment, |
| ISC_LOG_DEBUG(10), |
| fctx->res->mctx); |
| + |
| + if (message->rdclass != fctx->res->rdclass) { |
| + resend = ISC_TRUE; |
| + FCTXTRACE("bad class"); |
| + goto done; |
| + } |
| + |
| /* |
| * Process receive opt record. |
| */ |
| Index: bind-9.10.2-P4/lib/dns/xfrin.c |
| =================================================================== |
| --- bind-9.10.2-P4.orig/lib/dns/xfrin.c |
| +++ bind-9.10.2-P4/lib/dns/xfrin.c |
| @@ -1225,6 +1225,8 @@ xfrin_recv_done(isc_task_t *task, isc_ev |
| msg->tsigctx = xfr->tsigctx; |
| xfr->tsigctx = NULL; |
| |
| + dns_message_setclass(msg, xfr->rdclass); |
| + |
| if (xfr->nmsg > 0) |
| msg->tcp_continuation = 1; |
| |
| Index: bind-9.10.2-P4/CHANGES |
| =================================================================== |
| --- bind-9.10.2-P4.orig/CHANGES |
| +++ bind-9.10.2-P4/CHANGES |
| @@ -1,4 +1,9 @@ |
| - --- 9.10.2-P4 released --- |
| +4260. [security] Insufficient testing when parsing a message allowed |
| + records with an incorrect class to be be accepted, |
| + triggering a REQUIRE failure when those records |
| + were subsequently cached. (CVE-2015-8000) [RT #4098] |
| + |
| + --- 9.10.2-P4 released --- |
| |
| 4170. [security] An incorrect boundary check in the OPENPGPKEY |
| rdatatype could trigger an assertion failure. |