Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 1 | From 8259daad7242ab2af8731681177ef7e948a15ece Mon Sep 17 00:00:00 2001 |
| 2 | From: Mark Andrews <marka@isc.org> |
| 3 | Date: Mon, 16 Nov 2015 13:12:20 +1100 |
| 4 | Subject: [PATCH] 4260. [security] Insufficient testing when parsing a |
| 5 | message allowed records with an incorrect class to be |
| 6 | be accepted, triggering a REQUIRE failure when those |
| 7 | records were subsequently cached. (CVE-2015-8000) [RT |
| 8 | #4098] |
| 9 | |
| 10 | (cherry picked from commit c8821d124c532e0a65752b378f924d4259499fd3) |
| 11 | (cherry picked from commit 3a4c24c4a52d4a2d21d2decbde3d4e514e27d51c) |
| 12 | |
| 13 | |
| 14 | Upstream-Status: Backport |
| 15 | |
| 16 | https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=8259daad7242ab2af8731681177ef7e948a15ece |
| 17 | |
| 18 | CVE: CVE-2015-8000 |
| 19 | |
| 20 | Signed-off-by: Armin Kuster <akuster@mvista.com> |
| 21 | |
| 22 | --- |
| 23 | CHANGES | 5 +++++ |
| 24 | bin/tests/system/start.pl | 5 ++++- |
| 25 | doc/arm/notes.xml | 9 +++++++++ |
| 26 | lib/dns/include/dns/message.h | 13 +++++++++++-- |
| 27 | lib/dns/message.c | 45 ++++++++++++++++++++++++++++++++++++++----- |
| 28 | lib/dns/resolver.c | 9 +++++++++ |
| 29 | lib/dns/xfrin.c | 2 ++ |
| 30 | 7 files changed, 80 insertions(+), 8 deletions(-) |
| 31 | |
| 32 | Index: bind-9.10.2-P4/bin/tests/system/start.pl |
| 33 | =================================================================== |
| 34 | --- bind-9.10.2-P4.orig/bin/tests/system/start.pl |
| 35 | +++ bind-9.10.2-P4/bin/tests/system/start.pl |
| 36 | @@ -68,6 +68,7 @@ my $NAMED = $ENV{'NAMED'}; |
| 37 | my $LWRESD = $ENV{'LWRESD'}; |
| 38 | my $DIG = $ENV{'DIG'}; |
| 39 | my $PERL = $ENV{'PERL'}; |
| 40 | +my $PYTHON = $ENV{'PYTHON'}; |
| 41 | |
| 42 | # Start the server(s) |
| 43 | |
| 44 | @@ -213,7 +214,9 @@ sub start_server { |
| 45 | $pid_file = "lwresd.pid"; |
| 46 | } elsif ($server =~ /^ans/) { |
| 47 | $cleanup_files = "{ans.run}"; |
| 48 | - if (-e "$testdir/$server/ans.pl") { |
| 49 | + if (-e "$testdir/$server/ans.py") { |
| 50 | + $command = "$PYTHON ans.py 10.53.0.$' 5300"; |
| 51 | + } elsif (-e "$testdir/$server/ans.pl") { |
| 52 | $command = "$PERL ans.pl"; |
| 53 | } else { |
| 54 | $command = "$PERL $topdir/ans.pl 10.53.0.$'"; |
| 55 | Index: bind-9.10.2-P4/doc/arm/notes.xml |
| 56 | =================================================================== |
| 57 | --- bind-9.10.2-P4.orig/doc/arm/notes.xml |
| 58 | +++ bind-9.10.2-P4/doc/arm/notes.xml |
| 59 | @@ -62,6 +62,15 @@ |
| 60 | <itemizedlist> |
| 61 | <listitem> |
| 62 | <para> |
| 63 | + Insufficient testing when parsing a message allowed |
| 64 | + records with an incorrect class to be be accepted, |
| 65 | + triggering a REQUIRE failure when those records |
| 66 | + were subsequently cached. This flaw is disclosed |
| 67 | + in CVE-2015-8000. [RT #4098] |
| 68 | + </para> |
| 69 | + </listitem> |
| 70 | + <listitem> |
| 71 | + <para> |
| 72 | An incorrect boundary check in the OPENPGPKEY rdatatype |
| 73 | could trigger an assertion failure. This flaw is disclosed |
| 74 | in CVE-2015-5986. [RT #40286] |
| 75 | Index: bind-9.10.2-P4/lib/dns/include/dns/message.h |
| 76 | =================================================================== |
| 77 | --- bind-9.10.2-P4.orig/lib/dns/include/dns/message.h |
| 78 | +++ bind-9.10.2-P4/lib/dns/include/dns/message.h |
| 79 | @@ -15,8 +15,6 @@ |
| 80 | * PERFORMANCE OF THIS SOFTWARE. |
| 81 | */ |
| 82 | |
| 83 | -/* $Id$ */ |
| 84 | - |
| 85 | #ifndef DNS_MESSAGE_H |
| 86 | #define DNS_MESSAGE_H 1 |
| 87 | |
| 88 | @@ -221,6 +219,8 @@ struct dns_message { |
| 89 | unsigned int free_saved : 1; |
| 90 | unsigned int sitok : 1; |
| 91 | unsigned int sitbad : 1; |
| 92 | + unsigned int tkey : 1; |
| 93 | + unsigned int rdclass_set : 1; |
| 94 | |
| 95 | unsigned int opt_reserved; |
| 96 | unsigned int sig_reserved; |
| 97 | @@ -1400,6 +1400,15 @@ dns_message_buildopt(dns_message_t *msg, |
| 98 | * \li other. |
| 99 | */ |
| 100 | |
| 101 | +void |
| 102 | +dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass); |
| 103 | +/*%< |
| 104 | + * Set the expected class of records in the response. |
| 105 | + * |
| 106 | + * Requires: |
| 107 | + * \li msg be a valid message with parsing intent. |
| 108 | + */ |
| 109 | + |
| 110 | ISC_LANG_ENDDECLS |
| 111 | |
| 112 | #endif /* DNS_MESSAGE_H */ |
| 113 | Index: bind-9.10.2-P4/lib/dns/message.c |
| 114 | =================================================================== |
| 115 | --- bind-9.10.2-P4.orig/lib/dns/message.c |
| 116 | +++ bind-9.10.2-P4/lib/dns/message.c |
| 117 | @@ -439,6 +439,8 @@ msginit(dns_message_t *m) { |
| 118 | m->free_saved = 0; |
| 119 | m->sitok = 0; |
| 120 | m->sitbad = 0; |
| 121 | + m->tkey = 0; |
| 122 | + m->rdclass_set = 0; |
| 123 | m->querytsig = NULL; |
| 124 | } |
| 125 | |
| 126 | @@ -1091,13 +1093,19 @@ getquestions(isc_buffer_t *source, dns_m |
| 127 | * If this class is different than the one we already read, |
| 128 | * this is an error. |
| 129 | */ |
| 130 | - if (msg->state == DNS_SECTION_ANY) { |
| 131 | - msg->state = DNS_SECTION_QUESTION; |
| 132 | + if (msg->rdclass_set == 0) { |
| 133 | msg->rdclass = rdclass; |
| 134 | + msg->rdclass_set = 1; |
| 135 | } else if (msg->rdclass != rdclass) |
| 136 | DO_FORMERR; |
| 137 | |
| 138 | /* |
| 139 | + * Is this a TKEY query? |
| 140 | + */ |
| 141 | + if (rdtype == dns_rdatatype_tkey) |
| 142 | + msg->tkey = 1; |
| 143 | + |
| 144 | + /* |
| 145 | * Can't ask the same question twice. |
| 146 | */ |
| 147 | result = dns_message_find(name, rdclass, rdtype, 0, NULL); |
| 148 | @@ -1241,12 +1249,12 @@ getsection(isc_buffer_t *source, dns_mes |
| 149 | * If there was no question section, we may not yet have |
| 150 | * established a class. Do so now. |
| 151 | */ |
| 152 | - if (msg->state == DNS_SECTION_ANY && |
| 153 | + if (msg->rdclass_set == 0 && |
| 154 | rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ |
| 155 | rdtype != dns_rdatatype_tsig && /* class is ANY */ |
| 156 | rdtype != dns_rdatatype_tkey) { /* class is undefined */ |
| 157 | msg->rdclass = rdclass; |
| 158 | - msg->state = DNS_SECTION_QUESTION; |
| 159 | + msg->rdclass_set = 1; |
| 160 | } |
| 161 | |
| 162 | /* |
| 163 | @@ -1256,7 +1264,7 @@ getsection(isc_buffer_t *source, dns_mes |
| 164 | if (msg->opcode != dns_opcode_update |
| 165 | && rdtype != dns_rdatatype_tsig |
| 166 | && rdtype != dns_rdatatype_opt |
| 167 | - && rdtype != dns_rdatatype_dnskey /* in a TKEY query */ |
| 168 | + && rdtype != dns_rdatatype_key /* in a TKEY query */ |
| 169 | && rdtype != dns_rdatatype_sig /* SIG(0) */ |
| 170 | && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ |
| 171 | && msg->rdclass != dns_rdataclass_any |
| 172 | @@ -1264,6 +1272,16 @@ getsection(isc_buffer_t *source, dns_mes |
| 173 | DO_FORMERR; |
| 174 | |
| 175 | /* |
| 176 | + * If this is not a TKEY query/response then the KEY |
| 177 | + * record's class needs to match. |
| 178 | + */ |
| 179 | + if (msg->opcode != dns_opcode_update && !msg->tkey && |
| 180 | + rdtype == dns_rdatatype_key && |
| 181 | + msg->rdclass != dns_rdataclass_any && |
| 182 | + msg->rdclass != rdclass) |
| 183 | + DO_FORMERR; |
| 184 | + |
| 185 | + /* |
| 186 | * Special type handling for TSIG, OPT, and TKEY. |
| 187 | */ |
| 188 | if (rdtype == dns_rdatatype_tsig) { |
| 189 | @@ -1377,6 +1395,10 @@ getsection(isc_buffer_t *source, dns_mes |
| 190 | skip_name_search = ISC_TRUE; |
| 191 | skip_type_search = ISC_TRUE; |
| 192 | issigzero = ISC_TRUE; |
| 193 | + } else { |
| 194 | + if (msg->rdclass != dns_rdataclass_any && |
| 195 | + msg->rdclass != rdclass) |
| 196 | + DO_FORMERR; |
| 197 | } |
| 198 | } else |
| 199 | covers = 0; |
| 200 | @@ -1625,6 +1647,7 @@ dns_message_parse(dns_message_t *msg, is |
| 201 | msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); |
| 202 | |
| 203 | msg->header_ok = 1; |
| 204 | + msg->state = DNS_SECTION_QUESTION; |
| 205 | |
| 206 | /* |
| 207 | * -1 means no EDNS. |
| 208 | @@ -3706,3 +3729,15 @@ dns_message_buildopt(dns_message_t *mess |
| 209 | dns_message_puttemprdatalist(message, &rdatalist); |
| 210 | return (result); |
| 211 | } |
| 212 | + |
| 213 | +void |
| 214 | +dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) { |
| 215 | + |
| 216 | + REQUIRE(DNS_MESSAGE_VALID(msg)); |
| 217 | + REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); |
| 218 | + REQUIRE(msg->state == DNS_SECTION_ANY); |
| 219 | + REQUIRE(msg->rdclass_set == 0); |
| 220 | + |
| 221 | + msg->rdclass = rdclass; |
| 222 | + msg->rdclass_set = 1; |
| 223 | +} |
| 224 | Index: bind-9.10.2-P4/lib/dns/resolver.c |
| 225 | =================================================================== |
| 226 | --- bind-9.10.2-P4.orig/lib/dns/resolver.c |
| 227 | +++ bind-9.10.2-P4/lib/dns/resolver.c |
| 228 | @@ -7309,6 +7309,8 @@ resquery_response(isc_task_t *task, isc_ |
| 229 | goto done; |
| 230 | } |
| 231 | |
| 232 | + dns_message_setclass(message, fctx->res->rdclass); |
| 233 | + |
| 234 | if ((options & DNS_FETCHOPT_TCP) == 0) { |
| 235 | if ((options & DNS_FETCHOPT_NOEDNS0) == 0) |
| 236 | dns_adb_setudpsize(fctx->adb, query->addrinfo, |
| 237 | @@ -7391,6 +7393,13 @@ resquery_response(isc_task_t *task, isc_ |
| 238 | &dns_master_style_comment, |
| 239 | ISC_LOG_DEBUG(10), |
| 240 | fctx->res->mctx); |
| 241 | + |
| 242 | + if (message->rdclass != fctx->res->rdclass) { |
| 243 | + resend = ISC_TRUE; |
| 244 | + FCTXTRACE("bad class"); |
| 245 | + goto done; |
| 246 | + } |
| 247 | + |
| 248 | /* |
| 249 | * Process receive opt record. |
| 250 | */ |
| 251 | Index: bind-9.10.2-P4/lib/dns/xfrin.c |
| 252 | =================================================================== |
| 253 | --- bind-9.10.2-P4.orig/lib/dns/xfrin.c |
| 254 | +++ bind-9.10.2-P4/lib/dns/xfrin.c |
| 255 | @@ -1225,6 +1225,8 @@ xfrin_recv_done(isc_task_t *task, isc_ev |
| 256 | msg->tsigctx = xfr->tsigctx; |
| 257 | xfr->tsigctx = NULL; |
| 258 | |
| 259 | + dns_message_setclass(msg, xfr->rdclass); |
| 260 | + |
| 261 | if (xfr->nmsg > 0) |
| 262 | msg->tcp_continuation = 1; |
| 263 | |
| 264 | Index: bind-9.10.2-P4/CHANGES |
| 265 | =================================================================== |
| 266 | --- bind-9.10.2-P4.orig/CHANGES |
| 267 | +++ bind-9.10.2-P4/CHANGES |
| 268 | @@ -1,4 +1,9 @@ |
| 269 | - --- 9.10.2-P4 released --- |
| 270 | +4260. [security] Insufficient testing when parsing a message allowed |
| 271 | + records with an incorrect class to be be accepted, |
| 272 | + triggering a REQUIRE failure when those records |
| 273 | + were subsequently cached. (CVE-2015-8000) [RT #4098] |
| 274 | + |
| 275 | + --- 9.10.2-P4 released --- |
| 276 | |
| 277 | 4170. [security] An incorrect boundary check in the OPENPGPKEY |
| 278 | rdatatype could trigger an assertion failure. |