ソースを Diff ってみた。
■bind-9.11.0-P1 と bind-9.11.0-P2 の差分
・差分 Diff の作成
$ diff -uprN bind-9.9.9-P4/bin bind-9.9.9-P5/bin > bind-9.9.9-P5_bin.diff $ diff -uprN bind-9.9.9-P4/lib bind-9.9.9-P5/lib > bind-9.9.9-P5_lib.diff $ diff -uprN bind-9.9.9-P4/util bind-9.9.9-P5/util > bind-9.9.9-P5_util.diff $ diff -uprN bind-9.10.4-P4/bin bind-9.10.4-P5/bin > bind-9.10.4-P5_bin.diff $ diff -uprN bind-9.10.4-P4/lib bind-9.10.4-P5/lib > bind-9.10.4-P5_lib.diff $ diff -uprN bind-9.10.4-P4/util bind-9.10.4-P5/util > bind-9.10.4-P5_util.diff $ diff -uprN bind-9.11.0-P1/bin bind-9.11.0-P2/bin > bind-9.11.0-P2_bin.diff $ diff -uprN bind-9.11.0-P1/lib bind-9.11.0-P2/lib > bind-9.11.0-P2_lib.diff $ diff -uprN bind-9.11.0-P1/util bind-9.11.0-P2/util > bind-9.11.0-P2_util.diff $ ls -la *.diff -rw-rw-r-- 1 admin admin 1831 Jan 12 07:53 bind-9.10.4-P5_bin.diff -rw-rw-r-- 1 admin admin 11629 Jan 12 07:53 bind-9.10.4-P5_lib.diff -rw-rw-r-- 1 admin admin 0 Jan 12 07:53 bind-9.10.4-P5_util.diff -rw-rw-r-- 1 admin admin 6545 Jan 12 07:53 bind-9.11.0-P2_bin.diff -rw-rw-r-- 1 admin admin 11490 Jan 12 07:53 bind-9.11.0-P2_lib.diff -rw-rw-r-- 1 admin admin 0 Jan 12 07:53 bind-9.11.0-P2_util.diff -rw-rw-r-- 1 admin admin 1823 Jan 12 07:52 bind-9.9.9-P5_bin.diff -rw-rw-r-- 1 admin admin 11346 Jan 12 07:53 bind-9.9.9-P5_lib.diff -rw-rw-r-- 1 admin admin 0 Jan 12 07:53 bind-9.9.9-P5_util.diff
・bin ディレクトリの中身の差分を見てみる@bind-9.11.0-P2
$ cat bind-9.11.0-P2_bin.diff diff -uprN bind-9.11.0-P1/bin/named/include/named/query.h bind-9.11.0-P2/bin/named/include/named/query.h --- bind-9.11.0-P1/bin/named/include/named/query.h 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/bin/named/include/named/query.h 2016-12-12 07:05:44.000000000 +0900 @@ -69,6 +69,7 @@ struct ns_query { dns_rdataset_t * rdataset; dns_rdataset_t * sigrdataset; isc_boolean_t authoritative; + isc_boolean_t is_zone; } redirect; }; diff -uprN bind-9.11.0-P1/bin/named/query.c bind-9.11.0-P2/bin/named/query.c --- bind-9.11.0-P1/bin/named/query.c 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/bin/named/query.c 2016-12-12 07:05:44.000000000 +0900 @@ -701,6 +701,8 @@ ns_query_init(ns_client_t *client) { client->query.redirect.result = ISC_R_SUCCESS; client->query.redirect.rdataset = NULL; client->query.redirect.sigrdataset = NULL; + client->query.redirect.authoritative = ISC_FALSE; + client->query.redirect.is_zone = ISC_FALSE; dns_fixedname_init(&client->query.redirect.fixed); client->query.redirect.fname = dns_fixedname_name(&client->query.redirect.fixed); @@ -1176,7 +1178,6 @@ query_getcachedb(ns_client_t *client, dn return (result); } - static inline isc_result_t query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, unsigned int options, dns_zone_t **zonep, dns_db_t **dbp, @@ -6306,7 +6307,7 @@ redirect(ns_client_t *client, dns_name_t static isc_result_t redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp, - dns_rdatatype_t qtype) + dns_rdatatype_t qtype, isc_boolean_t *is_zonep) { dns_db_t *db = NULL; dns_dbnode_t *node = NULL; @@ -6320,8 +6321,8 @@ redirect2(ns_client_t *client, dns_name_ dns_clientinfo_t ci; dns_dbversion_t *version = NULL; dns_zone_t *zone = NULL; + isc_boolean_t is_zone; unsigned int options; - isc_boolean_t is_zonep = ISC_FALSE; CTRACE(ISC_LOG_DEBUG(3), "redirect2"); @@ -6381,7 +6382,7 @@ redirect2(ns_client_t *client, dns_name_ options = 0; result = query_getdb(client, redirectname, qtype, options, &zone, - &db, &version, &is_zonep); + &db, &version, &is_zone); if (result != ISC_R_SUCCESS) return (ISC_R_NOTFOUND); if (zone != NULL) @@ -6459,6 +6460,7 @@ redirect2(ns_client_t *client, dns_name_ dns_db_attach(db, dbp); dns_db_detachnode(db, &node); dns_db_detach(&db); + *is_zonep = is_zone; *versionp = version; client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | @@ -6651,6 +6653,7 @@ query_find(ns_client_t *client, dns_fetc RESTORE(node, client->query.redirect.node); RESTORE(zone, client->query.redirect.zone); authoritative = client->query.redirect.authoritative; + is_zone = client->query.redirect.is_zone; /* * Free resources used while recursing. @@ -6746,7 +6749,7 @@ query_find(ns_client_t *client, dns_fetc isc_event_free(ISC_EVENT_PTR(&event)); } else if (REDIRECT(client)) { result = client->query.redirect.result; - is_zone = ISC_TF(result == DNS_R_NXDOMAIN); + is_zone = client->query.redirect.is_zone; } else { result = event->result; } @@ -7785,7 +7788,7 @@ query_find(ns_client_t *client, dns_fetc /* FALLTHROUGH */ case DNS_R_NXDOMAIN: - INSIST(is_zone); + INSIST(is_zone || REDIRECT(client)); if (!empty_wild) { tresult = redirect(client, fname, rdataset, &node, &db, &version, type); @@ -7804,7 +7807,7 @@ query_find(ns_client_t *client, dns_fetc goto ncache_nxrrset; } tresult = redirect2(client, fname, rdataset, &node, - &db, &version, type); + &db, &version, type, &is_zone); if (tresult == DNS_R_CONTINUE) { inc_stats(client, dns_nsstatscounter_nxdomainredirect_rlookup); @@ -7822,6 +7825,7 @@ query_find(ns_client_t *client, dns_fetc NULL); client->query.redirect.authoritative = authoritative; + client->query.redirect.is_zone = is_zone; goto cleanup; } if (tresult == ISC_R_SUCCESS) { @@ -7919,7 +7923,7 @@ query_find(ns_client_t *client, dns_fetc goto ncache_nxrrset; } tresult = redirect2(client, fname, rdataset, &node, - &db, &version, type); + &db, &version, type, &is_zone); if (tresult == DNS_R_CONTINUE) { inc_stats(client, dns_nsstatscounter_nxdomainredirect_rlookup); @@ -7934,6 +7938,7 @@ query_find(ns_client_t *client, dns_fetc dns_name_copy(fname, client->query.redirect.fname, NULL); client->query.redirect.authoritative = authoritative; + client->query.redirect.is_zone = is_zone; goto cleanup; } if (tresult == ISC_R_SUCCESS) { diff -uprN bind-9.11.0-P1/bin/tests/system/dname/ns2/example.db bind-9.11.0-P2/bin/tests/system/dname/ns2/example.db --- bind-9.11.0-P1/bin/tests/system/dname/ns2/example.db 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/bin/tests/system/dname/ns2/example.db 2016-12-12 07:05:44.000000000 +0900 @@ -21,4 +21,6 @@ a.short A 10.0.0.1 short-dname DNAME short a.longlonglonglonglonglonglonglonglonglonglonglonglong A 10.0.0.2 long-dname DNAME longlonglonglonglonglonglonglonglonglonglonglonglong -; +cname CNAME a.cnamedname +cnamedname DNAME target +a.target A 10.0.0.3 diff -uprN bind-9.11.0-P1/bin/tests/system/dname/tests.sh bind-9.11.0-P2/bin/tests/system/dname/tests.sh --- bind-9.11.0-P1/bin/tests/system/dname/tests.sh 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/bin/tests/system/dname/tests.sh 2016-12-12 07:05:44.000000000 +0900 @@ -55,6 +55,24 @@ grep "status: YXDOMAIN" dig.out.ns4.tool if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:checking cname to dname from authoritative" +ret=0 +$DIG cname.example @10.53.0.2 a -p 5300 > dig.out.ns2.cname +grep "status: NOERROR" dig.out.ns2.cname > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:checking cname to dname from recursive" +ret=0 +$DIG cname.example @10.53.0.4 a -p 5300 > dig.out.ns4.cname +grep "status: NOERROR" dig.out.ns4.cname > /dev/null || ret=1 +grep '^cname.example.' dig.out.ns4.cname > /dev/null || ret=1 +grep '^cnamedname.example.' dig.out.ns4.cname > /dev/null || ret=1 +grep '^a.cnamedname.example.' dig.out.ns4.cname > /dev/null || ret=1 +grep '^a.target.example.' dig.out.ns4.cname > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:exit status: $status" [ $status -eq 0 ] || exit 1
・lib ディレクトリの中身の差分を見てみる@bind-9.11.0-P2
$ cat bind-9.11.0-P2_lib.diff diff -uprN bind-9.11.0-P1/lib/dns/api bind-9.11.0-P2/lib/dns/api --- bind-9.11.0-P1/lib/dns/api 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/lib/dns/api 2016-12-12 07:05:44.000000000 +0900 @@ -7,5 +7,5 @@ # 9.10: 140-149 # 9.11: 160-169 LIBINTERFACE = 166 -LIBREVISION = 3 +LIBREVISION = 4 LIBAGE = 0 diff -uprN bind-9.11.0-P1/lib/dns/message.c bind-9.11.0-P2/lib/dns/message.c --- bind-9.11.0-P1/lib/dns/message.c 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/lib/dns/message.c 2016-12-12 07:05:44.000000000 +0900 @@ -1148,6 +1148,63 @@ update(dns_section_t section, dns_rdatac return (ISC_FALSE); } +/* + * Check to confirm that all DNSSEC records (DS, NSEC, NSEC3) have + * covering RRSIGs. + */ +static isc_boolean_t +auth_signed(dns_namelist_t *section) { + dns_name_t *name; + + for (name = ISC_LIST_HEAD(*section); + name != NULL; + name = ISC_LIST_NEXT(name, link)) + { + int auth_dnssec = 0, auth_rrsig = 0; + dns_rdataset_t *rds; + + for (rds = ISC_LIST_HEAD(name->list); + rds != NULL; + rds = ISC_LIST_NEXT(rds, link)) + { + switch (rds->type) { + case dns_rdatatype_ds: + auth_dnssec |= 0x1; + break; + case dns_rdatatype_nsec: + auth_dnssec |= 0x2; + break; + case dns_rdatatype_nsec3: + auth_dnssec |= 0x4; + break; + case dns_rdatatype_rrsig: + break; + default: + continue; + } + + switch (rds->covers) { + case dns_rdatatype_ds: + auth_rrsig |= 0x1; + break; + case dns_rdatatype_nsec: + auth_rrsig |= 0x2; + break; + case dns_rdatatype_nsec3: + auth_rrsig |= 0x4; + break; + default: + break; + } + } + + if (auth_dnssec != auth_rrsig) + return (ISC_FALSE); + } + + return (ISC_TRUE); +} + static isc_result_t getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_section_t sectionid, unsigned int options) @@ -1173,12 +1230,12 @@ getsection(isc_buffer_t *source, dns_mes best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); seen_problem = ISC_FALSE; + section = &msg->sections[sectionid]; + for (count = 0; count < msg->counts[sectionid]; count++) { int recstart = source->current; isc_boolean_t skip_name_search, skip_type_search; - section = &msg->sections[sectionid]; - skip_name_search = ISC_FALSE; skip_type_search = ISC_FALSE; free_rdataset = ISC_FALSE; @@ -1352,7 +1409,7 @@ getsection(isc_buffer_t *source, dns_mes goto cleanup; rdata->rdclass = rdclass; issigzero = ISC_FALSE; - if (rdtype == dns_rdatatype_rrsig && + if (rdtype == dns_rdatatype_rrsig && rdata->flags == 0) { covers = dns_rdata_covers(rdata); if (covers == 0) @@ -1563,6 +1620,19 @@ getsection(isc_buffer_t *source, dns_mes INSIST(free_rdataset == ISC_FALSE); } + /* + * If any of DS, NSEC or NSEC3 appeared in the + * authority section of a query response without + * a covering RRSIG, FORMERR + */ + if (sectionid == DNS_SECTION_AUTHORITY && + msg->opcode == dns_opcode_query && + ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) && + ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) && + !preserve_order && + !auth_signed(section)) + DO_ERROR(DNS_R_FORMERR); + if (seen_problem) return (DNS_R_RECOVERABLE); return (ISC_R_SUCCESS); diff -uprN bind-9.11.0-P1/lib/dns/resolver.c bind-9.11.0-P2/lib/dns/resolver.c --- bind-9.11.0-P1/lib/dns/resolver.c 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/lib/dns/resolver.c 2016-12-12 07:05:44.000000000 +0900 @@ -5525,16 +5525,13 @@ cache_name(fetchctx_t *fctx, dns_name_t rdataset->type, &noqname); if (tresult == ISC_R_SUCCESS && - noqname != NULL) { - tresult = - dns_rdataset_addnoqname( + noqname != NULL) + (void) dns_rdataset_addnoqname( rdataset, noqname); - RUNTIME_CHECK(tresult == - ISC_R_SUCCESS); - } } - if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) - options = DNS_DBADD_PREFETCH; + if ((fctx->options & + DNS_FETCHOPT_PREFETCH) != 0) + options = DNS_DBADD_PREFETCH; addedrdataset = ardataset; result = dns_db_addrdataset(fctx->cache, node, NULL, now, rdataset, @@ -5667,11 +5664,9 @@ cache_name(fetchctx_t *fctx, dns_name_t tresult = findnoqname(fctx, name, rdataset->type, &noqname); if (tresult == ISC_R_SUCCESS && - noqname != NULL) { - tresult = dns_rdataset_addnoqname( - rdataset, noqname); - RUNTIME_CHECK(tresult == ISC_R_SUCCESS); - } + noqname != NULL) + (void) dns_rdataset_addnoqname( + rdataset, noqname); } /* @@ -6807,7 +6802,7 @@ static isc_result_t answer_response(fetchctx_t *fctx) { isc_result_t result; dns_message_t *message; - dns_name_t *name, *dname = NULL, *qname, *dqname, tname, *ns_name; + dns_name_t *name, *dname = NULL, *qname, tname, *ns_name; dns_name_t *cname = NULL; dns_rdataset_t *rdataset, *ns_rdataset; isc_boolean_t done, external, chaining, aa, found, want_chaining; @@ -6815,7 +6810,7 @@ answer_response(fetchctx_t *fctx) { isc_boolean_t wanted_chaining; unsigned int aflag; dns_rdatatype_t type; - dns_fixedname_t fdname, fqname, fqdname; + dns_fixedname_t fdname, fqname; dns_view_t *view; FCTXTRACE("answer_response"); @@ -6839,13 +6834,12 @@ answer_response(fetchctx_t *fctx) { aa = ISC_TRUE; else aa = ISC_FALSE; - dqname = qname = &fctx->name; + 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, dnamereln; + dns_namereln_t namereln; int order; unsigned int nlabels; @@ -6853,8 +6847,6 @@ 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); @@ -6871,6 +6863,19 @@ answer_response(fetchctx_t *fctx) { log_formerr(fctx, "NSEC3 in answer"); return (DNS_R_FORMERR); } + if (rdataset->type == dns_rdatatype_tkey) { + /* + * TKEY is not a valid record in a + * response to any query we can make. + */ + log_formerr(fctx, "TKEY in answer"); + return (DNS_R_FORMERR); + } + if (rdataset->rdclass != fctx->res->rdclass) { + log_formerr(fctx, "Mismatched class " + "in answer"); + return (DNS_R_FORMERR); + } /* * Apply filters, if given, on answers to reject @@ -6979,15 +6984,19 @@ answer_response(fetchctx_t *fctx) { * a CNAME or DNAME). */ INSIST(!external); - if ((rdataset->type != - dns_rdatatype_cname) || - !found_dname || - (aflag == - DNS_RDATASETATTR_ANSWER)) + /* + * Don't use found_cname here + * as we have just set it + * above. + */ + if (cname == NULL && + !found_dname && + aflag == + DNS_RDATASETATTR_ANSWER) { have_answer = ISC_TRUE; - if (rdataset->type == - dns_rdatatype_cname) + if (found_cname && + cname == NULL) cname = name; name->attributes |= DNS_NAMEATTR_ANSWER; @@ -7057,6 +7066,12 @@ answer_response(fetchctx_t *fctx) { rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (rdataset->rdclass != fctx->res->rdclass) { + log_formerr(fctx, "Mismatched class " + "in answer"); + return (DNS_R_FORMERR); + } + /* * Only pass DNAME or RRSIG(DNAME). */ @@ -7084,11 +7099,24 @@ answer_response(fetchctx_t *fctx) { return (DNS_R_FORMERR); } - if (dnamereln != dns_namereln_subdomain) { + /* + * If DNAME + synthetic CNAME then the + * namereln is dns_namereln_subdomain. + * + * If synthetic CNAME + DNAME then the + * namereln is dns_namereln_commonancestor + * and the number of label must match the + * DNAME. This order is not RFC compliant. + */ + + if (namereln != dns_namereln_subdomain && + (namereln != dns_namereln_commonancestor || + nlabels != dns_name_countlabels(name))) + { char qbuf[DNS_NAME_FORMATSIZE]; char obuf[DNS_NAME_FORMATSIZE]; - dns_name_format(dqname, qbuf, + dns_name_format(qname, qbuf, sizeof(qbuf)); dns_name_format(name, obuf, sizeof(obuf)); @@ -7103,7 +7131,7 @@ answer_response(fetchctx_t *fctx) { want_chaining = ISC_TRUE; POST(want_chaining); aflag = DNS_RDATASETATTR_ANSWER; - result = dname_target(rdataset, dqname, + result = dname_target(rdataset, qname, nlabels, &fdname); if (result == ISC_R_NOSPACE) { /* @@ -7120,13 +7148,11 @@ answer_response(fetchctx_t *fctx) { dname = dns_fixedname_name(&fdname); if (!is_answertarget_allowed(view, - dqname, rdataset->type, + qname, 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 @@ -7272,7 +7298,8 @@ answer_response(fetchctx_t *fctx) { rdataset->trust = dns_trust_additional; - if (rdataset->type == dns_rdatatype_ns) { + if (rdataset->type == dns_rdatatype_ns) + { ns_name = name; ns_rdataset = rdataset; } diff -uprN bind-9.11.0-P1/lib/isc/api bind-9.11.0-P2/lib/isc/api --- bind-9.11.0-P1/lib/isc/api 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/lib/isc/api 2016-12-12 07:05:44.000000000 +0900 @@ -7,5 +7,5 @@ # 9.10: 140-149 # 9.11: 160-169 LIBINTERFACE = 165 -LIBREVISION = 1 +LIBREVISION = 2 LIBAGE = 5 diff -uprN bind-9.11.0-P1/lib/isc/unix/socket.c bind-9.11.0-P2/lib/isc/unix/socket.c --- bind-9.11.0-P1/lib/isc/unix/socket.c 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/lib/isc/unix/socket.c 2016-12-12 07:05:44.000000000 +0900 @@ -4108,7 +4108,8 @@ process_fds(isc__socketmgr_t *manager, s * events. Note also that the read or write attempt * won't block because we use non-blocking sockets. */ - events[i].events |= (EPOLLIN | EPOLLOUT); + int fd = events[i].data.fd; + events[i].events |= manager->epoll_events[fd]; } process_fd(manager, events[i].data.fd, (events[i].events & EPOLLIN) != 0, diff -uprN bind-9.11.0-P1/lib/isc/win32/socket.c bind-9.11.0-P2/lib/isc/win32/socket.c --- bind-9.11.0-P1/lib/isc/win32/socket.c 2016-10-21 14:13:38.000000000 +0900 +++ bind-9.11.0-P2/lib/isc/win32/socket.c 2016-12-12 07:05:44.000000000 +0900 @@ -2514,14 +2514,16 @@ SocketIoThread(LPVOID ThreadContext) { request = lpo->request_type; - errstatus = 0; - if (!bSuccess) { + if (!bSuccess) + errstatus = GetLastError(); + else + errstatus = 0; + if (!bSuccess && errstatus != ERROR_MORE_DATA) { isc_result_t isc_result; /* * Did the I/O operation complete? */ - errstatus = GetLastError(); isc_result = isc__errno2result(errstatus); LOCK(&sock->lock);
差分多くて追っかけるの大変。
脆弱性4つもあるので、どれがどれだかわからない^q^;