| From c1d0599a246f646d1c22018f8fa09459270a44b8 Mon Sep 17 00:00:00 2001 |
| From: Mark Andrews <marka@isc.org> |
| Date: Fri, 21 Oct 2016 14:55:10 +1100 |
| Subject: [PATCH] 4489. [security] It was possible to trigger assertions when |
| processing a response. (CVE-2016-8864) [RT #43465] |
| |
| (cherry picked from commit bd6f27f5c353133b563fe69100b2f168c129f3ca) |
| |
| Upstream-Status: Backport |
| [https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=c1d0599a246f646d1c22018f8fa09459270a44b8] |
| |
| CVE: CVE-2016-8864 |
| |
| Signed-off-by: Yi Zhao <yi.zhao@windriver.com> |
| --- |
| CHANGES | 3 +++ |
| lib/dns/resolver.c | 69 +++++++++++++++++++++++++++++++++++++----------------- |
| 2 files changed, 50 insertions(+), 22 deletions(-) |
| |
| diff --git a/CHANGES b/CHANGES |
| index 5c8c61a..41cfce5 100644 |
| --- a/CHANGES |
| +++ b/CHANGES |
| @@ -1,3 +1,6 @@ |
| +4489. [security] It was possible to trigger assertions when processing |
| + a response. (CVE-2016-8864) [RT #43465] |
| + |
| 4467. [security] It was possible to trigger an assertion when |
| rendering a message. (CVE-2016-2776) [RT #43139] |
| |
| diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c |
| index ba1ae23..13c8b44 100644 |
| --- a/lib/dns/resolver.c |
| +++ b/lib/dns/resolver.c |
| @@ -612,7 +612,9 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name, |
| valarg->addrinfo = addrinfo; |
| |
| if (!ISC_LIST_EMPTY(fctx->validators)) |
| - INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0); |
| + valoptions |= DNS_VALIDATOR_DEFER; |
| + else |
| + valoptions &= ~DNS_VALIDATOR_DEFER; |
| |
| result = dns_validator_create(fctx->res->view, name, type, rdataset, |
| sigrdataset, fctx->rmessage, |
| @@ -5526,13 +5528,6 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, |
| rdataset, |
| sigrdataset, |
| valoptions, task); |
| - /* |
| - * Defer any further validations. |
| - * This prevents multiple validators |
| - * from manipulating fctx->rmessage |
| - * simultaneously. |
| - */ |
| - valoptions |= DNS_VALIDATOR_DEFER; |
| } |
| } else if (CHAINING(rdataset)) { |
| if (rdataset->type == dns_rdatatype_cname) |
| @@ -5647,6 +5642,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, |
| eresult == DNS_R_NCACHENXRRSET); |
| } |
| event->result = eresult; |
| + if (adbp != NULL && *adbp != NULL) { |
| + if (anodep != NULL && *anodep != NULL) |
| + dns_db_detachnode(*adbp, anodep); |
| + dns_db_detach(adbp); |
| + } |
| dns_db_attach(fctx->cache, adbp); |
| dns_db_transfernode(fctx->cache, &node, anodep); |
| clone_results(fctx); |
| @@ -5897,6 +5897,11 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, |
| fctx->attributes |= FCTX_ATTR_HAVEANSWER; |
| if (event != NULL) { |
| event->result = eresult; |
| + if (adbp != NULL && *adbp != NULL) { |
| + if (anodep != NULL && *anodep != NULL) |
| + dns_db_detachnode(*adbp, anodep); |
| + dns_db_detach(adbp); |
| + } |
| dns_db_attach(fctx->cache, adbp); |
| dns_db_transfernode(fctx->cache, &node, anodep); |
| clone_results(fctx); |
| @@ -6718,13 +6723,15 @@ static isc_result_t |
| answer_response(fetchctx_t *fctx) { |
| isc_result_t result; |
| dns_message_t *message; |
| - dns_name_t *name, *dname, *qname, tname, *ns_name; |
| + dns_name_t *name, *dname = NULL, *qname, *dqname, tname, *ns_name; |
| + dns_name_t *cname = NULL; |
| dns_rdataset_t *rdataset, *ns_rdataset; |
| isc_boolean_t done, external, chaining, aa, found, want_chaining; |
| - isc_boolean_t have_answer, found_cname, found_type, wanted_chaining; |
| + isc_boolean_t have_answer, found_cname, found_dname, found_type; |
| + isc_boolean_t wanted_chaining; |
| unsigned int aflag; |
| dns_rdatatype_t type; |
| - dns_fixedname_t fdname, fqname; |
| + dns_fixedname_t fdname, fqname, fqdname; |
| dns_view_t *view; |
| |
| FCTXTRACE("answer_response"); |
| @@ -6738,6 +6745,7 @@ answer_response(fetchctx_t *fctx) { |
| |
| done = ISC_FALSE; |
| found_cname = ISC_FALSE; |
| + found_dname = ISC_FALSE; |
| found_type = ISC_FALSE; |
| chaining = ISC_FALSE; |
| have_answer = ISC_FALSE; |
| @@ -6747,12 +6755,13 @@ answer_response(fetchctx_t *fctx) { |
| aa = ISC_TRUE; |
| else |
| aa = ISC_FALSE; |
| - qname = &fctx->name; |
| + dqname = qname = &fctx->name; |
| type = fctx->type; |
| view = fctx->res->view; |
| + dns_fixedname_init(&fqdname); |
| result = dns_message_firstname(message, DNS_SECTION_ANSWER); |
| while (!done && result == ISC_R_SUCCESS) { |
| - dns_namereln_t namereln; |
| + dns_namereln_t namereln, dnamereln; |
| int order; |
| unsigned int nlabels; |
| |
| @@ -6760,6 +6769,8 @@ answer_response(fetchctx_t *fctx) { |
| dns_message_currentname(message, DNS_SECTION_ANSWER, &name); |
| external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); |
| namereln = dns_name_fullcompare(qname, name, &order, &nlabels); |
| + dnamereln = dns_name_fullcompare(dqname, name, &order, |
| + &nlabels); |
| if (namereln == dns_namereln_equal) { |
| wanted_chaining = ISC_FALSE; |
| for (rdataset = ISC_LIST_HEAD(name->list); |
| @@ -6854,7 +6865,7 @@ answer_response(fetchctx_t *fctx) { |
| } |
| } else if (rdataset->type == dns_rdatatype_rrsig |
| && rdataset->covers == |
| - dns_rdatatype_cname |
| + dns_rdatatype_cname |
| && !found_type) { |
| /* |
| * We're looking for something else, |
| @@ -6884,11 +6895,18 @@ answer_response(fetchctx_t *fctx) { |
| * a CNAME or DNAME). |
| */ |
| INSIST(!external); |
| - if (aflag == |
| - DNS_RDATASETATTR_ANSWER) { |
| + if ((rdataset->type != |
| + dns_rdatatype_cname) || |
| + !found_dname || |
| + (aflag == |
| + DNS_RDATASETATTR_ANSWER)) |
| + { |
| have_answer = ISC_TRUE; |
| + if (rdataset->type == |
| + dns_rdatatype_cname) |
| + cname = name; |
| name->attributes |= |
| - DNS_NAMEATTR_ANSWER; |
| + DNS_NAMEATTR_ANSWER; |
| } |
| rdataset->attributes |= aflag; |
| if (aa) |
| @@ -6982,11 +7000,11 @@ answer_response(fetchctx_t *fctx) { |
| return (DNS_R_FORMERR); |
| } |
| |
| - if (namereln != dns_namereln_subdomain) { |
| + if (dnamereln != dns_namereln_subdomain) { |
| char qbuf[DNS_NAME_FORMATSIZE]; |
| char obuf[DNS_NAME_FORMATSIZE]; |
| |
| - dns_name_format(qname, qbuf, |
| + dns_name_format(dqname, qbuf, |
| sizeof(qbuf)); |
| dns_name_format(name, obuf, |
| sizeof(obuf)); |
| @@ -7001,7 +7019,7 @@ answer_response(fetchctx_t *fctx) { |
| want_chaining = ISC_TRUE; |
| POST(want_chaining); |
| aflag = DNS_RDATASETATTR_ANSWER; |
| - result = dname_target(rdataset, qname, |
| + result = dname_target(rdataset, dqname, |
| nlabels, &fdname); |
| if (result == ISC_R_NOSPACE) { |
| /* |
| @@ -7018,10 +7036,13 @@ answer_response(fetchctx_t *fctx) { |
| |
| dname = dns_fixedname_name(&fdname); |
| if (!is_answertarget_allowed(view, |
| - qname, rdataset->type, |
| - dname, &fctx->domain)) { |
| + dqname, rdataset->type, |
| + dname, &fctx->domain)) |
| + { |
| return (DNS_R_SERVFAIL); |
| } |
| + dqname = dns_fixedname_name(&fqdname); |
| + dns_name_copy(dname, dqname, NULL); |
| } else { |
| /* |
| * We've found a signature that |
| @@ -7046,6 +7067,10 @@ answer_response(fetchctx_t *fctx) { |
| INSIST(!external); |
| if (aflag == DNS_RDATASETATTR_ANSWER) { |
| have_answer = ISC_TRUE; |
| + found_dname = ISC_TRUE; |
| + if (cname != NULL) |
| + cname->attributes &= |
| + ~DNS_NAMEATTR_ANSWER; |
| name->attributes |= |
| DNS_NAMEATTR_ANSWER; |
| } |
| -- |
| 2.7.4 |
| |