File bind-CVE-2020-8616.patch of Package bind.29689
Index: bind-9.9.9-P1/lib/dns/adb.c
===================================================================
--- bind-9.9.9-P1.orig/lib/dns/adb.c
+++ bind-9.9.9-P1/lib/dns/adb.c
@@ -402,14 +402,13 @@ static void log_quota(dns_adbentry_t *en
*/
#define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
-#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
- != 0)
-#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
- != 0)
-#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
-#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
-#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
-#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
+#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) != 0)
+#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) != 0)
+#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
+#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
+#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
+#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
+#define FIND_NOFETCH(fn) (((fn)->options & DNS_ADBFIND_NOFETCH) != 0)
/*
* These are currently used on simple unsigned ints, so they are
@@ -3106,21 +3105,25 @@ dns_adb_createfind2(dns_adb_t *adb, isc_
* Listen to negative cache hints, and don't start
* another query.
*/
- if (NCACHE_RESULT(result) || AUTH_NX(result))
+ if (NCACHE_RESULT(result) || AUTH_NX(result)) {
goto fetch;
+ }
- if (!NAME_FETCH_V6(adbname))
+ if (!NAME_FETCH_V6(adbname)) {
wanted_fetches |= DNS_ADBFIND_INET6;
+ }
}
fetch:
if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
- (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
+ (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname))) {
have_address = ISC_TRUE;
- else
+ } else {
have_address = ISC_FALSE;
- if (wanted_fetches != 0 &&
- ! (FIND_AVOIDFETCHES(find) && have_address)) {
+ }
+ if (wanted_fetches != 0 && !(FIND_AVOIDFETCHES(find) && have_address) &&
+ !FIND_NOFETCH(find))
+ {
/*
* We're missing at least one address family. Either the
* caller hasn't instructed us to avoid fetches, or we don't
@@ -3128,8 +3131,9 @@ dns_adb_createfind2(dns_adb_t *adb, isc_
* be acceptable so we have to launch fetches.
*/
- if (FIND_STARTATZONE(find))
+ if (FIND_STARTATZONE(find)) {
start_at_zone = ISC_TRUE;
+ }
/*
* Start V4.
Index: bind-9.9.9-P1/lib/dns/include/dns/adb.h
===================================================================
--- bind-9.9.9-P1.orig/lib/dns/include/dns/adb.h
+++ bind-9.9.9-P1/lib/dns/include/dns/adb.h
@@ -211,6 +211,10 @@ struct dns_adbfind {
* lame for this query.
*/
#define DNS_ADBFIND_OVERQUOTA 0x00000400
+/*%
+ * Don't perform a fetch even if there are no address records available.
+ */
+#define DNS_ADBFIND_NOFETCH 0x00000800
/*%
* The answers to queries come back as a list of these.
Index: bind-9.9.9-P1/lib/dns/resolver.c
===================================================================
--- bind-9.9.9-P1.orig/lib/dns/resolver.c
+++ bind-9.9.9-P1/lib/dns/resolver.c
@@ -170,6 +170,14 @@
#define DEFAULT_MAX_QUERIES 50
#endif
+/*
+ * After NS_FAIL_LIMIT attempts to fetch a name server address,
+ * if the number of addresses in the NS RRset exceeds NS_RR_LIMIT,
+ * stop trying to fetch, in order to avoid wasting resources.
+ */
+#define NS_FAIL_LIMIT 4
+#define NS_RR_LIMIT 5
+
/* Number of hash buckets for zone counters */
#ifndef RES_DOMAIN_BUCKETS
#define RES_DOMAIN_BUCKETS 523
@@ -2733,7 +2741,7 @@ sort_finds(dns_adbfindlist_t *findlist)
static void
findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
unsigned int options, unsigned int flags, isc_stdtime_t now,
- isc_boolean_t *overquota, isc_boolean_t *need_alternate)
+ isc_boolean_t *overquota, isc_boolean_t *need_alternate, unsigned int *no_addresses)
{
dns_adbaddrinfo_t *ai;
dns_adbfind_t *find;
@@ -2826,7 +2834,12 @@ findname(fetchctx_t *fctx, dns_name_t *n
find->result_v6 != DNS_R_NXDOMAIN) ||
(res->dispatches6 == NULL &&
find->result_v4 != DNS_R_NXDOMAIN)))
+ {
*need_alternate = ISC_TRUE;
+ }
+ if (no_addresses != NULL) {
+ (*no_addresses)++;
+ }
} else {
#ifdef ENABLE_FETCHLIMIT
if ((find->options & DNS_ADBFIND_OVERQUOTA) != 0) {
@@ -2882,6 +2895,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_
#ifdef ENABLE_FETCHLIMIT
isc_boolean_t all_spilled = ISC_TRUE;
#endif /* ENABLE_FETCHLIMIT */
+ unsigned int no_addresses = 0;
FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
@@ -2955,7 +2969,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_
result = dns_name_dup(domain, fctx->mctx,
&fctx->domain);
if (result != ISC_R_SUCCESS)
+ {
return (result);
+ }
#ifdef ENABLE_FETCHLIMIT
result = fcount_incr(fctx, ISC_TRUE);
if (result != ISC_R_SUCCESS)
@@ -3042,10 +3058,17 @@ fctx_getaddresses(fetchctx_t *fctx, isc_
*/
result = dns_rdata_tostruct(&rdata, &ns, NULL);
if (result != ISC_R_SUCCESS)
+ {
continue;
+ }
+ if (no_addresses > NS_FAIL_LIMIT &&
+ dns_rdataset_count(&fctx->nameservers) > NS_RR_LIMIT)
+ {
+ stdoptions |= DNS_ADBFIND_NOFETCH;
+ }
findname(fctx, &ns.name, 0, stdoptions, 0, now,
- &overquota, &need_alternate);
+ &overquota, &need_alternate, &no_addresses);
#ifdef ENABLE_FETCHLIMIT
if (!overquota)
@@ -3056,7 +3079,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_
dns_rdata_freestruct(&ns);
}
if (result != ISC_R_NOMORE)
+ {
return (result);
+ }
/*
* Do we need to use 6 to 4?
@@ -3071,7 +3096,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_
if (!a->isaddress) {
findname(fctx, &a->_u._n.name, a->_u._n.port,
stdoptions, FCTX_ADDRINFO_FORWARDER,
- now, NULL, NULL);
+ now, NULL, NULL, NULL);
continue;
}
if (isc_sockaddr_pf(&a->_u.addr) != family)