diff --git a/Add-some-DBC-checks-in-dighost-fix-race-between-clea.patch b/Add-some-DBC-checks-in-dighost-fix-race-between-clea.patch deleted file mode 100644 index 64f56c5dc8d487353a09890e1390591454709ddc..0000000000000000000000000000000000000000 --- a/Add-some-DBC-checks-in-dighost-fix-race-between-clea.patch +++ /dev/null @@ -1,228 +0,0 @@ ---- a/bin/dig/dighost.c 2019-04-18 00:14:08.120000000 -0400 -+++ b/bin/dig/dighost_1.c 2019-04-18 02:34:32.947000000 -0400 -@@ -1822,9 +1822,9 @@ clear_query(dig_query_t *query) { - - debug("clear_query(%p)", query); - -- if (query->timer != NULL) -+ if (query->timer != NULL){ - isc_timer_detach(&query->timer); -- -+ } - if (query->waiting_senddone) { - debug("send_done not yet called"); - query->pending_free = true; -@@ -1833,13 +1833,15 @@ clear_query(dig_query_t *query) { - - lookup = query->lookup; - -- if (lookup->current_query == query) -+ if (lookup->current_query == query){ - lookup->current_query = NULL; -- -- if (ISC_LINK_LINKED(query, link)) -+ } -+ if (ISC_LINK_LINKED(query, link)){ - ISC_LIST_UNLINK(lookup->q, query, link); -- if (ISC_LINK_LINKED(query, clink)) -+ } -+ if (ISC_LINK_LINKED(query, clink)){ - ISC_LIST_UNLINK(lookup->connecting, query, clink); -+ } - if (ISC_LINK_LINKED(&query->recvbuf, link)) - ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf, - link); -@@ -1856,6 +1858,7 @@ clear_query(dig_query_t *query) { - isc_mempool_put(commctx, query->recvspace); - isc_buffer_invalidate(&query->recvbuf); - isc_buffer_invalidate(&query->lengthbuf); -+ query->magic = 0; - isc_mem_free(mctx, query); - } - -@@ -2807,13 +2810,14 @@ setup_lookup(dig_lookup_t *lookup) { - - for (serv = ISC_LIST_HEAD(lookup->my_server_list); - serv != NULL; -- serv = ISC_LIST_NEXT(serv, link)) { -+ serv = ISC_LIST_NEXT(serv, link)) -+ { - query = isc_mem_allocate(mctx, sizeof(dig_query_t)); -- if (query == NULL) -+ if (query == NULL){ - fatal("memory allocation failure in %s:%d", - __FILE__, __LINE__); -- debug("create query %p linked to lookup %p", -- query, lookup); -+ } -+ debug("create query %p linked to lookup %p", query, lookup); - query->lookup = lookup; - query->timer = NULL; - query->waiting_connect = false; -@@ -2838,9 +2842,9 @@ setup_lookup(dig_lookup_t *lookup) { - ISC_LIST_INIT(query->lengthlist); - query->sock = NULL; - query->recvspace = isc_mempool_get(commctx); -- if (query->recvspace == NULL) -+ if (query->recvspace == NULL){ - fatal("memory allocation failure"); -- -+ } - isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE); - isc_buffer_init(&query->lengthbuf, query->lengthspace, 2); - isc_buffer_init(&query->slbuf, query->slspace, 2); -@@ -2848,6 +2852,7 @@ setup_lookup(dig_lookup_t *lookup) { - - ISC_LINK_INIT(query, clink); - ISC_LINK_INIT(query, link); -+ query->magic = DIG_QUERY_MAGIC; - ISC_LIST_ENQUEUE(lookup->q, query, link); - } - -@@ -2856,9 +2861,10 @@ setup_lookup(dig_lookup_t *lookup) { - extrabytes = 0; - dighost_printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg, - true); -- if (lookup->stats) -+ if (lookup->stats){ - printf(";; QUERY SIZE: %u\n\n", - isc_buffer_usedlength(&lookup->renderbuf)); -+ } - } - return (true); - } -@@ -2893,20 +2899,26 @@ send_done(isc_task_t *_task, isc_event_t - } - - query = event->ev_arg; -+ REQUIRE(DIG_VALID_QUERY(query)); - query->waiting_senddone = false; - l = query->lookup; - -- if (l->ns_search_only && !l->trace_root && !l->tcp_mode) { -+ if (!query->pending_free && l->ns_search_only && -+ !l->trace_root && !l->tcp_mode) -+ { - debug("sending next, since searching"); - next = ISC_LIST_NEXT(query, link); -- if (next != NULL) -+ if (next != NULL){ - send_udp(next); -+ } - } - - isc_event_free(&event); - -- if (query->pending_free) -+ if (query->pending_free){ -+ query->magic = 0; - clear_query(query); -+ } - - check_next_lookup(l); - UNLOCK_LOOKUP; -@@ -2924,6 +2936,7 @@ cancel_lookup(dig_lookup_t *lookup) { - debug("cancel_lookup()"); - query = ISC_LIST_HEAD(lookup->q); - while (query != NULL) { -+ REQUIRE(DIG_VALID_QUERY(query)); - next = ISC_LIST_NEXT(query, link); - if (query->sock != NULL) { - isc_socket_cancel(query->sock, global_task, -@@ -2943,6 +2956,7 @@ bringup_timer(dig_query_t *query, unsign - dig_lookup_t *l; - unsigned int local_timeout; - isc_result_t result; -+ REQUIRE(DIG_VALID_QUERY(query)); - - debug("bringup_timer()"); - /* -@@ -3007,7 +3021,7 @@ send_tcp_connect(dig_query_t *query) { - isc_result_t result; - dig_query_t *next; - dig_lookup_t *l; -- -+ REQUIRE(DIG_VALID_QUERY(query)); - debug("send_tcp_connect(%p)", query); - - l = query->lookup; -@@ -3145,7 +3159,7 @@ send_udp(dig_query_t *query) { - isc_result_t result; - isc_buffer_t *sendbuf; - dig_query_t *next; -- -+ REQUIRE(DIG_VALID_QUERY(query)); - debug("send_udp(%p)", query); - - l = query->lookup; -@@ -3248,6 +3262,7 @@ connect_timeout(isc_task_t *task, isc_ev - - LOCK_LOOKUP; - query = event->ev_arg; -+ REQUIRE(DIG_VALID_QUERY(query)); - l = query->lookup; - isc_event_free(&event); - -@@ -3335,7 +3350,7 @@ tcp_length_done(isc_task_t *task, isc_ev - LOCK_LOOKUP; - sevent = (isc_socketevent_t *)event; - query = event->ev_arg; -- -+ REQUIRE(DIG_VALID_QUERY(query)); - recvcount--; - INSIST(recvcount >= 0); - -@@ -3412,7 +3427,7 @@ launch_next_query(dig_query_t *query, is - isc_result_t result; - dig_lookup_t *l; - isc_buffer_t *buffer; -- -+ REQUIRE(DIG_VALID_QUERY(query)); - INSIST(!free_now); - - debug("launch_next_query()"); -@@ -3491,7 +3506,7 @@ connect_done(isc_task_t *task, isc_event - LOCK_LOOKUP; - sevent = (isc_socketevent_t *)event; - query = sevent->ev_arg; -- -+ REQUIRE(DIG_VALID_QUERY(query)); - INSIST(query->waiting_connect); - - query->waiting_connect = false; -@@ -4460,6 +4475,7 @@ do_lookup(dig_lookup_t *lookup) { - lookup->pending = true; - query = ISC_LIST_HEAD(lookup->q); - if (query != NULL) { -+ REQUIRE(DIG_VALID_QUERY(query)); - if (lookup->tcp_mode) - send_tcp_connect(query); - else ---- a/bin/dig/include/dig/dig.h 2018-09-04 00:04:41.000000000 -0400 -+++ b/bin/dig/include/dig/dig_1.h 2019-04-18 02:36:44.313000000 -0400 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -90,6 +91,9 @@ typedef struct dig_message dig_message_t - #endif - typedef ISC_LIST(dig_server_t) dig_serverlist_t; - typedef struct dig_searchlist dig_searchlist_t; -+#define DIG_QUERY_MAGIC ISC_MAGIC('D','i','g','q') -+ -+#define DIG_VALID_QUERY(x) ISC_MAGIC_VALID((x), DIG_QUERY_MAGIC) - - /*% The dig_lookup structure */ - struct dig_lookup { -@@ -199,6 +203,7 @@ isc_boolean_t sigchase; - - /*% The dig_query structure */ - struct dig_query { -+ unsigned int magic; - dig_lookup_t *lookup; - bool waiting_connect, - pending_free, diff --git a/CVE-2020-8622.patch b/CVE-2020-8622.patch deleted file mode 100644 index 1abc50519334e1932fd70afe289769656d371c13..0000000000000000000000000000000000000000 --- a/CVE-2020-8622.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 6ed167ad0a647dff20c8cb08c944a7967df2d415 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Wed, 15 Jul 2020 16:07:51 +1000 -Subject: [PATCH] Always keep a copy of the message - -this allows it to be available even when dns_message_parse() -returns a error. ---- - lib/dns/message.c | 24 +++++++++++++----------- - 1 file changed, 13 insertions(+), 11 deletions(-) - -diff --git a/lib/dns/message.c b/lib/dns/message.c -index d9e341a09e..7c813a5cf6 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -1712,6 +1712,19 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, - msg->header_ok = 0; - msg->question_ok = 0; - -+ if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) { -+ isc_buffer_usedregion(&origsource, &msg->saved); -+ } else { -+ msg->saved.length = isc_buffer_usedlength(&origsource); -+ msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); -+ if (msg->saved.base == NULL) { -+ return (ISC_R_NOMEMORY); -+ } -+ memmove(msg->saved.base, isc_buffer_base(&origsource), -+ msg->saved.length); -+ msg->free_saved = 1; -+ } -+ - isc_buffer_remainingregion(source, &r); - if (r.length < DNS_MESSAGE_HEADERLEN) - return (ISC_R_UNEXPECTEDEND); -@@ -1787,17 +1800,6 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, - } - - truncated: -- if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) -- isc_buffer_usedregion(&origsource, &msg->saved); -- else { -- msg->saved.length = isc_buffer_usedlength(&origsource); -- msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); -- if (msg->saved.base == NULL) -- return (ISC_R_NOMEMORY); -- memmove(msg->saved.base, isc_buffer_base(&origsource), -- msg->saved.length); -- msg->free_saved = 1; -- } - - if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) - return (DNS_R_RECOVERABLE); --- -GitLab - diff --git a/CVE-2020-8623.patch b/CVE-2020-8623.patch deleted file mode 100644 index 384b73dd1dc0774c640a93213dfc4e496d144f2e..0000000000000000000000000000000000000000 --- a/CVE-2020-8623.patch +++ /dev/null @@ -1,398 +0,0 @@ -From 8d807cc21655eaa6e6a08afafeec3682c0f3f2ab Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= -Date: Tue, 21 Jul 2020 14:42:47 +0200 -Subject: [PATCH] Fix crash in pk11_numbits() when native-pkcs11 is used - -When pk11_numbits() is passed a user provided input that contains all -zeroes (via crafted DNS message), it would crash with assertion -failure. Fix that by properly handling such input. ---- - lib/dns/pkcs11dh_link.c | 15 ++++++- - lib/dns/pkcs11dsa_link.c | 8 +++- - lib/dns/pkcs11rsa_link.c | 79 +++++++++++++++++++++++++-------- - lib/isc/include/pk11/internal.h | 3 +- - lib/isc/pk11.c | 61 ++++++++++++++++--------- - 5 files changed, 121 insertions(+), 45 deletions(-) - -diff --git a/lib/dns/pkcs11dh_link.c b/lib/dns/pkcs11dh_link.c -index e2b60ea7c5..4cd8e32d60 100644 ---- a/lib/dns/pkcs11dh_link.c -+++ b/lib/dns/pkcs11dh_link.c -@@ -748,6 +748,7 @@ pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { - CK_BYTE *prime = NULL, *base = NULL, *pub = NULL; - CK_ATTRIBUTE *attr; - int special = 0; -+ unsigned int bits; - isc_result_t result; - - isc_buffer_remainingregion(data, &r); -@@ -852,7 +853,11 @@ pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { - pub = r.base; - isc_region_consume(&r, publen); - -- key->key_size = pk11_numbits(prime, plen_); -+ result = pk11_numbits(prime, plen_, &bits); -+ if (result != ISC_R_SUCCESS) { -+ goto cleanup; -+ } -+ key->key_size = bits; - - dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3); - if (dh->repr == NULL) -@@ -1012,6 +1017,7 @@ pkcs11dh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - dst_private_t priv; - isc_result_t ret; - int i; -+ unsigned int bits; - pk11_object_t *dh = NULL; - CK_ATTRIBUTE *attr; - isc_mem_t *mctx; -@@ -1082,7 +1088,12 @@ pkcs11dh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - attr = pk11_attribute_bytype(dh, CKA_PRIME); - INSIST(attr != NULL); -- key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ key->key_size = bits; - - return (ISC_R_SUCCESS); - -diff --git a/lib/dns/pkcs11dsa_link.c b/lib/dns/pkcs11dsa_link.c -index 12d707a112..24d4c149ff 100644 ---- a/lib/dns/pkcs11dsa_link.c -+++ b/lib/dns/pkcs11dsa_link.c -@@ -983,6 +983,7 @@ pkcs11dsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - dst_private_t priv; - isc_result_t ret; - int i; -+ unsigned int bits; - pk11_object_t *dsa = NULL; - CK_ATTRIBUTE *attr; - isc_mem_t *mctx = key->mctx; -@@ -1072,7 +1073,12 @@ pkcs11dsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - attr = pk11_attribute_bytype(dsa, CKA_PRIME); - INSIST(attr != NULL); -- key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ key->key_size = bits; - - return (ISC_R_SUCCESS); - -diff --git a/lib/dns/pkcs11rsa_link.c b/lib/dns/pkcs11rsa_link.c -index 096c1a8e91..1d10d26564 100644 ---- a/lib/dns/pkcs11rsa_link.c -+++ b/lib/dns/pkcs11rsa_link.c -@@ -332,6 +332,7 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, - key->key_alg == DST_ALG_RSASHA256 || - key->key_alg == DST_ALG_RSASHA512); - #endif -+ REQUIRE(maxbits <= RSA_MAX_PUBEXP_BITS); - - /* - * Reject incorrect RSA key lengths. -@@ -376,6 +377,7 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, - for (attr = pk11_attribute_first(rsa); - attr != NULL; - attr = pk11_attribute_next(rsa, attr)) -+ { - switch (attr->type) { - case CKA_MODULUS: - INSIST(keyTemplate[5].type == attr->type); -@@ -396,12 +398,16 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, - memmove(keyTemplate[6].pValue, attr->pValue, - attr->ulValueLen); - keyTemplate[6].ulValueLen = attr->ulValueLen; -- if (pk11_numbits(attr->pValue, -- attr->ulValueLen) > maxbits && -- maxbits != 0) -+ unsigned int bits; -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, -+ &bits); -+ if (ret != ISC_R_SUCCESS || -+ (bits > maxbits && maxbits != 0)) { - DST_RET(DST_R_VERIFYFAILURE); -+ } - break; - } -+ } - pk11_ctx->object = CK_INVALID_HANDLE; - pk11_ctx->ontoken = false; - PK11_RET(pkcs_C_CreateObject, -@@ -1072,6 +1078,7 @@ pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) { - keyTemplate[5].ulValueLen = attr->ulValueLen; - break; - case CKA_PUBLIC_EXPONENT: -+ unsigned int bits; - INSIST(keyTemplate[6].type == attr->type); - keyTemplate[6].pValue = isc_mem_get(dctx->mctx, - attr->ulValueLen); -@@ -1080,10 +1087,12 @@ pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) { - memmove(keyTemplate[6].pValue, attr->pValue, - attr->ulValueLen); - keyTemplate[6].ulValueLen = attr->ulValueLen; -- if (pk11_numbits(attr->pValue, -- attr->ulValueLen) -- > RSA_MAX_PUBEXP_BITS) -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, -+ &bits); -+ if (ret != ISC_R_SUCCESS || bits > RSA_MAX_PUBEXP_BITS) -+ { - DST_RET(DST_R_VERIFYFAILURE); -+ } - break; - } - pk11_ctx->object = CK_INVALID_HANDLE; -@@ -1461,6 +1470,8 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - CK_BYTE *exponent = NULL, *modulus = NULL; - CK_ATTRIBUTE *attr; - unsigned int length; -+ unsigned int bits; -+ isc_result_t ret = ISC_R_SUCCESS; - - isc_buffer_remainingregion(data, &r); - if (r.length == 0) -@@ -1478,9 +1489,7 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - - if (e_bytes == 0) { - if (r.length < 2) { -- isc_safe_memwipe(rsa, sizeof(*rsa)); -- isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -- return (DST_R_INVALIDPUBLICKEY); -+ DST_RET(DST_R_INVALIDPUBLICKEY); - } - e_bytes = (*r.base) << 8; - isc_region_consume(&r, 1); -@@ -1489,16 +1498,18 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - } - - if (r.length < e_bytes) { -- isc_safe_memwipe(rsa, sizeof(*rsa)); -- isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -- return (DST_R_INVALIDPUBLICKEY); -+ DST_RET(DST_R_INVALIDPUBLICKEY); - } - exponent = r.base; - isc_region_consume(&r, e_bytes); - modulus = r.base; - mod_bytes = r.length; - -- key->key_size = pk11_numbits(modulus, mod_bytes); -+ ret = pk11_numbits(modulus, mod_bytes, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ key->key_size = bits; - - isc_buffer_forward(data, length); - -@@ -1548,9 +1559,12 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - rsa->repr, - rsa->attrcnt * sizeof(*attr)); - } -+ ret = ISC_R_NOMEMORY; -+ -+ err: - isc_safe_memwipe(rsa, sizeof(*rsa)); - isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -- return (ISC_R_NOMEMORY); -+ return (ret); - } - - static isc_result_t -@@ -1729,6 +1743,7 @@ pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label, - pk11_object_t *pubrsa; - pk11_context_t *pk11_ctx = NULL; - isc_result_t ret; -+ unsigned int bits; - - if (label == NULL) - return (DST_R_NOENGINE); -@@ -1815,7 +1830,11 @@ pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label, - - attr = pk11_attribute_bytype(rsa, CKA_MODULUS); - INSIST(attr != NULL); -- key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ key->key_size = bits; - - return (ISC_R_SUCCESS); - -@@ -1901,6 +1920,7 @@ pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - CK_ATTRIBUTE *attr; - isc_mem_t *mctx = key->mctx; - const char *engine = NULL, *label = NULL; -+ unsigned int bits; - - /* read private key file */ - ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); -@@ -2044,12 +2064,22 @@ pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - attr = pk11_attribute_bytype(rsa, CKA_MODULUS); - INSIST(attr != NULL); -- key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ key->key_size = bits; - - attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); - INSIST(attr != NULL); -- if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS) -+ -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ if (bits > RSA_MAX_PUBEXP_BITS) { - DST_RET(ISC_R_RANGE); -+ } - - dst__privstruct_free(&priv, mctx); - isc_safe_memwipe(&priv, sizeof(priv)); -@@ -2084,6 +2114,7 @@ pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label, - pk11_context_t *pk11_ctx = NULL; - isc_result_t ret; - unsigned int i; -+ unsigned int bits; - - UNUSED(pin); - -@@ -2178,12 +2209,22 @@ pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label, - - attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); - INSIST(attr != NULL); -- if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS) -+ -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ if (bits > RSA_MAX_PUBEXP_BITS) { - DST_RET(ISC_R_RANGE); -+ } - - attr = pk11_attribute_bytype(rsa, CKA_MODULUS); - INSIST(attr != NULL); -- key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits); -+ if (ret != ISC_R_SUCCESS) { -+ goto err; -+ } -+ key->key_size = bits; - - pk11_return_session(pk11_ctx); - isc_safe_memwipe(pk11_ctx, sizeof(*pk11_ctx)); -diff --git a/lib/isc/include/pk11/internal.h b/lib/isc/include/pk11/internal.h -index aa8907ab08..7cc8ec812b 100644 ---- a/lib/isc/include/pk11/internal.h -+++ b/lib/isc/include/pk11/internal.h -@@ -25,7 +25,8 @@ void pk11_mem_put(void *ptr, size_t size); - - CK_SLOT_ID pk11_get_best_token(pk11_optype_t optype); - --unsigned int pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt); -+isc_result_t -+pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt, unsigned int *bits); - - CK_ATTRIBUTE *pk11_attribute_first(const pk11_object_t *obj); - -diff --git a/lib/isc/pk11.c b/lib/isc/pk11.c -index 012afd968a..4e4052044b 100644 ---- a/lib/isc/pk11.c -+++ b/lib/isc/pk11.c -@@ -962,13 +962,15 @@ pk11_get_best_token(pk11_optype_t optype) { - return (token->slotid); - } - --unsigned int --pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) { -+isc_result_t -+pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt, unsigned int *bits) { - unsigned int bitcnt, i; - CK_BYTE top; - -- if (bytecnt == 0) -- return (0); -+ if (bytecnt == 0) { -+ *bits = 0; -+ return (ISC_R_SUCCESS); -+ } - bitcnt = bytecnt * 8; - for (i = 0; i < bytecnt; i++) { - top = data[i]; -@@ -976,26 +978,41 @@ pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) { - bitcnt -= 8; - continue; - } -- if (top & 0x80) -- return (bitcnt); -- if (top & 0x40) -- return (bitcnt - 1); -- if (top & 0x20) -- return (bitcnt - 2); -- if (top & 0x10) -- return (bitcnt - 3); -- if (top & 0x08) -- return (bitcnt - 4); -- if (top & 0x04) -- return (bitcnt - 5); -- if (top & 0x02) -- return (bitcnt - 6); -- if (top & 0x01) -- return (bitcnt - 7); -+ if (top & 0x80) { -+ *bits = bitcnt; -+ return (ISC_R_SUCCESS); -+ } -+ if (top & 0x40) { -+ *bits = bitcnt - 1; -+ return (ISC_R_SUCCESS); -+ } -+ if (top & 0x20) { -+ *bits = bitcnt - 2; -+ return (ISC_R_SUCCESS); -+ } -+ if (top & 0x10) { -+ *bits = bitcnt - 3; -+ return (ISC_R_SUCCESS); -+ } -+ if (top & 0x08) { -+ *bits = bitcnt - 4; -+ return (ISC_R_SUCCESS); -+ } -+ if (top & 0x04) { -+ *bits = bitcnt - 5; -+ return (ISC_R_SUCCESS); -+ } -+ if (top & 0x02) { -+ *bits = bitcnt - 6; -+ return (ISC_R_SUCCESS); -+ } -+ if (top & 0x01) { -+ *bits = bitcnt - 7; -+ return (ISC_R_SUCCESS); -+ } - break; - } -- INSIST(0); -- ISC_UNREACHABLE(); -+ return (ISC_R_RANGE); - } - - CK_ATTRIBUTE * --- -GitLab - diff --git a/CVE-2020-8624.patch b/CVE-2020-8624.patch deleted file mode 100644 index 54e82f158f41111534d8abcf5eed829af3130d5d..0000000000000000000000000000000000000000 --- a/CVE-2020-8624.patch +++ /dev/null @@ -1,29 +0,0 @@ -From e4cccf9668c7adee4724a7649ec64685f82c8677 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Wed, 29 Jul 2020 23:36:03 +1000 -Subject: [PATCH] Update-policy 'subdomain' was incorrectly treated as - 'zonesub' - -resulting in names outside the specified subdomain having the wrong -restrictions for the given key. ---- - bin/named/zoneconf.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c -index 55f191bad4..b77a07c14a 100644 ---- a/bin/named/zoneconf.c -+++ b/bin/named/zoneconf.c -@@ -239,7 +239,8 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, - - str = cfg_obj_asstring(matchtype); - CHECK(dns_ssu_mtypefromstring(str, &mtype)); -- if (mtype == dns_ssumatchtype_subdomain) { -+ if (mtype == dns_ssumatchtype_subdomain && -+ strcasecmp(str, "zonesub") == 0) { - usezone = true; - } - --- -GitLab - diff --git a/CVE-2020-8625.patch b/CVE-2020-8625.patch deleted file mode 100644 index 454d17ef9d76564c09c2b0cf9d9a3a498c3feb74..0000000000000000000000000000000000000000 --- a/CVE-2020-8625.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/dns/spnego.c b/lib/dns/spnego.c -index dea108bad05..13cf15d7404 100644 ---- a/lib/dns/spnego.c -+++ b/lib/dns/spnego.c -@@ -877,7 +877,7 @@ der_get_oid(const unsigned char *p, size_t len, oid *data, size_t *size) { - return (ASN1_OVERRUN); - } - -- data->components = malloc(len * sizeof(*data->components)); -+ data->components = malloc((len + 1) * sizeof(*data->components)); - if (data->components == NULL) { - return (ENOMEM); - } diff --git a/Changes.md b/Changes.md new file mode 100644 index 0000000000000000000000000000000000000000..66610342d0e94a868595068956b0ee20c31af0d9 --- /dev/null +++ b/Changes.md @@ -0,0 +1,43 @@ +# Significant Changes in BIND9 package + +## BIND 9.16 + +### New features + +- *libuv* is used for network subsystem as a mandatory dependency +- *dnssec-policy* support in named.conf is introduced, providing a a key and signing policy + ([KASP](https://gitlab.isc.org/isc-projects/bind9/-/wikis/DNSSEC-Key-and-Signing-Policy-(KASP))) +- *trusted-keys* and *managed-keys* are deprecated, replaced by *trust-anchors* +- *trust-anchors* support also anchor in a *DS* format, in addition to *DNSKEY* format +- **dig, mdig** and **delv** support **+yaml** parameter to print detailed machine parseable output + +### Feature changes + +- Static trust anchor and *dnssec-validation auto;* are incompatible and cause fatal error, when used together. +- *DS* and *CDS* now generates only SHA-256 digest, SHA-1 is no longer generated by default +- SipHash 2-4 DNS Cookie ([RFC 7873](https://www.rfc-editor.org/rfc/rfc7873.html) is now default). + Only AES alternative algorithm is kept, HMAC-SHA cookie support were removed. +- **dnssec-signzone** and **dnssec-verify** commands print output to stdout, *-q* parameter can silence them + +### Features removed + +- *dnssec-enable* option is obsolete, DNSSEC support is always enabled +- *dnssec-lookaside* option is deprecated and support for it removed from all tools +- *cleaning-interval* option is removed + +### Upstream release notes + +- [9.16.10 notes](https://downloads.isc.org/isc/bind9/9.16.10/doc/arm/html/notes.html#notes-for-bind-9-16-10) +- [9.16.0 notes](https://downloads.isc.org/isc/bind9/9.16.0/doc/arm/html/notes.html#notes-for-bind-9-16-0) + +## BIND 9.14 + +- single thread support removed. Cannot provide *bind-export-libs* for DHCP +- *lwres* support completely removed. Both daemon and library +- common parts of daemon moved into *libns* shared library +- introduced plugin for filtering aaaa responses +- some SDB utilities no longer supported + +### Upstream release notes + +- [9.14.7 notes](https://downloads.isc.org/isc/bind9/9.14.7/RELEASE-NOTES-bind-9.14.7.html) diff --git a/Fix_the_difference_at_the_macro_definition_using_clock_gettime_instead_of_gettimeofda.patch b/Fix_the_difference_at_the_macro_definition_using_clock_gettime_instead_of_gettimeofda.patch deleted file mode 100644 index de4837fb6a50a71364bc20ad295a08de33b61825..0000000000000000000000000000000000000000 --- a/Fix_the_difference_at_the_macro_definition_using_clock_gettime_instead_of_gettimeofda.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 33bf90331b48c7378316c141e5e9acb2862dd0ac Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= -Date: Sun, 9 Dec 2018 00:41:21 +0100 -Subject: [PATCH] use clock_gettime() instead of gettimeofday() for isc_itme - functions - ---- - lib/isc/unix/time.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c -index 9828250..c2ae60e 100644 ---- a/lib/isc/unix/time.c -+++ b/lib/isc/unix/time.c -@@ -38,7 +38,11 @@ - #define NS_PER_MS 1000000 /*%< Nanoseconds per millisecond. */ - #define US_PER_S 1000000 /*%< Microseconds per second. */ - --#define CLOCKSOURCE CLOCK_MONOTONIC -+#ifdef CLOCK_REALTIME_COARSE -+#define CLOCKSOURCE CLOCK_REALTIME_COARSE -+#else -+#define CLOCKSOURCE CLOCK_REALTIME -+#endif - - /*% - *** Intervals --- -2.23.0 - diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 5e0a40041c06568d00ab23397a0da785caf958e3..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# bind - -#### Description -{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.sdb_pgsql b/README.sdb_pgsql deleted file mode 100644 index c10c29468907a3a897126e79a11863f7f6a3dc70..0000000000000000000000000000000000000000 --- a/README.sdb_pgsql +++ /dev/null @@ -1,79 +0,0 @@ - PGSQL BIND SDB driver - -The postgresql BIND SDB driver is of experimental status and should not be -used for production systems. - -Usage: - -o Use the named_sdb process ( put ENABLE_SDB=yes in /etc/sysconfig/named ) - -o Edit your named.conf to contain a database zone, eg. : - -zone "pgdb.net." IN { - type master; - database "pgsql bind pgdb localhost pguser pgpasswd"; - # ^- DB name ^-Table ^-host ^-user ^-password -}; - -o Create the database zone table - The table must contain the columns "name", "rdtype", and "rdata", and - is expected to contain a properly constructed zone. The program "zonetodb" - creates such a table. - - zonetodb usage: - - zonetodb origin file dbname dbtable - - where - origin : zone origin, eg "pgdb.net." - file : master zone database file, eg. pgdb.net.db - dbname : name of postgresql database - dbtable: name of table in database - - Eg. to import this zone in the file 'pgdb.net.db' into the 'bind' database - 'pgdb' table: - ---- -#pgdb.net.db: -$TTL 1H -@ SOA localhost. root.localhost. ( 1 - 3H - 1H - 1W - 1H ) - NS localhost. -host1 A 192.168.2.1 -host2 A 192.168.2.2 -host3 A 192.168.2.3 -host4 A 192.168.2.4 -host5 A 192.168.2.5 -host6 A 192.168.2.6 -host7 A 192.168.2.7 ---- - -Issue this command as the pgsql user authorized to update the bind database: - -# zonetodb pgdb.net. pgdb.net.db bind pgdb - -will create / update the pgdb table in the 'bind' db: - -$ psql -dbind -c 'select * from pgdb;' - name | ttl | rdtype | rdata -----------------+------+--------+----------------------------------------------------- - pgdb.net | 3600 | SOA | localhost. root.localhost. 1 10800 3600 604800 3600 - pgdb.net | 3600 | NS | localhost. - host1.pgdb.net | 3600 | A | 192.168.2.1 - host2.pgdb.net | 3600 | A | 192.168.2.2 - host3.pgdb.net | 3600 | A | 192.168.2.3 - host4.pgdb.net | 3600 | A | 192.168.2.4 - host5.pgdb.net | 3600 | A | 192.168.2.5 - host6.pgdb.net | 3600 | A | 192.168.2.6 - host7.pgdb.net | 3600 | A | 192.168.2.7 -(9 rows) - -I've tested exactly the above configuration with bind-sdb-9.3.1+ and it works OK. - -NOTE: If you use pgsqldb SDB, ensure the postgresql service is started before the named - service . - -USE AT YOUR OWN RISK! diff --git a/Use-clock_gettime-instead-of-gettimeofday.patch b/Use-clock_gettime-instead-of-gettimeofday.patch deleted file mode 100644 index bfe25606fc213aa517a8417673ba716c4adef74d..0000000000000000000000000000000000000000 --- a/Use-clock_gettime-instead-of-gettimeofday.patch +++ /dev/null @@ -1,161 +0,0 @@ -diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c -index f06d31a5508c2d3f7227063c21d9d4563789e72a..da25e5bf8e07639c8f70420a5c3f3c98a36a0548 100644 ---- a/lib/isc/unix/time.c -+++ b/lib/isc/unix/time.c -@@ -36,16 +36,7 @@ - #define NS_PER_MS 1000000 /*%< Nanoseconds per millisecond. */ - #define US_PER_S 1000000 /*%< Microseconds per second. */ - --/* -- * All of the INSIST()s checks of nanoseconds < NS_PER_S are for -- * consistency checking of the type. In lieu of magic numbers, it -- * is the best we've got. The check is only performed on functions which -- * need an initialized type. -- */ -- --#ifndef ISC_FIX_TV_USEC --#define ISC_FIX_TV_USEC 1 --#endif -+#define CLOCKSOURCE CLOCK_MONOTONIC - - /*% - *** Intervals -@@ -54,32 +49,6 @@ - static const isc_interval_t zero_interval = { 0, 0 }; - const isc_interval_t * const isc_interval_zero = &zero_interval; - --#if ISC_FIX_TV_USEC --static inline void --fix_tv_usec(struct timeval *tv) { -- bool fixed = false; -- -- if (tv->tv_usec < 0) { -- fixed = true; -- do { -- tv->tv_sec -= 1; -- tv->tv_usec += US_PER_S; -- } while (tv->tv_usec < 0); -- } else if (tv->tv_usec >= US_PER_S) { -- fixed = true; -- do { -- tv->tv_sec += 1; -- tv->tv_usec -= US_PER_S; -- } while (tv->tv_usec >=US_PER_S); -- } -- /* -- * Call syslog directly as was are called from the logging functions. -- */ -- if (fixed) -- (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected"); --} --#endif -- - void - isc_interval_set(isc_interval_t *i, - unsigned int seconds, unsigned int nanoseconds) -@@ -141,76 +110,52 @@ isc_time_isepoch(const isc_time_t *t) { - - isc_result_t - isc_time_now(isc_time_t *t) { -- struct timeval tv; -+ struct timespec ts; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(t != NULL); - -- if (gettimeofday(&tv, NULL) == -1) { -+ if (clock_gettime(CLOCKSOURCE, &ts) == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf); - return (ISC_R_UNEXPECTED); - } - -- /* -- * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not, -- * then this test will generate warnings for platforms on which it is -- * unsigned. In any event, the chances of any of these problems -- * happening are pretty much zero, but since the libisc library ensures -- * certain things to be true ... -- */ --#if ISC_FIX_TV_USEC -- fix_tv_usec(&tv); -- if (tv.tv_sec < 0) -- return (ISC_R_UNEXPECTED); --#else -- if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S) -+ if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec >= NS_PER_S) { - return (ISC_R_UNEXPECTED); --#endif -+ } - - /* - * Ensure the tv_sec value fits in t->seconds. - */ -- if (sizeof(tv.tv_sec) > sizeof(t->seconds) && -- ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U) -+ if (sizeof(ts.tv_sec) > sizeof(t->seconds) && -+ ((ts.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U) - return (ISC_R_RANGE); - -- t->seconds = tv.tv_sec; -- t->nanoseconds = tv.tv_usec * NS_PER_US; -+ t->seconds = ts.tv_sec; -+ t->nanoseconds = ts.tv_nsec; - - return (ISC_R_SUCCESS); - } - - isc_result_t - isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) { -- struct timeval tv; -+ struct timespec ts; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(t != NULL); - REQUIRE(i != NULL); - INSIST(i->nanoseconds < NS_PER_S); - -- if (gettimeofday(&tv, NULL) == -1) { -+ if (clock_gettime(CLOCKSOURCE, &ts) == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf); - return (ISC_R_UNEXPECTED); - } - -- /* -- * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not, -- * then this test will generate warnings for platforms on which it is -- * unsigned. In any event, the chances of any of these problems -- * happening are pretty much zero, but since the libisc library ensures -- * certain things to be true ... -- */ --#if ISC_FIX_TV_USEC -- fix_tv_usec(&tv); -- if (tv.tv_sec < 0) -- return (ISC_R_UNEXPECTED); --#else -- if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S) -+ if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec >= NS_PER_S) { - return (ISC_R_UNEXPECTED); --#endif -+ } - - /* - * Ensure the resulting seconds value fits in the size of an -@@ -218,12 +163,12 @@ isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) { - * note that even if both values == INT_MAX, then when added - * and getting another 1 added below the result is UINT_MAX.) - */ -- if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) && -- ((long long)tv.tv_sec + i->seconds > UINT_MAX)) -+ if ((ts.tv_sec > INT_MAX || i->seconds > INT_MAX) && -+ ((long long)ts.tv_sec + i->seconds > UINT_MAX)) - return (ISC_R_RANGE); - -- t->seconds = tv.tv_sec + i->seconds; -- t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds; -+ t->seconds = ts.tv_sec + i->seconds; -+ t->nanoseconds = ts.tv_nsec + i->nanoseconds; - if (t->nanoseconds >= NS_PER_S) { - t->seconds++; - t->nanoseconds -= NS_PER_S; diff --git a/backport-0001-Do-not-convert-ISC_R_NOSPACE-to-DNS_R_SERVFAIL-too-e.patch b/backport-0001-Do-not-convert-ISC_R_NOSPACE-to-DNS_R_SERVFAIL-too-e.patch new file mode 100644 index 0000000000000000000000000000000000000000..b89d8630bcedab664340952ca1bfecaa98b206ad --- /dev/null +++ b/backport-0001-Do-not-convert-ISC_R_NOSPACE-to-DNS_R_SERVFAIL-too-e.patch @@ -0,0 +1,39 @@ +From 4ace37bf7386e73af1d295d206b101c27a9edbad Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Wed, 24 Nov 2021 11:03:19 +1100 +Subject: [PATCH] Do not convert ISC_R_NOSPACE to DNS_R_SERVFAIL too early + +The parsing loop needs to process ISC_R_NOSPACE to properly +size the buffer. If result is still ISC_R_NOSPACE at the end +of the parsing loop set result to DNS_R_SERVFAIL. + +(cherry picked from commit 08f1cba096243cd14041731b7ea1ad45e54e87b0) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/4ace37bf7386e73af1d295d206b101c27a9edbad +--- + lib/dns/sdlz.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c +index c8a615a0f3..0b46fb9efd 100644 +--- a/lib/dns/sdlz.c ++++ b/lib/dns/sdlz.c +@@ -1875,7 +1875,6 @@ dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, + mctx, rdatabuf, &lookup->callbacks); + if (result != ISC_R_SUCCESS) { + isc_buffer_free(&rdatabuf); +- result = DNS_R_SERVFAIL; + } + if (size >= 65535) { + break; +@@ -1887,6 +1886,7 @@ dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, + } while (result == ISC_R_NOSPACE); + + if (result != ISC_R_SUCCESS) { ++ result = DNS_R_SERVFAIL; + goto failure; + } + +-- +2.23.0 + diff --git a/backport-0001-Exercise-ISC_R_NOSPACE-path-in-dns_sdlz_putrr.patch b/backport-0001-Exercise-ISC_R_NOSPACE-path-in-dns_sdlz_putrr.patch new file mode 100644 index 0000000000000000000000000000000000000000..8c378387f760b3eb4f00aa9c72b04e36521e745d --- /dev/null +++ b/backport-0001-Exercise-ISC_R_NOSPACE-path-in-dns_sdlz_putrr.patch @@ -0,0 +1,82 @@ +From bf1eaf46611bdbfcc2a6f6f77871eebf8351a629 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 25 Nov 2021 13:16:56 +1100 +Subject: [PATCH] Exercise ISC_R_NOSPACE path in dns_sdlz_putrr + +Use relative names when adding SOA record and a long domain +name to create SOA RR where the wire format is longer than +the initial buffer allocation in dns_sdlz_putrr. + +(cherry picked from commit 6dc524860622277bd24fe17d4a82454b30f5f1b5) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/bf1eaf46611bdbfcc2a6f6f77871eebf8351a629 +--- + bin/tests/system/dlzexternal/driver.c | 23 +++++++++---------- + bin/tests/system/dlzexternal/ns1/dlzs.conf.in | 5 ++++ + 2 files changed, 16 insertions(+), 12 deletions(-) + +diff --git a/bin/tests/system/dlzexternal/driver.c b/bin/tests/system/dlzexternal/driver.c +index 26da9c5deb..9c8ed0080f 100644 +--- a/bin/tests/system/dlzexternal/driver.c ++++ b/bin/tests/system/dlzexternal/driver.c +@@ -238,10 +238,9 @@ dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, + struct dlz_example_data *state; + const char *helper_name; + va_list ap; +- char soa_data[1024]; +- const char *extra; ++ char soa_data[sizeof("@ hostmaster.root 123 900 600 86400 3600")]; + isc_result_t result; +- int n; ++ size_t n; + + UNUSED(dlzname); + +@@ -275,19 +274,19 @@ dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, + sprintf(state->zone_name, "%s.", argv[1]); + } + ++ /* ++ * Use relative names to trigger ISC_R_NOSPACE in dns_sdlz_putrr. ++ */ + if (strcmp(state->zone_name, ".") == 0) { +- extra = ".root"; ++ n = strlcpy(soa_data, ++ "@ hostmaster.root 123 900 600 86400 3600", ++ sizeof(soa_data)); + } else { +- extra = "."; ++ n = strlcpy(soa_data, "@ hostmaster 123 900 600 86400 3600", ++ sizeof(soa_data)); + } + +- n = sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600", +- state->zone_name, extra, state->zone_name); +- +- if (n < 0) { +- CHECK(ISC_R_FAILURE); +- } +- if ((unsigned)n >= sizeof(soa_data)) { ++ if (n >= sizeof(soa_data)) { + CHECK(ISC_R_NOSPACE); + } + +diff --git a/bin/tests/system/dlzexternal/ns1/dlzs.conf.in b/bin/tests/system/dlzexternal/ns1/dlzs.conf.in +index 07bf329b50..c679498118 100644 +--- a/bin/tests/system/dlzexternal/ns1/dlzs.conf.in ++++ b/bin/tests/system/dlzexternal/ns1/dlzs.conf.in +@@ -21,6 +21,11 @@ dlz "example three" { + database "dlopen ../driver.@SO@ example.org"; + }; + ++dlz "example four" { ++ // Long zone name to trigger ISC_R_NOSPACE in dns_sdlz_putrr. ++ database "dlopen ../driver.@SO@ 123456789.123456789.123456789.123456789.123456789.example.foo"; ++}; ++ + dlz "unsearched1" { + database "dlopen ../driver.@SO@ other.nil"; + search no; +-- +2.23.0 + diff --git a/backport-0002-Add-a-regression-test.patch b/backport-0002-Add-a-regression-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..db07bd6b1da3d34f6e7040a57a1bf162a102914d --- /dev/null +++ b/backport-0002-Add-a-regression-test.patch @@ -0,0 +1,153 @@ +From c243daf8395bf8406f6697dde5ba62a25d188a1b Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Mon, 11 Oct 2021 13:01:20 -0700 +Subject: [PATCH] Add a regression test + +Reconfigure the server without catalog-zone configuration, and then +put it back and reconfigure again, to confirm that there's no crash. + +(cherry picked from commit bb411af31dd78ceda7a16f7ecfab483fb3746af9) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/c243daf8395bf8406f6697dde5ba62a25d188a1b +--- + .../ns2/{named.conf.in => named1.conf.in} | 0 + bin/tests/system/catz/ns2/named2.conf.in | 60 +++++++++++++++++++ + bin/tests/system/catz/setup.sh | 2 +- + bin/tests/system/catz/tests.sh | 16 ++++- + 4 files changed, 74 insertions(+), 4 deletions(-) + rename bin/tests/system/catz/ns2/{named.conf.in => named1.conf.in} (100%) + create mode 100644 bin/tests/system/catz/ns2/named2.conf.in + +diff --git a/bin/tests/system/catz/ns2/named.conf.in b/bin/tests/system/catz/ns2/named1.conf.in +similarity index 100% +rename from bin/tests/system/catz/ns2/named.conf.in +rename to bin/tests/system/catz/ns2/named1.conf.in +diff --git a/bin/tests/system/catz/ns2/named2.conf.in b/bin/tests/system/catz/ns2/named2.conf.in +new file mode 100644 +index 0000000000..fcd99ca0d4 +--- /dev/null ++++ b/bin/tests/system/catz/ns2/named2.conf.in +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ * ++ * See the COPYRIGHT file distributed with this work for additional ++ * information regarding copyright ownership. ++ */ ++ ++include "../../common/rndc.key"; ++ ++controls { ++ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; ++}; ++ ++options { ++ query-source address 10.53.0.2; ++ notify-source 10.53.0.2; ++ transfer-source 10.53.0.2; ++ port @PORT@; ++ pid-file "named.pid"; ++ listen-on { 10.53.0.2; }; ++ listen-on-v6 { fd92:7065:b8e:ffff::2; }; ++ notify no; ++ recursion no; ++ serial-query-rate 100; ++ # removed catalog-zone option, otherwise this is ++ # identical to named1.conf.in ++}; ++ ++zone "catalog1.example" { ++ type secondary; ++ file "catalog1.example.db"; ++ primaries { 10.53.0.1; }; ++}; ++ ++zone "catalog2.example" { ++ type secondary; ++ file "catalog2.example.db"; ++ primaries { 10.53.0.3; }; ++}; ++ ++zone "catalog3.example" { ++ type secondary; ++ file "catalog3.example.db"; ++ primaries { 10.53.0.1; }; ++}; ++ ++zone "catalog4.example" { ++ type secondary; ++ file "catalog4.example.db"; ++ primaries { 10.53.0.1; }; ++}; ++ ++key tsig_key. { ++ secret "LSAnCU+Z"; ++ algorithm hmac-md5; ++}; +diff --git a/bin/tests/system/catz/setup.sh b/bin/tests/system/catz/setup.sh +index 960cffe9a7..e23ea4f058 100644 +--- a/bin/tests/system/catz/setup.sh ++++ b/bin/tests/system/catz/setup.sh +@@ -15,7 +15,7 @@ SYSTEMTESTTOP=.. + $SHELL clean.sh + + copy_setports ns1/named.conf.in ns1/named.conf +-copy_setports ns2/named.conf.in ns2/named.conf ++copy_setports ns2/named1.conf.in ns2/named.conf + copy_setports ns3/named.conf.in ns3/named.conf + + cp -f ns1/catalog.example.db.in ns1/catalog1.example.db +diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh +index c443b739ff..cd2084e59a 100644 +--- a/bin/tests/system/catz/tests.sh ++++ b/bin/tests/system/catz/tests.sh +@@ -1179,7 +1179,7 @@ status=$((status+ret)) + n=$((n+1)) + echo_i "reconfiguring secondary - adding catalog4 catalog zone ($n)" + ret=0 +-sed -e "s/^#T1//g" < ns2/named.conf.in > ns2/named.conf.tmp ++sed -e "s/^#T1//g" < ns2/named1.conf.in > ns2/named.conf.tmp + copy_setports ns2/named.conf.tmp ns2/named.conf + rndccmd 10.53.0.2 reconfig || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi +@@ -1210,7 +1210,7 @@ status=$((status+ret)) + n=$((n+1)) + echo_i "reconfiguring secondary - removing catalog4 catalog zone, adding non-existent catalog5 catalog zone ($n)" + ret=0 +-sed -e "s/^#T2//" < ns2/named.conf.in > ns2/named.conf.tmp ++sed -e "s/^#T2//" < ns2/named1.conf.in > ns2/named.conf.tmp + copy_setports ns2/named.conf.tmp ns2/named.conf + $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > /dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi +@@ -1219,7 +1219,7 @@ status=$((status+ret)) + n=$((n+1)) + echo_i "reconfiguring secondary - removing non-existent catalog5 catalog zone ($n)" + ret=0 +-copy_setports ns2/named.conf.in ns2/named.conf ++copy_setports ns2/named1.conf.in ns2/named.conf + rndccmd 10.53.0.2 reconfig || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status+ret)) +@@ -1730,5 +1730,15 @@ wait_for_no_soa @10.53.0.2 dom16.example. dig.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status+ret)) + ++n=$((n+1)) ++echo_i "checking that reconfig can delete and restore catalog zone configuration ($n)" ++ret=0 ++copy_setports ns2/named2.conf.in ns2/named.conf ++rndccmd 10.53.0.2 reconfig || ret=1 ++copy_setports ns2/named1.conf.in ns2/named.conf ++rndccmd 10.53.0.2 reconfig || ret=1 ++if [ $ret -ne 0 ]; then echo_i "failed"; fi ++status=$((status+ret)) ++ + echo_i "exit status: $status" + [ $status -eq 0 ] || exit 1 +-- +2.23.0 + diff --git a/backport-0002-Fix-catalog-zone-reconfiguration-crash.patch b/backport-0002-Fix-catalog-zone-reconfiguration-crash.patch new file mode 100644 index 0000000000000000000000000000000000000000..20996e4e253f4dfaf25f359540d00b81ecfb26ba --- /dev/null +++ b/backport-0002-Fix-catalog-zone-reconfiguration-crash.patch @@ -0,0 +1,119 @@ +From 4b362a82ebf511d0915585bbe55bdb9b989f439a Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Mon, 11 Oct 2021 18:13:39 +0000 +Subject: [PATCH] Fix catalog zone reconfiguration crash + +The following scenario triggers a "named" crash: + +1. Configure a catalog zone. +2. Start "named". +3. Comment out the "catalog-zone" clause. +4. Run `rndc reconfig`. +5. Uncomment the "catalog-zone" clause. +6. Run `rndc reconfig` again. + +Implement the required cleanup of the in-memory catalog zone during +the first `rndc reconfig`, so that the second `rndc reconfig` could +find it in an expected state. + +(cherry picked from commit 43ac2cd229813c04438e027c42c0b93b9661adda) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/4b362a82ebf511d0915585bbe55bdb9b989f439a +--- + bin/named/server.c | 2 ++ + lib/dns/include/dns/zone.h | 20 ++++++++++++++++++++ + lib/dns/win32/libdns.def.in | 2 ++ + lib/dns/zone.c | 18 ++++++++++++++++++ + 4 files changed, 42 insertions(+) + +diff --git a/bin/named/server.c b/bin/named/server.c +index 860ccae8a1..9c0f12f63f 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -6523,6 +6523,8 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, + + if (zone_is_catz) { + dns_zone_catz_enable(zone, view->catzs); ++ } else if (dns_zone_catz_is_enabled(zone)) { ++ dns_zone_catz_disable(zone); + } + + /* +diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h +index 08e2263c5b..33ab5c60fd 100644 +--- a/lib/dns/include/dns/zone.h ++++ b/lib/dns/include/dns/zone.h +@@ -2605,6 +2605,26 @@ dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs); + * \li prior to calling, zone->catzs is NULL or is equal to 'catzs' + */ + ++void ++dns_zone_catz_disable(dns_zone_t *zone); ++/*%< ++ * Disable zone as catalog zone, if it is one. ++ * ++ * Requires: ++ * ++ * \li 'zone' is a valid zone object ++ */ ++ ++bool ++dns_zone_catz_is_enabled(dns_zone_t *zone); ++/*%< ++ * Return a boolean indicating whether the zone is enabled as catalog zone. ++ * ++ * Requires: ++ * ++ * \li 'zone' is a valid zone object ++ */ ++ + void + dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db); + /*%< +diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in +index 31f511103f..1e0f7cf64a 100644 +--- a/lib/dns/win32/libdns.def.in ++++ b/lib/dns/win32/libdns.def.in +@@ -1173,8 +1173,10 @@ dns_xfrin_shutdown + dns_zone_addnsec3chain + dns_zone_asyncload + dns_zone_attach ++dns_zone_catz_disable + dns_zone_catz_enable + dns_zone_catz_enable_db ++dns_zone_catz_is_enabled + dns_zone_cdscheck + dns_zone_checknames + dns_zone_clearforwardacl +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 65a3aacab7..bc33e6ede8 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -1942,6 +1942,24 @@ dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) { + UNLOCK_ZONE(zone); + } + ++void ++dns_zone_catz_disable(dns_zone_t *zone) { ++ REQUIRE(DNS_ZONE_VALID(zone)); ++ ++ LOCK_ZONE(zone); ++ if (zone->catzs != NULL) { ++ dns_catz_catzs_detach(&zone->catzs); ++ } ++ UNLOCK_ZONE(zone); ++} ++ ++bool ++dns_zone_catz_is_enabled(dns_zone_t *zone) { ++ REQUIRE(DNS_ZONE_VALID(zone)); ++ ++ return (zone->catzs != NULL); ++} ++ + /* + * If a zone is a catalog zone, attach it to update notification in database. + */ +-- +2.27.0 + diff --git a/backport-0003-Improve-the-logging-on-failed-TCP-accept.patch b/backport-0003-Improve-the-logging-on-failed-TCP-accept.patch new file mode 100644 index 0000000000000000000000000000000000000000..aba4616334374cfe925ff958293dd1b950682d0d --- /dev/null +++ b/backport-0003-Improve-the-logging-on-failed-TCP-accept.patch @@ -0,0 +1,162 @@ +From 75c484e36d6d28da820bfcf530a28b4f785049a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 1 Dec 2021 17:41:20 +0100 +Subject: [PATCH] Improve the logging on failed TCP accept + +Previously, when TCP accept failed, we have logged a message with +ISC_LOG_ERROR level. One common case, how this could happen is that the +client hits TCP client quota and is put on hold and when resumed, the +client has already given up and closed the TCP connection. In such +case, the named would log: + + TCP connection failed: socket is not connected + +This message was quite confusing because it actually doesn't say that +it's related to the accepting the TCP connection and also it logs +everything on the ISC_LOG_ERROR level. + +Change the log message to "Accepting TCP connection failed" and for +specific error states lower the severity of the log message to +ISC_LOG_INFO. + +(cherry picked from commit 20ac73eb222e60395399b467b0a72015a4dd8845) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/75c484e36d6d28da820bfcf530a28b4f785049a6 +--- + lib/isc/netmgr/netmgr-int.h | 3 +++ + lib/isc/netmgr/netmgr.c | 27 +++++++++++++++++++++++++++ + lib/isc/netmgr/tcp.c | 20 ++------------------ + lib/isc/netmgr/tcpdns.c | 22 ++-------------------- + 4 files changed, 34 insertions(+), 38 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index f7b54f9..b4299d5 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -1576,4 +1576,7 @@ isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, bool async); + void + isc__nmsocket_connecttimeout_cb(uv_timer_t *timer); + ++void ++isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota); ++ + #define STREAM_CLIENTS_PER_CONN 23 +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 3283eb6e4f..54042a9123 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -1967,6 +1967,33 @@ isc__nmsocket_connecttimeout_cb(uv_timer_t *timer) { + } + } + ++void ++isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota) { ++ int level; ++ ++ switch (result) { ++ case ISC_R_SUCCESS: ++ case ISC_R_NOCONN: ++ return; ++ case ISC_R_QUOTA: ++ case ISC_R_SOFTQUOTA: ++ if (!can_log_quota) { ++ return; ++ } ++ level = ISC_LOG_INFO; ++ break; ++ case ISC_R_NOTCONNECTED: ++ level = ISC_LOG_INFO; ++ break; ++ default: ++ level = ISC_LOG_ERROR; ++ } ++ ++ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR, ++ level, "Accepting TCP connection failed: %s", ++ isc_result_totext(result)); ++} ++ + static void + isc__nmsocket_readtimeout_cb(uv_timer_t *timer) { + isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer); +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index 5cca9f5214..1b5e80d3a7 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -631,15 +631,7 @@ tcp_connection_cb(uv_stream_t *server, int status) { + + result = accept_connection(ssock, quota); + done: +- if (result != ISC_R_SUCCESS && result != ISC_R_NOCONN) { +- if ((result != ISC_R_QUOTA && result != ISC_R_SOFTQUOTA) || +- can_log_tcp_quota()) { +- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, +- ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR, +- "TCP connection failed: %s", +- isc_result_totext(result)); +- } +- } ++ isc__nm_accept_connection_log(result, can_log_tcp_quota()); + } + + void +@@ -934,15 +926,7 @@ isc__nm_async_tcpaccept(isc__networker_t *worker, isc__netievent_t *ev0) { + REQUIRE(sock->tid == isc_nm_tid()); + + result = accept_connection(sock, ievent->quota); +- if (result != ISC_R_SUCCESS && result != ISC_R_NOCONN) { +- if ((result != ISC_R_QUOTA && result != ISC_R_SOFTQUOTA) || +- can_log_tcp_quota()) { +- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, +- ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR, +- "TCP connection failed: %s", +- isc_result_totext(result)); +- } +- } ++ isc__nm_accept_connection_log(result, can_log_tcp_quota()); + } + + static isc_result_t +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index 188790c8b4..b76dcbc66c 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -600,16 +600,7 @@ tcpdns_connection_cb(uv_stream_t *server, int status) { + + result = accept_connection(ssock, quota); + done: +- if (result != ISC_R_SUCCESS && result != ISC_R_NOCONN) { +- if ((result != ISC_R_QUOTA && result != ISC_R_SOFTQUOTA) || +- can_log_tcpdns_quota()) +- { +- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, +- ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR, +- "TCP connection failed: %s", +- isc_result_totext(result)); +- } +- } ++ isc__nm_accept_connection_log(result, can_log_tcpdns_quota()); + } + + void +@@ -905,16 +896,7 @@ isc__nm_async_tcpdnsaccept(isc__networker_t *worker, isc__netievent_t *ev0) { + REQUIRE(ievent->sock->tid == isc_nm_tid()); + + result = accept_connection(ievent->sock, ievent->quota); +- if (result != ISC_R_SUCCESS && result != ISC_R_NOCONN) { +- if ((result != ISC_R_QUOTA && result != ISC_R_SOFTQUOTA) || +- can_log_tcpdns_quota()) +- { +- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, +- ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR, +- "TCP connection failed: %s", +- isc_result_totext(result)); +- } +- } ++ isc__nm_accept_connection_log(result, can_log_tcpdns_quota()); + } + + static isc_result_t +-- +2.27.0 + diff --git a/backport-0004-Stop-leaking-mutex-in-nmworker-and-cond-in-nm-socket.patch b/backport-0004-Stop-leaking-mutex-in-nmworker-and-cond-in-nm-socket.patch new file mode 100644 index 0000000000000000000000000000000000000000..6796b11d5605eb832e44a12569743c03c136d814 --- /dev/null +++ b/backport-0004-Stop-leaking-mutex-in-nmworker-and-cond-in-nm-socket.patch @@ -0,0 +1,46 @@ +From d5cdcf924a6b94cd501e33b0963dd787a72af1f8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Mon, 6 Dec 2021 11:10:17 +0100 +Subject: [PATCH] Stop leaking mutex in nmworker and cond in nm socket + +On FreeBSD, the pthread primitives are not solely allocated on stack, +but part of the object lives on the heap. Missing pthread_*_destroy +causes the heap memory to grow and in case of fast lived object it's +possible to run out-of-memory. + +Properly destroy the leaking mutex (worker->lock) and +the leaking condition (sock->cond). + +(cherry picked from commit 57d0fabaddf0e7ac297a046b084df8fb22d54d51) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/d5cdcf924a6b94cd501e33b0963dd787a72af1f8 +--- + lib/isc/netmgr/netmgr.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 54042a9123..e81ad4673e 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -425,6 +425,7 @@ nm_destroy(isc_nm_t **mgr0) { + isc_mempool_put(mgr->evpool, ievent); + } + isc_condition_destroy(&worker->cond_prio); ++ isc_mutex_destroy(&worker->lock); + + r = uv_loop_close(&worker->loop); + INSIST(r == 0); +@@ -1267,8 +1268,9 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) { + + isc_mem_free(sock->mgr->mctx, sock->ah_frees); + isc_mem_free(sock->mgr->mctx, sock->ah_handles); +- isc_mutex_destroy(&sock->lock); + isc_condition_destroy(&sock->scond); ++ isc_condition_destroy(&sock->cond); ++ isc_mutex_destroy(&sock->lock); + #ifdef NETMGR_TRACE + LOCK(&sock->mgr->lock); + ISC_LIST_UNLINK(sock->mgr->active_sockets, sock, active_link); +-- +2.23.0 + diff --git a/backport-0005-Address-memory-leak-when-processing-dnssec-policy-cl.patch b/backport-0005-Address-memory-leak-when-processing-dnssec-policy-cl.patch new file mode 100644 index 0000000000000000000000000000000000000000..8f79ff853fd32062b152afd4741a90eca6e11744 --- /dev/null +++ b/backport-0005-Address-memory-leak-when-processing-dnssec-policy-cl.patch @@ -0,0 +1,32 @@ +From 8dd1288dca7d6c15e8d27a746ff0e218c8981345 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 23 Dec 2021 17:42:39 +1100 +Subject: [PATCH] Address memory leak when processing dnssec-policy clauses + +A kasp structure was not detached when looking to see if there +was an existing kasp structure with the same name, causing memory +to be leaked. Fixed by calling dns_kasp_detach() to release the +reference. + +(cherry picked from commit 694440e6140bbf410b4abe3b1539491d63a43a33) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/8dd1288dca7d6c15e8d27a746ff0e218c8981345 +--- + lib/isccfg/kaspconf.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c +index 8a119fb612..15433d9f90 100644 +--- a/lib/isccfg/kaspconf.c ++++ b/lib/isccfg/kaspconf.c +@@ -272,6 +272,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx, + result = dns_kasplist_find(kasplist, kaspname, &kasp); + + if (result == ISC_R_SUCCESS) { ++ dns_kasp_detach(&kasp); + return (ISC_R_EXISTS); + } + if (result != ISC_R_NOTFOUND) { +-- +2.23.0 + diff --git a/backport-0005-Report-duplicate-dnssec-policy-names.patch b/backport-0005-Report-duplicate-dnssec-policy-names.patch new file mode 100644 index 0000000000000000000000000000000000000000..907864961886849424f92c28cc6b4b658b53dedb --- /dev/null +++ b/backport-0005-Report-duplicate-dnssec-policy-names.patch @@ -0,0 +1,54 @@ +From 0e0cd6bf17704300cf3a1f69563219ce263da913 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 23 Dec 2021 17:54:53 +1100 +Subject: [PATCH] Report duplicate dnssec-policy names + +Duplicate dnssec-policy names were detected as an error condition +but were not logged. + +(cherry picked from commit b8845454c8c67c5c5650e597936f6303708bdd7d) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/0e0cd6bf17704300cf3a1f69563219ce263da913 +--- + bin/tests/system/checkconf/bad-kasp-duplicate.conf | 13 +++++++++++++ + lib/isccfg/kaspconf.c | 4 ++++ + 2 files changed, 17 insertions(+) + create mode 100644 bin/tests/system/checkconf/bad-kasp-duplicate.conf + +diff --git a/bin/tests/system/checkconf/bad-kasp-duplicate.conf b/bin/tests/system/checkconf/bad-kasp-duplicate.conf +new file mode 100644 +index 0000000000..8ecc670e0b +--- /dev/null ++++ b/bin/tests/system/checkconf/bad-kasp-duplicate.conf +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ * ++ * See the COPYRIGHT file distributed with this work for additional ++ * information regarding copyright ownership. ++ */ ++ ++dnssec-policy a { }; ++dnssec-policy a { }; +diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c +index 15433d9f90..f6f1bc3a10 100644 +--- a/lib/isccfg/kaspconf.c ++++ b/lib/isccfg/kaspconf.c +@@ -272,6 +272,10 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx, + result = dns_kasplist_find(kasplist, kaspname, &kasp); + + if (result == ISC_R_SUCCESS) { ++ cfg_obj_log( ++ config, logctx, ISC_LOG_ERROR, ++ "dnssec-policy: duplicately named policy found '%s'", ++ kaspname); + dns_kasp_detach(&kasp); + return (ISC_R_EXISTS); + } +-- +2.23.0 + diff --git a/backport-0006-Prevent-a-shutdown-race-in-catz_create_chg_task.patch b/backport-0006-Prevent-a-shutdown-race-in-catz_create_chg_task.patch new file mode 100644 index 0000000000000000000000000000000000000000..57611a6fe0ebb707edf067bccba45f5e4e718260 --- /dev/null +++ b/backport-0006-Prevent-a-shutdown-race-in-catz_create_chg_task.patch @@ -0,0 +1,65 @@ +From 21b00934403697a6ac98422b38a517d0833c946f Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Tue, 4 Jan 2022 12:08:43 -0800 +Subject: [PATCH] Prevent a shutdown race in catz_create_chg_task() + +If a catz event is scheduled while the task manager was being +shut down, task-exclusive mode is unavailable. This needs to be +handled as an error rather than triggering an assertion. + +(cherry picked from commit 973ac1d8912d8d885e9a002ffee4acbaf23e9c81) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/21b00934403697a6ac98422b38a517d0833c946f +--- + bin/named/server.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/bin/named/server.c b/bin/named/server.c +index 9c0f12f63f..cad992f873 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -2921,11 +2921,16 @@ static isc_result_t + catz_create_chg_task(dns_catz_entry_t *entry, dns_catz_zone_t *origin, + dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata, + isc_eventtype_t type) { +- catz_chgzone_event_t *event; +- isc_task_t *task; ++ catz_chgzone_event_t *event = NULL; ++ isc_task_t *task = NULL; + isc_result_t result; + isc_taskaction_t action = NULL; + ++ result = isc_taskmgr_excltask(taskmgr, &task); ++ if (result != ISC_R_SUCCESS) { ++ return (result); ++ } ++ + switch (type) { + case DNS_EVENT_CATZADDZONE: + case DNS_EVENT_CATZMODZONE: +@@ -2936,6 +2941,7 @@ catz_create_chg_task(dns_catz_entry_t *entry, dns_catz_zone_t *origin, + break; + default: + REQUIRE(0); ++ ISC_UNREACHABLE(); + } + + event = (catz_chgzone_event_t *)isc_event_allocate( +@@ -2946,13 +2952,11 @@ catz_create_chg_task(dns_catz_entry_t *entry, dns_catz_zone_t *origin, + event->origin = NULL; + event->view = NULL; + event->mod = (type == DNS_EVENT_CATZMODZONE); ++ + dns_catz_entry_attach(entry, &event->entry); + dns_catz_zone_attach(origin, &event->origin); + dns_view_attach(view, &event->view); + +- task = NULL; +- result = isc_taskmgr_excltask(taskmgr, &task); +- REQUIRE(result == ISC_R_SUCCESS); + isc_task_send(task, ISC_EVENT_PTR(&event)); + isc_task_detach(&task); + +-- +2.23.0 + diff --git a/backport-0007-Fix-bug-introduced-by-763-related-to-offline-keys.patch b/backport-0007-Fix-bug-introduced-by-763-related-to-offline-keys.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8d181d015f4c1b644f4c87548e1298316149d79 --- /dev/null +++ b/backport-0007-Fix-bug-introduced-by-763-related-to-offline-keys.patch @@ -0,0 +1,129 @@ +From bdb91e3825c194a0750ecf79f8acfd81de8c001d Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Tue, 7 Dec 2021 13:59:42 +0100 +Subject: [PATCH] Fix bug introduced by #763 related to offline keys + +In some cases we want to keep expired signatures. For example, if the +KSK is offline, we don't want to fall back to signing with the ZSK. +We could remove the signatures, but in any case we end up with a broken +zone. + +The change made for GL #763 prevented the behavior to sign the DNSKEY +RRset with the ZSK if the KSK was offline (and signatures were expired). + +The change causes the definition of "having both keys": if one key is +offline, we still consider having both keys, so we don't fallback +signing with the ZSK if KSK is offline. + +That change also works the other way, if the ZSK is offline, we don't +fallback signing with the KSK. + +This commit fixes that, so we only fallback signing zone RRsets with +the KSK, not signing key RRsets with the ZSK. + +(cherry picked from commit beeefe35c4a05bb69e9730190039fdf3e9fea1ba) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/bdb91e3825c194a0750ecf79f8acfd81de8c001d +--- + lib/dns/update.c | 6 +++--- + lib/dns/zone.c | 24 +++++++++++++++--------- + 2 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/lib/dns/update.c b/lib/dns/update.c +index 71ef7dde46..2a766dc6ba 100644 +--- a/lib/dns/update.c ++++ b/lib/dns/update.c +@@ -1158,8 +1158,8 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + } + + /* Don't consider inactive keys, however +- * the key may be temporary offline, so do +- * consider keys which private key files are ++ * the KSK may be temporary offline, so do ++ * consider KSKs which private key files are + * unavailable. + */ + if (dst_key_inactive(keys[j])) { +@@ -1171,7 +1171,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + } + if (KSK(keys[j])) { + have_ksk = true; +- } else { ++ } else if (dst_key_isprivate(keys[j])) { + have_nonksk = true; + } + both = have_ksk && have_nonksk; +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 27373b34fe..f8eb0aae82 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -3483,7 +3483,8 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) { + result = dns_rdata_tostruct(&rdata, &dnskey, NULL); + INSIST(result == ISC_R_SUCCESS); + +- /* RFC 3110, section 4: Performance Considerations: ++ /* ++ * RFC 3110, section 4: Performance Considerations: + * + * A public exponent of 3 minimizes the effort needed to verify + * a signature. Use of 3 as the public exponent is weak for +@@ -7060,8 +7061,9 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone, + continue; + } + +- /* Don't consider inactive keys, however +- * the key may be temporary offline, so do ++ /* ++ * Don't consider inactive keys, however ++ * the KSK may be temporary offline, so do + * consider keys which private key files are + * unavailable. + */ +@@ -7074,7 +7076,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone, + } + if (KSK(keys[j])) { + have_ksk = true; +- } else { ++ } else if (dst_key_isprivate(keys[j])) { + have_nonksk = true; + } + both = have_ksk && have_nonksk; +@@ -9705,9 +9707,10 @@ zone_sign(dns_zone_t *zone) { + ALG(zone_keys[j]))) { + continue; + } +- /* Don't consider inactive keys, however ++ /* ++ * Don't consider inactive keys, however + * the key may be temporary offline, so +- * do consider keys which private key ++ * do consider KSKs which private key + * files are unavailable. + */ + if (dst_key_inactive(zone_keys[j])) { +@@ -9718,7 +9721,8 @@ zone_sign(dns_zone_t *zone) { + } + if (KSK(zone_keys[j])) { + have_ksk = true; +- } else { ++ } else if (dst_key_isprivate( ++ zone_keys[j])) { + have_nonksk = true; + } + both = have_ksk && have_nonksk; +@@ -14744,8 +14748,10 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { + timeout = 30; + } + +- /* Save request parameters so we can reuse them later on +- for resolving missing glue A/AAAA records. */ ++ /* ++ * Save request parameters so we can reuse them later on ++ * for resolving missing glue A/AAAA records. ++ */ + cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args)); + cb_args->stub = stub; + cb_args->tsig_key = key; +-- +2.23.0 + diff --git a/backport-0007-Only-warn-if-we-could-not-delete-signature.patch b/backport-0007-Only-warn-if-we-could-not-delete-signature.patch new file mode 100644 index 0000000000000000000000000000000000000000..3d8668991194e7d1cc86970d8f4b31d871e3e3c9 --- /dev/null +++ b/backport-0007-Only-warn-if-we-could-not-delete-signature.patch @@ -0,0 +1,58 @@ +From 8e31f6981a4e080bc02158a74f4f99f70144cf45 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Fri, 3 Dec 2021 16:18:13 +0100 +Subject: [PATCH] Only warn if we could not delete signature + +BIND can log this warning: + + zone example.ch/IN (signed): Key example.ch/ECDSAP256SHA256/56340 + missing or inactive and has no replacement: retaining signatures. + +This log can happen when BIND tries to remove signatures because the +are about to expire or to be resigned. These RRsets may be signed with +the KSK if the ZSK files has been removed from disk. When we have +created a new ZSK we can replace the signatures creeated by the KSK +with signatures from the new ZSK. + +It complains about the KSK being missing or inactive, but actually it +takes the key id from the RRSIG. + +The warning is logged if BIND detects the private ZSK file is missing. + +The warning is logged even if we were able to delete the signature. + +With the change from this commit it only logs this warning if it is not +okay to delete the signature. + +(cherry picked from commit 2d2858841a8a749792f50ff077d03cf50f730981) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/8e31f6981a4e080bc02158a74f4f99f70144cf45 +--- + lib/dns/zone.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 8bfc5e8bc9..27373b34fe 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -6858,7 +6858,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + } + deleted = true; + } +- if (warn) { ++ if (warn && !deleted) { + /* + * At this point, we've got an RRSIG, + * which is signed by an inactive key. +@@ -6868,7 +6868,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + * offline will prevent us spinning waiting + * for the private part. + */ +- if (incremental && !deleted) { ++ if (incremental) { + result = offline(db, ver, zonediff, + name, rdataset.ttl, + &rdata); +-- +2.23.0 + diff --git a/backport-0007-Replace-RSASHA1-in-autosign-test-with-default-alg.patch b/backport-0007-Replace-RSASHA1-in-autosign-test-with-default-alg.patch new file mode 100644 index 0000000000000000000000000000000000000000..0ae0496d8525ab16a8d5386b991a9a8e414016e7 --- /dev/null +++ b/backport-0007-Replace-RSASHA1-in-autosign-test-with-default-alg.patch @@ -0,0 +1,498 @@ +From 99316385d35dc4a212988be7c69aadd20bc31fa1 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Wed, 5 Jan 2022 11:39:03 +0100 +Subject: [PATCH] Replace RSASHA1 in autosign test with default alg + +Change RSASHA1 to $DEFAULT_ALGORITHM to be FIPS compliant. + +There is one RSASHA1 occurence left, to test that dynamically adding an +NSEC3PARAM record to an NSEC-only zone fails. + +(cherry picked from commit 6e9fed2d24bc6bd475132285971ad1a86c0f9dc6) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/99316385d35dc4a212988be7c69aadd20bc31fa1 +--- + bin/tests/system/autosign/ns3/keygen.sh | 132 ++++++++++++------------ + bin/tests/system/autosign/tests.sh | 35 ++++--- + 2 files changed, 85 insertions(+), 82 deletions(-) + +diff --git a/bin/tests/system/autosign/ns3/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh +index 633e08360a..1755a499fe 100644 +--- a/bin/tests/system/autosign/ns3/keygen.sh ++++ b/bin/tests/system/autosign/ns3/keygen.sh +@@ -30,8 +30,8 @@ setup () { + + setup secure.example + cp $infile $zonefile +-ksk=`$KEYGEN -a RSASHA1 -3 -q -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -39,8 +39,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup secure.nsec3.example + cp $infile $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -48,8 +48,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup nsec3.nsec3.example + cp $infile $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -72,8 +72,8 @@ done + # + setup optout.nsec3.example + cp $infile $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -81,8 +81,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup nsec3.example + cat $infile dsset-*.${zone}$TP > $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -90,9 +90,9 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup autonsec3.example + cat $infile > $zonefile +-ksk=`$KEYGEN -G -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out ++ksk=`$KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out + echo $ksk > ../autoksk.key +-zsk=`$KEYGEN -G -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out` || dumpit kg.out + echo $zsk > ../autozsk.key + $DSFROMKEY $ksk.key > dsset-${zone}$TP + +@@ -101,8 +101,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup secure.optout.example + cp $infile $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -110,8 +110,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup nsec3.optout.example + cp $infile $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -119,8 +119,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup optout.optout.example + cp $infile $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -128,8 +128,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup optout.example + cat $infile dsset-*.${zone}$TP > $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -171,8 +171,8 @@ do + echo "label${count} IN TXT label${count}" >> $zonefile + count=`expr $count + 1` + done +-$KEYGEN -q -a RSASHA1 -fk $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -q -a RSASHA1 $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM $zone > kg.out 2>&1 || dumpit kg.out + $SIGNER -PS -s now-1y -e now-6mo -o $zone -f $zonefile.signed $zonefile > s.out || dumpit s.out + mv $zonefile.signed $zonefile + +@@ -189,8 +189,8 @@ $SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > s.out || dumpit s.out + # keys via nsupdate + # + setup secure-to-insecure.example +-$KEYGEN -a RSASHA1 -q -fk $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -a RSASHA1 -q $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -q -fk $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -q $zone > kg.out 2>&1 || dumpit kg.out + $SIGNER -S -o $zone -f $zonefile $infile > s.out || dumpit s.out + + # +@@ -198,9 +198,9 @@ $SIGNER -S -o $zone -f $zonefile $infile > s.out || dumpit s.out + # removal of keys on schedule. + # + setup secure-to-insecure2.example +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out + echo $ksk > ../del1.key +-zsk=`$KEYGEN -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out` || dumpit kg.out + echo $zsk > ../del2.key + $SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out || dumpit s.out + +@@ -209,8 +209,8 @@ $SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out || dumpit s.out + # + setup prepub.example + infile="secure-to-insecure2.example.db.in" +-$KEYGEN -a RSASHA1 -3 -q -fk $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + $SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out || dumpit s.out + + # +@@ -219,35 +219,35 @@ $SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out || dumpit s.out + + # no default key TTL; DNSKEY should get SOA TTL + setup ttl1.example +-$KEYGEN -a RSASHA1 -3 -q -fk $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + cp $infile $zonefile + + # default key TTL should be used +-setup ttl2.example +-$KEYGEN -a RSASHA1 -3 -q -fk -L 60 $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q -L 60 $zone > kg.out 2>&1 || dumpit kg.out ++setup ttl2.example ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 60 $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone > kg.out 2>&1 || dumpit kg.out + cp $infile $zonefile + + # mismatched key TTLs, should use shortest + setup ttl3.example +-$KEYGEN -a RSASHA1 -3 -q -fk -L 30 $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q -L 60 $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 30 $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone > kg.out 2>&1 || dumpit kg.out + cp $infile $zonefile + + # existing DNSKEY RRset, should retain TTL + setup ttl4.example +-$KEYGEN -a RSASHA1 -3 -q -L 30 -fk $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 30 -fk $zone > kg.out 2>&1 || dumpit kg.out + cat ${infile} K${zone}.+*.key > $zonefile +-$KEYGEN -a RSASHA1 -3 -q -L 180 $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 180 $zone > kg.out 2>&1 || dumpit kg.out + + # + # A zone with a DNSKEY RRset that is published before it's activated + # + setup delay.example +-ksk=`$KEYGEN -G -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out ++ksk=`$KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out + echo $ksk > ../delayksk.key +-zsk=`$KEYGEN -G -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out` || dumpit kg.out + echo $zsk > ../delayzsk.key + + # +@@ -255,8 +255,8 @@ echo $zsk > ../delayzsk.key + # is missing. + # + setup noksk.example +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-zsk=`$KEYGEN -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out` || dumpit kg.out + $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out + echo $ksk > ../noksk-ksk.key + rm -f ${ksk}.private +@@ -266,8 +266,8 @@ rm -f ${ksk}.private + # is missing. + # + setup nozsk.example +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-zsk=`$KEYGEN -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out` || dumpit kg.out + $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out + echo $ksk > ../nozsk-ksk.key + echo $zsk > ../nozsk-zsk.key +@@ -278,8 +278,8 @@ rm -f ${zsk}.private + # is inactive. + # + setup inaczsk.example +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-zsk=`$KEYGEN -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out` || dumpit kg.out + $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out + echo $ksk > ../inaczsk-ksk.key + echo $zsk > ../inaczsk-zsk.key +@@ -290,16 +290,16 @@ $SETTIME -I now $zsk > st.out 2>&1 || dumpit st.out + # + setup reconf.example + cp secure.example.db.in $zonefile +-$KEYGEN -q -a RSASHA1 -3 -fk $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + + # + # A zone which generates CDS and CDNSEY RRsets automatically + # + setup sync.example + cp $infile $zonefile +-ksk=`$KEYGEN -a RSASHA1 -3 -q -fk -P sync now $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + echo ns3/$ksk > ../sync.key + +@@ -308,8 +308,8 @@ echo ns3/$ksk > ../sync.key + # + setup kskonly.example + cp $infile $zonefile +-ksk=`$KEYGEN -a RSASHA1 -3 -q -fk -P sync now $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -317,8 +317,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup inacksk2.example + cp $infile $zonefile +-ksk=`$KEYGEN -a RSASHA1 -3 -q -Pnow -A now+3600 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -Pnow -A now+3600 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -326,8 +326,8 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup inaczsk2.example + cp $infile $zonefile +-ksk=`$KEYGEN -a RSASHA1 -3 -q -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a RSASHA1 -3 -q -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -335,9 +335,9 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup inacksk3.example + cp $infile $zonefile +-$KEYGEN -a NSEC3RSASHA1 -3 -q -P now -A now+3600 -fk $zone > kg.out 2>&1 || dumpit kg.out +-ksk=`$KEYGEN -a NSEC3RSASHA1 -3 -q -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a NSEC3RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 -fk $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -345,9 +345,9 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup inaczsk3.example + cp $infile $zonefile +-ksk=`$KEYGEN -a NSEC3RSASHA1 -3 -q -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a NSEC3RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out +-$KEYGEN -a NSEC3RSASHA1 -3 -q -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +@@ -356,9 +356,9 @@ $DSFROMKEY $ksk.key > dsset-${zone}$TP + # + setup delzsk.example + cp $infile $zonefile +-ksk=`$KEYGEN -a NSEC3RSASHA1 -3 -q -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -a NSEC3RSASHA1 -3 -q $zone > kg.out 2>&1 || dumpit kg.out +-zsk=`$KEYGEN -a NSEC3RSASHA1 -3 -q -I now-1w $zone 2>kg.out` || dumpit kg.out ++ksk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out ++zsk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -I now-1w $zone 2>kg.out` || dumpit kg.out + echo $zsk > ../delzsk.key + + # +@@ -366,6 +366,6 @@ echo $zsk > ../delzsk.key + # + setup dname-at-apex-nsec3.example + cp $infile $zonefile +-ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out +-$KEYGEN -q -a RSASHA1 -3 $zone > kg.out 2>&1 || dumpit kg.out ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP +diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh +index 33692cd5f5..b5069ce6fe 100755 +--- a/bin/tests/system/autosign/tests.sh ++++ b/bin/tests/system/autosign/tests.sh +@@ -203,9 +203,9 @@ $DIG $DIGOPTS @10.53.0.3 axfr inacksk3.example > dig.out.ns3.test$n + + zskid=`awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n | + $DSFROMKEY -A -2 -f - inacksk3.example | awk '{ print $4}'` +-grep "DNSKEY 7 2 " dig.out.ns3.test$n > /dev/null || ret=1 ++grep "DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 " dig.out.ns3.test$n > /dev/null || ret=1 + +-pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${zskid} " ++pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${zskid} " + grep "${pattern}" dig.out.ns3.test$n > /dev/null && ret=1 + + count=`awk 'BEGIN { count = 0 } +@@ -221,7 +221,8 @@ test $count -eq 3 || ret=1 + awk='$4 == "RRSIG" && $5 == "DNSKEY" { printf "%05u\n", $11 }' + id=`awk "${awk}" dig.out.ns3.test$n` + +-$SETTIME -D now+5 ns3/Kinacksk3.example.+007+${id} > settime.out.test$n || ret=1 ++keyfile=$(printf "ns3/Kinacksk3.example.+%03u+%s" "${DEFAULT_ALGORITHM_NUMBER}" "${id}") ++$SETTIME -D now+5 "${keyfile}" > settime.out.test$n || ret=1 + ($RNDCCMD 10.53.0.3 loadkeys inacksk3.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 + + n=`expr $n + 1` +@@ -238,8 +239,8 @@ ret=0 + $DIG $DIGOPTS @10.53.0.3 axfr inaczsk3.example > dig.out.ns3.test$n + kskid=`awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n | + $DSFROMKEY -2 -f - inaczsk3.example | awk '{ print $4}' ` +-grep "CNAME 7 3 " dig.out.ns3.test$n > /dev/null || ret=1 +-grep "CNAME 7 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null && ret=1 ++grep "CNAME ${DEFAULT_ALGORITHM_NUMBER} 3 " dig.out.ns3.test$n > /dev/null || ret=1 ++grep "CNAME ${DEFAULT_ALGORITHM_NUMBER} 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null && ret=1 + count=`awk 'BEGIN { count = 0 } + $4 == "RRSIG" && $5 == "CNAME" { count++ } + END {print count}' dig.out.ns3.test$n` +@@ -249,7 +250,9 @@ count=`awk 'BEGIN { count = 0 } + END {print count}' dig.out.ns3.test$n` + test $count -eq 3 || ret=1 + id=`awk '$4 == "RRSIG" && $5 == "CNAME" { printf "%05u\n", $11 }' dig.out.ns3.test$n` +-$SETTIME -D now+5 ns3/Kinaczsk3.example.+007+${id} > settime.out.test$n || ret=1 ++ ++keyfile=$(printf "ns3/Kinaczsk3.example.+%03u+%s" "${DEFAULT_ALGORITHM_NUMBER}" "${id}") ++$SETTIME -D now+5 "${keyfile}" > settime.out.test$n || ret=1 + ($RNDCCMD 10.53.0.3 loadkeys inaczsk3.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -399,7 +402,7 @@ status=`expr $status + $ret` + + echo_i "checking that replaced RRSIGs are not logged (missing ZSK private key) ($n)" + ret=0 +-loglines=`grep "Key nozsk.example/NSEC3RSASHA1/$missing .* retaining signatures" ns3/named.run | wc -l` ++loglines=`grep "Key nozsk.example/$DEFAULT_ALGORITHM/$missing .* retaining signatures" ns3/named.run | wc -l` + [ "$loglines" -eq 0 ] || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -407,7 +410,7 @@ status=`expr $status + $ret` + + echo_i "checking that replaced RRSIGs are not logged (inactive ZSK private key) ($n)" + ret=0 +-loglines=`grep "Key inaczsk.example/NSEC3RSASHA1/$inactive .* retaining signatures" ns3/named.run | wc -l` ++loglines=`grep "Key inaczsk.example/$DEFAULT_ALGORITHM/$inactive .* retaining signatures" ns3/named.run | wc -l` + [ "$loglines" -eq 0 ] || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -1065,7 +1068,7 @@ send + END + [ $ret != 0 ] && echo_i "error: dynamic update add NSEC3PARAM failed" + # Create DNSSEC keys in the zone directory. +-$KEYGEN -a rsasha1 -3 -q -K ns3 jitter.nsec3.example > /dev/null ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -K ns3 jitter.nsec3.example > /dev/null + # Trigger zone signing. + ($RNDCCMD 10.53.0.3 sign jitter.nsec3.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 + # Wait until zone has been signed. +@@ -1089,7 +1092,7 @@ ret=0 + oldserial=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '$0 !~ /SOA/ {print $3}'` + oldinception=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u` + +-$KEYGEN -a rsasha1 -3 -q -K ns3 -P 0 -A +6d -I +38d -D +45d prepub.example > /dev/null ++$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -K ns3 -P 0 -A +6d -I +38d -D +45d prepub.example > /dev/null + + ($RNDCCMD 10.53.0.3 sign prepub.example 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 + newserial=$oldserial +@@ -1473,12 +1476,12 @@ $DIG $DIGOPTS @10.53.0.3 axfr inacksk2.example > dig.out.ns3.test$n + + zskid=`awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n | + $DSFROMKEY -A -2 -f - inacksk2.example | awk '{ print $4}' ` +-pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${zskid} " ++pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${zskid} " + grep "${pattern}" dig.out.ns3.test$n > /dev/null || ret=1 + + kskid=`awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n | + $DSFROMKEY -2 -f - inacksk2.example | awk '{ print $4}' ` +-pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${kskid} " ++pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${kskid} " + grep "${pattern}" dig.out.ns3.test$n > /dev/null && ret=1 + + n=`expr $n + 1` +@@ -1488,7 +1491,7 @@ status=`expr $status + $ret` + echo_i "check that zone with inactive ZSK and active KSK is properly autosigned ($n)" + ret=0 + $DIG $DIGOPTS @10.53.0.3 axfr inaczsk2.example > dig.out.ns3.test$n +-grep "SOA 7 2" dig.out.ns3.test$n > /dev/null || ret=1 ++grep "SOA ${DEFAULT_ALGORITHM_NUMBER} 2" dig.out.ns3.test$n > /dev/null || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` +@@ -1505,7 +1508,7 @@ $DIG $DIGOPTS @10.53.0.3 axfr inacksk3.example > dig.out.ns3.test$n + + zskid=`awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n | + $DSFROMKEY -A -2 -f - inacksk3.example | awk '{ print $4}' ` +-pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${zskid} " ++pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${zskid} " + grep "${pattern}" dig.out.ns3.test$n > /dev/null || ret=1 + + count=`awk 'BEGIN { count = 0 } +@@ -1532,7 +1535,7 @@ ret=0 + $DIG $DIGOPTS @10.53.0.3 axfr inaczsk3.example > dig.out.ns3.test$n + kskid=`awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n | + $DSFROMKEY -2 -f - inaczsk3.example | awk '{ print $4}' ` +-grep "CNAME 7 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null || ret=1 ++grep "CNAME ${DEFAULT_ALGORITHM_NUMBER} 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null || ret=1 + count=`awk 'BEGIN { count = 0 } + $4 == "RRSIG" && $5 == "CNAME" { count++ } + END {print count}' dig.out.ns3.test$n` +@@ -1606,7 +1609,7 @@ status=`expr $status + $ret` + echo_i "check that DNAME at apex with NSEC3 is correctly signed (auto-dnssec maintain) ($n)" + ret=0 + $DIG $DIGOPTS txt dname-at-apex-nsec3.example @10.53.0.3 > dig.out.ns3.test$n || ret=1 +-grep "RRSIG NSEC3 7 3 600" dig.out.ns3.test$n > /dev/null || ret=1 ++grep "RRSIG NSEC3 ${DEFAULT_ALGORITHM_NUMBER} 3 600" dig.out.ns3.test$n > /dev/null || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` +-- +2.23.0 + diff --git a/backport-0007-Update-autosign-test.patch b/backport-0007-Update-autosign-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..f027d5942419ec8ae3562c4457ba503416ffceeb --- /dev/null +++ b/backport-0007-Update-autosign-test.patch @@ -0,0 +1,233 @@ +From 17ae663084bdab626314da73b30aa53fc76ebe16 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Tue, 7 Dec 2021 14:11:06 +0100 +Subject: [PATCH] Update autosign test + +Update the autosign system test with new expected behavior. + +The 'nozsk.example' zone should have its expired zone signatures +deleted and replaced with signatures generated with the KSK. + +The 'inaczsk.example' zone should have its expired zone signatures +deleted and replaced with signatures generated with the KSK. + +In both scenarios, signatures are deleted, not retained, so the +"retaining signatures" warning should not be logged. + +Furthermore, thsi commit fixex a test bug where the 'awk' command +always returned 0. + +Finally, this commit adds a test case for an offline KSK, for the zone +'noksk.example'. In this case the expired signatures should be retained +(despite the zone being bogus, but resigning the DNSKEY RRset with the +ZSK won't help here). + +(cherry picked from commit fbd559ad0d389948c594a35b72d7fb6d16794702) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/17ae663084bdab626314da73b30aa53fc76ebe16 +--- + bin/tests/system/autosign/clean.sh | 3 +- + bin/tests/system/autosign/ns3/keygen.sh | 25 ++++++++++--- + bin/tests/system/autosign/ns3/named.conf.in | 7 ++++ + .../system/autosign/ns3/noksk.example.db.in | 24 ++++++++++++ + bin/tests/system/autosign/tests.sh | 37 +++++++++++++------ + 5 files changed, 78 insertions(+), 18 deletions(-) + create mode 100644 bin/tests/system/autosign/ns3/noksk.example.db.in + +diff --git a/bin/tests/system/autosign/clean.sh b/bin/tests/system/autosign/clean.sh +index 7a1101d6dd..20efc69499 100644 +--- a/bin/tests/system/autosign/clean.sh ++++ b/bin/tests/system/autosign/clean.sh +@@ -22,7 +22,7 @@ rm -f delayksk.key delayzsk.key autoksk.key autozsk.key + rm -f dig.out.* + rm -f digcomp.out.test* + rm -f digcomp.out.test* +-rm -f missingzsk.key inactivezsk.key ++rm -f noksk-ksk.key nozsk-ksk.key nozsk-zsk.key inaczsk-zsk.key inaczsk-ksk.key + rm -f nopriv.key vanishing.key del1.key del2.key + rm -f ns*/managed-keys.bind* + rm -f ns*/named.lock +@@ -43,6 +43,7 @@ rm -f ns3/jitter.nsec3.example.db + rm -f ns3/kg.out ns3/s.out ns3/st.out + rm -f ns3/kskonly.example.db + rm -f ns3/named.ns3.prev ++rm -f ns3/noksk.example.db + rm -f ns3/nozsk.example.db ns3/inaczsk.example.db + rm -f ns3/nsec.example.db + rm -f ns3/nsec3-to-nsec.example.db +diff --git a/bin/tests/system/autosign/ns3/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh +index 4c85d0c87c..633e08360a 100644 +--- a/bin/tests/system/autosign/ns3/keygen.sh ++++ b/bin/tests/system/autosign/ns3/keygen.sh +@@ -250,15 +250,27 @@ echo $ksk > ../delayksk.key + zsk=`$KEYGEN -G -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out + echo $zsk > ../delayzsk.key + ++# ++# A zone with signatures that are already expired, and the private KSK ++# is missing. ++# ++setup noksk.example ++ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out ++$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out ++echo $ksk > ../noksk-ksk.key ++rm -f ${ksk}.private ++ + # + # A zone with signatures that are already expired, and the private ZSK + # is missing. + # + setup nozsk.example +-$KEYGEN -q -a RSASHA1 -3 -fk $zone > kg.out 2>&1 || dumpit kg.out +-zsk=`$KEYGEN -q -a RSASHA1 -3 $zone` ++ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out + $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out +-echo $zsk > ../missingzsk.key ++echo $ksk > ../nozsk-ksk.key ++echo $zsk > ../nozsk-zsk.key + rm -f ${zsk}.private + + # +@@ -266,10 +278,11 @@ rm -f ${zsk}.private + # is inactive. + # + setup inaczsk.example +-$KEYGEN -q -a RSASHA1 -3 -fk $zone > kg.out 2>&1 || dumpit kg.out +-zsk=`$KEYGEN -q -a RSASHA1 -3 $zone` ++ksk=`$KEYGEN -q -a RSASHA1 -3 -fk $zone 2> kg.out` || dumpit kg.out ++zsk=`$KEYGEN -q -a RSASHA1 -3 $zone 2> kg.out` || dumpit kg.out + $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out +-echo $zsk > ../inactivezsk.key ++echo $ksk > ../inaczsk-ksk.key ++echo $zsk > ../inaczsk-zsk.key + $SETTIME -I now $zsk > st.out 2>&1 || dumpit st.out + + # +diff --git a/bin/tests/system/autosign/ns3/named.conf.in b/bin/tests/system/autosign/ns3/named.conf.in +index 7c8f74f19a..8aa64b2165 100644 +--- a/bin/tests/system/autosign/ns3/named.conf.in ++++ b/bin/tests/system/autosign/ns3/named.conf.in +@@ -249,6 +249,13 @@ zone "inaczsk.example" { + auto-dnssec maintain; + }; + ++zone "noksk.example" { ++ type primary; ++ file "noksk.example.db"; ++ allow-update { any; }; ++ auto-dnssec maintain; ++}; ++ + zone "sync.example" { + type primary; + file "sync.example.db"; +diff --git a/bin/tests/system/autosign/ns3/noksk.example.db.in b/bin/tests/system/autosign/ns3/noksk.example.db.in +new file mode 100644 +index 0000000000..90dcba9daf +--- /dev/null ++++ b/bin/tests/system/autosign/ns3/noksk.example.db.in +@@ -0,0 +1,24 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, You can obtain one at http://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 300 ; 5 minutes ++@ IN SOA mname1. . ( ++ 1 ; serial ++ 20 ; refresh (20 seconds) ++ 20 ; retry (20 seconds) ++ 1814400 ; expire (3 weeks) ++ 3600 ; minimum (1 hour) ++ ) ++ NS ns ++ns A 10.53.0.3 ++ ++a A 10.0.0.1 ++b A 10.0.0.2 ++d A 10.0.0.4 ++x CNAME a +diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh +index 79c5999d94..33692cd5f5 100755 +--- a/bin/tests/system/autosign/tests.sh ++++ b/bin/tests/system/autosign/tests.sh +@@ -157,7 +157,7 @@ do + grep "NS SOA" dig.out.ns2.test$n > /dev/null || ret=1 + done + for z in bar. example. inacksk2.example. inacksk3.example \ +- inaczsk2.example. inaczsk3.example ++ inaczsk2.example. inaczsk3.example noksk.example nozsk.example + do + $DIG $DIGOPTS $z @10.53.0.3 nsec > dig.out.ns3.test$n || ret=1 + grep "NS SOA" dig.out.ns3.test$n > /dev/null || ret=1 +@@ -364,36 +364,51 @@ END + echo_i "waiting for change to take effect" + sleep 3 + +-echo_i "checking that expired RRSIGs from missing key are not deleted ($n)" ++missing=$(keyfile_to_key_id "$(cat noksk-ksk.key)") ++echo_i "checking that expired RRSIGs from missing KSK $missing are not deleted ($n)" + ret=0 +-missing=$(keyfile_to_key_id "$(cat missingzsk.key)") ++$JOURNALPRINT ns3/noksk.example.db.jnl | \ ++ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {error=1}} END {exit error}' id=$missing || ret=1 ++n=`expr $n + 1` ++if [ $ret != 0 ]; then echo_i "failed"; fi ++status=`expr $status + $ret` ++ ++missing=$(keyfile_to_key_id "$(cat nozsk-zsk.key)") ++ksk=$(keyfile_to_key_id "$(cat nozsk-ksk.key)") ++echo_i "checking that expired RRSIGs from missing ZSK $missing are replaced ($n)" ++ret=0 ++$JOURNALPRINT ns3/nozsk.example.db.jnl | \ ++ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$missing || ret=1 + $JOURNALPRINT ns3/nozsk.example.db.jnl | \ +- awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$missing || ret=1 ++ awk '{if ($1 == "add" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$ksk || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +-echo_i "checking that expired RRSIGs from inactive key are not deleted ($n)" ++inactive=$(keyfile_to_key_id "$(cat inaczsk-zsk.key)") ++ksk=$(keyfile_to_key_id "$(cat inaczsk-ksk.key)") ++echo_i "checking that expired RRSIGs from inactive ZSK $inactive are replaced ($n)" + ret=0 +-inactive=$(keyfile_to_key_id "$(cat inactivezsk.key)") + $JOURNALPRINT ns3/inaczsk.example.db.jnl | \ +- awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$inactive || ret=1 ++ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$inactive || ret=1 ++$JOURNALPRINT ns3/inaczsk.example.db.jnl | \ ++ awk '{if ($1 == "add" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$ksk || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +-echo_i "checking that non-replaceable RRSIGs are logged only once (missing private key) ($n)" ++echo_i "checking that replaced RRSIGs are not logged (missing ZSK private key) ($n)" + ret=0 + loglines=`grep "Key nozsk.example/NSEC3RSASHA1/$missing .* retaining signatures" ns3/named.run | wc -l` +-[ "$loglines" -eq 1 ] || ret=1 ++[ "$loglines" -eq 0 ] || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +-echo_i "checking that non-replaceable RRSIGs are logged only once (inactive private key) ($n)" ++echo_i "checking that replaced RRSIGs are not logged (inactive ZSK private key) ($n)" + ret=0 + loglines=`grep "Key inaczsk.example/NSEC3RSASHA1/$inactive .* retaining signatures" ns3/named.run | wc -l` +-[ "$loglines" -eq 1 ] || ret=1 ++[ "$loglines" -eq 0 ] || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` +-- +2.23.0 + diff --git a/backport-0008-On-shutdown-return-ISC_R_SHUTTINGDOWN-from-isc_taskm.patch b/backport-0008-On-shutdown-return-ISC_R_SHUTTINGDOWN-from-isc_taskm.patch new file mode 100644 index 0000000000000000000000000000000000000000..99215cdfe3315c881536407a6461089663e4b362 --- /dev/null +++ b/backport-0008-On-shutdown-return-ISC_R_SHUTTINGDOWN-from-isc_taskm.patch @@ -0,0 +1,46 @@ +From 9ec7d78d164991b668cd50371ffe8f9b7b4b5ac3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 5 Jan 2022 11:48:22 +0100 +Subject: [PATCH] On shutdown, return ISC_R_SHUTTINGDOWN from + isc_taskmgr_excltask() + +The isc_taskmgr_excltask() would return ISC_R_NOTFOUND either when the +exclusive task was not set (yet) or when the taskmgr is shutting down +and the exclusive task has been already cleared. + +Distinguish between the two states and return ISC_R_SHUTTINGDOWN when +the taskmgr is being shut down instead of ISC_R_NOTFOUND. + +(cherry picked from commit f9d90159b84831fd83d74594827fedf0f4e9e265) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/9ec7d78d164991b668cd50371ffe8f9b7b4b5ac3 +--- + lib/isc/task.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lib/isc/task.c b/lib/isc/task.c +index 2c0d89c2b9..3e894f8dab 100644 +--- a/lib/isc/task.c ++++ b/lib/isc/task.c +@@ -1130,7 +1130,7 @@ isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task) { + + isc_result_t + isc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp) { +- isc_result_t result = ISC_R_SUCCESS; ++ isc_result_t result; + + REQUIRE(VALID_MANAGER(mgr)); + REQUIRE(taskp != NULL && *taskp == NULL); +@@ -1138,6 +1138,9 @@ isc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp) { + LOCK(&mgr->excl_lock); + if (mgr->excl != NULL) { + isc_task_attach(mgr->excl, taskp); ++ result = ISC_R_SUCCESS; ++ } else if (atomic_load_relaxed(&mgr->exiting)) { ++ result = ISC_R_SHUTTINGDOWN; + } else { + result = ISC_R_NOTFOUND; + } +-- +2.23.0 + diff --git a/backport-0009-Remove-taskmgr-excl_lock-fix-the-locking-for-taskmgr.patch b/backport-0009-Remove-taskmgr-excl_lock-fix-the-locking-for-taskmgr.patch new file mode 100644 index 0000000000000000000000000000000000000000..080bdb84a9ed852f7efcb0d198f41d899d97181c --- /dev/null +++ b/backport-0009-Remove-taskmgr-excl_lock-fix-the-locking-for-taskmgr.patch @@ -0,0 +1,179 @@ +From 5be356760dd6855944234980f2fc0f13130267fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 5 Jan 2022 13:06:37 +0100 +Subject: [PATCH] Remove taskmgr->excl_lock, fix the locking for + taskmgr->exiting + +While doing code review, it was found that the taskmgr->exiting is set +under taskmgr->lock, but accessed under taskmgr->excl_lock in the +isc_task_beginexclusive(). + +Additionally, before the change that moved running the tasks to the +netmgr, the task_ready() subrouting of isc_task_detach() would lock +mgr->lock, requiring the mgr->excl to be protected mgr->excl_lock +to prevent deadlock in the code. After !4918 has been merged, this is +no longer true, and we can remove taskmgr->excl_lock and use +taskmgr->lock in its stead. + +Solve both issues by removing the taskmgr->excl_lock and exclusively use +taskmgr->lock to protect both taskmgr->excl and taskmgr->exiting which +now doesn't need to be atomic_bool, because it's always accessed from +within the locked section. + +(cherry picked from commit e705f213cac8a79e1fa8c20ce20f2e7a28daf3f9) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/5be356760dd6855944234980f2fc0f13130267fb +--- + lib/isc/task.c | 54 ++++++++++++++++---------------------------------- + 1 file changed, 17 insertions(+), 37 deletions(-) + +diff --git a/lib/isc/task.c b/lib/isc/task.c +index 3e894f8dab..caf2c06c47 100644 +--- a/lib/isc/task.c ++++ b/lib/isc/task.c +@@ -140,14 +140,7 @@ struct isc_taskmgr { + LIST(isc_task_t) tasks; + atomic_uint_fast32_t mode; + atomic_bool exclusive_req; +- atomic_bool exiting; +- +- /* +- * Multiple threads can read/write 'excl' at the same time, so we need +- * to protect the access. We can't use 'lock' since isc_task_detach() +- * will try to acquire it. +- */ +- isc_mutex_t excl_lock; ++ bool exiting; + isc_task_t *excl; + }; + +@@ -254,13 +247,11 @@ isc_task_create_bound(isc_taskmgr_t *manager, unsigned int quantum, + INIT_LINK(task, link); + task->magic = TASK_MAGIC; + +- exiting = false; + LOCK(&manager->lock); +- if (!atomic_load_relaxed(&manager->exiting)) { ++ exiting = manager->exiting; ++ if (!exiting) { + APPEND(manager->tasks, task, link); + atomic_fetch_add(&manager->tasks_count, 1); +- } else { +- exiting = true; + } + UNLOCK(&manager->lock); + +@@ -956,7 +947,6 @@ manager_free(isc_taskmgr_t *manager) { + isc_nm_detach(&manager->netmgr); + + isc_mutex_destroy(&manager->lock); +- isc_mutex_destroy(&manager->excl_lock); + manager->magic = 0; + isc_mem_putanddetach(&manager->mctx, manager, sizeof(*manager)); + } +@@ -1000,7 +990,6 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm, + *manager = (isc_taskmgr_t){ .magic = TASK_MANAGER_MAGIC }; + + isc_mutex_init(&manager->lock); +- isc_mutex_init(&manager->excl_lock); + + if (default_quantum == 0) { + default_quantum = DEFAULT_DEFAULT_QUANTUM; +@@ -1012,7 +1001,6 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int default_quantum, isc_nm_t *nm, + } + + INIT_LIST(manager->tasks); +- atomic_init(&manager->exiting, false); + atomic_init(&manager->mode, isc_taskmgrmode_normal); + atomic_init(&manager->exclusive_req, false); + atomic_init(&manager->tasks_count, 0); +@@ -1041,15 +1029,6 @@ isc__taskmgr_shutdown(isc_taskmgr_t *manager) { + * that the startup thread is sleeping on. + */ + +- /* +- * Detach the exclusive task before acquiring the manager lock +- */ +- LOCK(&manager->excl_lock); +- if (manager->excl != NULL) { +- isc_task_detach((isc_task_t **)&manager->excl); +- } +- UNLOCK(&manager->excl_lock); +- + /* + * Unlike elsewhere, we're going to hold this lock a long time. + * We need to do so, because otherwise the list of tasks could +@@ -1058,14 +1037,16 @@ isc__taskmgr_shutdown(isc_taskmgr_t *manager) { + * This is also the only function where we will hold both the + * task manager lock and a task lock at the same time. + */ +- + LOCK(&manager->lock); ++ if (manager->excl != NULL) { ++ isc_task_detach((isc_task_t **)&manager->excl); ++ } + + /* + * Make sure we only get called once. + */ +- INSIST(atomic_compare_exchange_strong(&manager->exiting, +- &(bool){ false }, true)); ++ INSIST(manager->exiting == false); ++ manager->exiting = true; + + /* + * Post shutdown event(s) to every task (if they haven't already been +@@ -1120,12 +1101,12 @@ isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task) { + REQUIRE(task->threadid == 0); + UNLOCK(&task->lock); + +- LOCK(&mgr->excl_lock); ++ LOCK(&mgr->lock); + if (mgr->excl != NULL) { + isc_task_detach(&mgr->excl); + } + isc_task_attach(task, &mgr->excl); +- UNLOCK(&mgr->excl_lock); ++ UNLOCK(&mgr->lock); + } + + isc_result_t +@@ -1135,16 +1116,16 @@ isc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp) { + REQUIRE(VALID_MANAGER(mgr)); + REQUIRE(taskp != NULL && *taskp == NULL); + +- LOCK(&mgr->excl_lock); ++ LOCK(&mgr->lock); + if (mgr->excl != NULL) { + isc_task_attach(mgr->excl, taskp); + result = ISC_R_SUCCESS; +- } else if (atomic_load_relaxed(&mgr->exiting)) { ++ } else if (mgr->exiting) { + result = ISC_R_SHUTTINGDOWN; + } else { + result = ISC_R_NOTFOUND; + } +- UNLOCK(&mgr->excl_lock); ++ UNLOCK(&mgr->lock); + + return (result); + } +@@ -1159,11 +1140,10 @@ isc_task_beginexclusive(isc_task_t *task) { + + REQUIRE(task->state == task_state_running); + +- LOCK(&manager->excl_lock); +- REQUIRE(task == task->manager->excl || +- (atomic_load_relaxed(&task->manager->exiting) && +- task->manager->excl == NULL)); +- UNLOCK(&manager->excl_lock); ++ LOCK(&manager->lock); ++ REQUIRE(task == manager->excl || ++ (manager->exiting && manager->excl == NULL)); ++ UNLOCK(&manager->lock); + + if (!atomic_compare_exchange_strong(&manager->exclusive_req, + &(bool){ false }, true)) +-- +2.23.0 + diff --git a/backport-0010-add-UV_ENOTSUP-to-isc___nm_uverr2result.patch b/backport-0010-add-UV_ENOTSUP-to-isc___nm_uverr2result.patch new file mode 100644 index 0000000000000000000000000000000000000000..09ca63fcca1024585d82123f4bff487a4c58adba --- /dev/null +++ b/backport-0010-add-UV_ENOTSUP-to-isc___nm_uverr2result.patch @@ -0,0 +1,30 @@ +From 464b09a8043e61fb713bd090aac63bf869985248 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Wed, 12 Jan 2022 10:43:18 -0800 +Subject: [PATCH] add UV_ENOTSUP to isc___nm_uverr2result() + +This error code is now mapped to ISC_R_FAMILYNOSUPPORT. + +(cherry picked from commit be0bc24c7f7b22d6e42bc73e3c0c978ca3ae3af3) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/464b09a8043e61fb713bd090aac63bf869985248 +--- + lib/isc/netmgr/uverr2result.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/isc/netmgr/uverr2result.c b/lib/isc/netmgr/uverr2result.c +index 2a1de20954..5ce953d729 100644 +--- a/lib/isc/netmgr/uverr2result.c ++++ b/lib/isc/netmgr/uverr2result.c +@@ -89,6 +89,8 @@ isc___nm_uverr2result(int uverr, bool dolog, const char *file, + return (ISC_R_EOF); + case UV_EMSGSIZE: + return (ISC_R_MAXSIZE); ++ case UV_ENOTSUP: ++ return (ISC_R_FAMILYNOSUPPORT); + default: + if (dolog) { + UNEXPECTED_ERROR( +-- +2.23.0 + diff --git a/backport-0011-rndc-add-an-extra-task-reference.patch b/backport-0011-rndc-add-an-extra-task-reference.patch new file mode 100644 index 0000000000000000000000000000000000000000..f23c615ba59995f9d9a582bca9310fdff0e2e6f1 --- /dev/null +++ b/backport-0011-rndc-add-an-extra-task-reference.patch @@ -0,0 +1,56 @@ +From 075722f8a2ff30396b0b920d4665c1c75dc5f1ba Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Wed, 19 Jan 2022 11:05:00 -0800 +Subject: [PATCH] rndc: add an extra task reference + +adding an extra task before launching the rndc app prevents +a use-after-free when task events fire after the app has been +shut down by a signal. +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/075722f8a2ff30396b0b920d4665c1c75dc5f1ba +--- + bin/rndc/rndc.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c +index 1e74b9b033..6ce9d252f4 100644 +--- a/bin/rndc/rndc.c ++++ b/bin/rndc/rndc.c +@@ -292,8 +292,6 @@ static void + rndc_senddone(isc_task_t *task, isc_event_t *event) { + isc_socketevent_t *sevent = (isc_socketevent_t *)event; + +- UNUSED(task); +- + if (sevent->result != ISC_R_SUCCESS) { + fatal("send failed: %s", isc_result_totext(sevent->result)); + } +@@ -302,7 +300,7 @@ rndc_senddone(isc_task_t *task, isc_event_t *event) { + atomic_load_acquire(&recvs) == 0) + { + isc_socket_detach(&sock); +- isc_task_shutdown(task); ++ isc_task_detach(&task); + isc_app_shutdown(); + } + } +@@ -378,7 +376,7 @@ rndc_recvdone(isc_task_t *task, isc_event_t *event) { + if (atomic_load_acquire(&sends) == 0 && + atomic_load_acquire(&recvs) == 0) { + isc_socket_detach(&sock); +- isc_task_shutdown(task); ++ isc_task_detach(&task); + isc_app_shutdown(); + } + } +@@ -1058,6 +1056,7 @@ main(int argc, char **argv) { + get_addresses(servername, (in_port_t)remoteport); + } + ++ isc_task_attach(task, &(isc_task_t *){ NULL }); + DO("post event", isc_app_onrun(rndc_mctx, task, rndc_start, NULL)); + + result = isc_app_run(); +-- +2.23.0 + diff --git a/backport-0012-Add-a-system-test-for-view-reverting-after-a-failed-.patch b/backport-0012-Add-a-system-test-for-view-reverting-after-a-failed-.patch new file mode 100644 index 0000000000000000000000000000000000000000..f00db1736c180fa8862094be6d420b91b88ea556 --- /dev/null +++ b/backport-0012-Add-a-system-test-for-view-reverting-after-a-failed-.patch @@ -0,0 +1,83 @@ +From 094e416fff2c2c2d0f0d83d4201860e52e65d0ac Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Wed, 29 Dec 2021 09:07:03 +0000 +Subject: [PATCH] Add a system test for view reverting after a failed + reconfiguration + +Test the view reverting code by introducing a faulty dlz configuration +in named.conf and using `rndc reconfig` to check if named handles the +situation correctly. + +We use "dlz" because the dlz processing code is located in an ideal +place in the view configuration function for the test to cover the +view reverting code. + +This test is specifically added to the catz system test to additionally +cover the catz reconfiguration during the mentioned failed +reconfiguration attempt. + +(cherry picked from commit 62337d433f233506d340acdedb7d46bdc0dd662f) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/094e416fff2c2c2d0f0d83d4201860e52e65d0ac +--- + bin/tests/system/catz/ns2/named1.conf.in | 8 ++++++++ + bin/tests/system/catz/tests.sh | 24 ++++++++++++++++++++++++ + 2 files changed, 32 insertions(+) + +diff --git a/bin/tests/system/catz/ns2/named1.conf.in b/bin/tests/system/catz/ns2/named1.conf.in +index 7c5f8c2835..8519802bb0 100644 +--- a/bin/tests/system/catz/ns2/named1.conf.in ++++ b/bin/tests/system/catz/ns2/named1.conf.in +@@ -46,6 +46,14 @@ options { + }; + }; + ++# A faulty dlz configuration to check if named and catz survive a certain class ++# of failed configuration attempts (see GL#3060). ++# We use "dlz" because the dlz processing code is located in an ideal place in ++# the view configuration function for the test to cover the view reverting code. ++#T3dlz "bad-dlz" { ++#T3 database "dlopen bad-dlz.so example.org"; ++#T3}; ++ + zone "catalog1.example" { + type secondary; + file "catalog1.example.db"; +diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh +index f217103d8f..2f50740374 100644 +--- a/bin/tests/system/catz/tests.sh ++++ b/bin/tests/system/catz/tests.sh +@@ -370,6 +370,30 @@ wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status+ret)) + ++n=$((n+1)) ++echo_i "reconfiguring secondary - checking if catz survives a certain class of failed reconfiguration attempts ($n)" ++ret=0 ++sed -e "s/^#T3//" < ns2/named1.conf.in > ns2/named.conf.tmp ++copy_setports ns2/named.conf.tmp ns2/named.conf ++$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig > /dev/null 2>&1 && ret=1 ++if [ $ret -ne 0 ]; then echo_i "failed"; fi ++status=$((status+ret)) ++ ++n=$((n+1)) ++echo_i "checking again that dom3.example. is served by secondary ($n)" ++ret=0 ++wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1 ++if [ $ret -ne 0 ]; then echo_i "failed"; fi ++status=$((status+ret)) ++ ++n=$((n+1)) ++echo_i "reconfiguring secondary - reverting the bad configuration ($n)" ++ret=0 ++copy_setports ns2/named1.conf.in ns2/named.conf ++rndccmd 10.53.0.2 reconfig || ret=1 ++if [ $ret -ne 0 ]; then echo_i "failed"; fi ++status=$((status+ret)) ++ + n=$((n+1)) + echo_i "removing all records from catalog1 zone ($n)" + ret=0 +-- +2.23.0 + diff --git a/backport-0012-Fix-a-memory-leak-in-dns_dlzcreate.patch b/backport-0012-Fix-a-memory-leak-in-dns_dlzcreate.patch new file mode 100644 index 0000000000000000000000000000000000000000..4137d7a061d14ad427c0c9b80e1b713eae9a607c --- /dev/null +++ b/backport-0012-Fix-a-memory-leak-in-dns_dlzcreate.patch @@ -0,0 +1,33 @@ +From 254cabb558cc6152ae892d2a71e65f7cedbd1a38 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Tue, 4 Jan 2022 18:49:20 +0000 +Subject: [PATCH] Fix a memory leak in dns_dlzcreate() + +dns_dlzcreate() fails to free the memory allocated for dlzname +when an error occurs. + +Free dlzname's memory (acquired earlier with isc_mem_strdup()) +by calling isc_mem_free() before returning an error code. + +(cherry picked from commit 4a6c66288ff831a3450e6472605d3ef8d668eac7) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/254cabb558cc6152ae892d2a71e65f7cedbd1a38 +--- + lib/dns/dlz.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c +index cc0b17e5d2..20e3f545bf 100644 +--- a/lib/dns/dlz.c ++++ b/lib/dns/dlz.c +@@ -230,6 +230,7 @@ dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername, + + /* impinfo->methods->create failed. */ + RWUNLOCK(&dlz_implock, isc_rwlocktype_read); ++ isc_mem_free(mctx, db->dlzname); + isc_mem_put(mctx, db, sizeof(dns_dlzdb_t)); + return (result); + } +-- +2.23.0 + diff --git a/backport-0012-Fix-invalid-control-port-number-in-the-catz-system-t.patch b/backport-0012-Fix-invalid-control-port-number-in-the-catz-system-t.patch new file mode 100644 index 0000000000000000000000000000000000000000..65a19e4374a0357bb26f3a69562734dc4b3ded56 --- /dev/null +++ b/backport-0012-Fix-invalid-control-port-number-in-the-catz-system-t.patch @@ -0,0 +1,51 @@ +From b5735ec37a93d2a660ede2f430d08e7abeaf500b Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Tue, 4 Jan 2022 17:22:32 +0000 +Subject: [PATCH] Fix invalid control port number in the catz system test + +When failure is expected, the `rndc` command in the catz system test +is being called directly instead of using a function, i.e.: + + $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig \ + > /dev/null 2>&1 && ret=1 + +... instead of: + + rndccmd 10.53.0.2 reconfig && ret=1 + +This is done to suppress messages like "lt-rndc: 'reconfig' failed: +failure" appearing in the message log of the test, because failure +is actually expected, and the appearance of that message can be +confusing. + +The port value used in this case is not correct, making the +`rndc reload` command to fail. This error was not detected earlier +only because the failure of the command is actually expected, but +the failure happens for a "wrong" reason, and the test still passes. + +Fix the error by using the existing variable instead of the fixed +number. + +(cherry picked from commit 5f9d4b5db41f074699647cfc3033c6ebba61b72e) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/b5735ec37a93d2a660ede2f430d08e7abeaf500b +--- + bin/tests/system/catz/tests.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh +index 2f50740374..97b7e314b4 100644 +--- a/bin/tests/system/catz/tests.sh ++++ b/bin/tests/system/catz/tests.sh +@@ -1238,7 +1238,7 @@ echo_i "reconfiguring secondary - removing catalog4 catalog zone, adding non-exi + ret=0 + sed -e "s/^#T2//" < ns2/named1.conf.in > ns2/named.conf.tmp + copy_setports ns2/named.conf.tmp ns2/named.conf +-$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > /dev/null 2>&1 && ret=1 ++$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig > /dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status+ret)) + +-- +2.23.0 + diff --git a/backport-0012-Improve-the-view-configuration-error-handling-and-re.patch b/backport-0012-Improve-the-view-configuration-error-handling-and-re.patch new file mode 100644 index 0000000000000000000000000000000000000000..e153eaba77a6cc72427be4c9b4a6645a6e73a5b1 --- /dev/null +++ b/backport-0012-Improve-the-view-configuration-error-handling-and-re.patch @@ -0,0 +1,325 @@ +From f555f1d2eb4cf0d0cf2f6aa1203d369aecb7339e Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Tue, 28 Dec 2021 11:51:01 +0000 +Subject: [PATCH] Improve the view configuration error handling and reverting + logic + +If a view configuration error occurs during a named reconfiguration +procedure, BIND can end up having twin views (old and new), with some +zones and internal structures attached to the old one, and others +attached to the new one, which essentially creates chaos. + +Implement some additional view reverting mechanisms to avoid the +situation described above: + + 1. Revert rpz configuration. + + 2. Revert catz configuration. + + 3. Revert zones to view attachments. + +(cherry picked from commit 3697560f048792430640e7f848cdae8547c70d90) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/f555f1d2eb4cf0d0cf2f6aa1203d369aecb7339e +--- + bin/named/server.c | 153 +++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 126 insertions(+), 27 deletions(-) + +diff --git a/bin/named/server.c b/bin/named/server.c +index d8993e06b4..721464db8e 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -437,6 +437,10 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, + cfg_aclconfctx_t *aclconf, bool added, bool old_rpz_ok, + bool modify); + ++static void ++configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, ++ dns_view_t *view); ++ + static isc_result_t + configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + isc_mem_t *mctx, cfg_aclconfctx_t *actx); +@@ -2439,7 +2443,7 @@ configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, + } + + static isc_result_t +-configure_rpz(dns_view_t *view, const cfg_obj_t **maps, ++configure_rpz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t **maps, + const cfg_obj_t *rpz_obj, bool *old_rpz_okp) { + bool dnsrps_enabled; + const cfg_listelt_t *zone_element; +@@ -2453,7 +2457,7 @@ configure_rpz(dns_view_t *view, const cfg_obj_t **maps, + uint32_t minupdateinterval_default; + dns_rpz_zones_t *zones; + const dns_rpz_zones_t *old; +- dns_view_t *pview; ++ bool pview_must_detach = false; + const dns_rpz_zone_t *old_zone; + isc_result_t result; + int i; +@@ -2592,14 +2596,19 @@ configure_rpz(dns_view_t *view, const cfg_obj_t **maps, + zones->p.nsip_wait_recurse = false; + } + +- pview = NULL; +- result = dns_viewlist_find(&named_g_server->viewlist, view->name, +- view->rdclass, &pview); +- if (result == ISC_R_SUCCESS) { ++ if (pview != NULL) { + old = pview->rpzs; + } else { +- old = NULL; ++ result = dns_viewlist_find(&named_g_server->viewlist, ++ view->name, view->rdclass, &pview); ++ if (result == ISC_R_SUCCESS) { ++ pview_must_detach = true; ++ old = pview->rpzs; ++ } else { ++ old = NULL; ++ } + } ++ + if (old == NULL) { + *old_rpz_okp = false; + } else { +@@ -2621,7 +2630,7 @@ configure_rpz(dns_view_t *view, const cfg_obj_t **maps, + add_soa_default, ttl_default, minupdateinterval_default, + old_zone, old_rpz_okp); + if (result != ISC_R_SUCCESS) { +- if (pview != NULL) { ++ if (pview_must_detach) { + dns_view_detach(&pview); + } + return (result); +@@ -2658,7 +2667,7 @@ configure_rpz(dns_view_t *view, const cfg_obj_t **maps, + view->rpzs->rpz_ver); + } + +- if (pview != NULL) { ++ if (pview_must_detach) { + dns_view_detach(&pview); + } + +@@ -2987,15 +2996,14 @@ catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, + } + + static isc_result_t +-configure_catz_zone(dns_view_t *view, const cfg_obj_t *config, +- const cfg_listelt_t *element) { ++configure_catz_zone(dns_view_t *view, dns_view_t *pview, ++ const cfg_obj_t *config, const cfg_listelt_t *element) { + const cfg_obj_t *catz_obj, *obj; + dns_catz_zone_t *zone = NULL; + const char *str; + isc_result_t result; + dns_name_t origin; + dns_catz_options_t *opts; +- dns_view_t *pview = NULL; + + dns_name_init(&origin, NULL); + catz_obj = cfg_listelt_value(element); +@@ -3026,9 +3034,7 @@ configure_catz_zone(dns_view_t *view, const cfg_obj_t *config, + if (result == ISC_R_EXISTS) { + isc_ht_iter_t *it = NULL; + +- result = dns_viewlist_find(&named_g_server->viewlist, +- view->name, view->rdclass, &pview); +- RUNTIME_CHECK(result == ISC_R_SUCCESS); ++ RUNTIME_CHECK(pview != NULL); + + /* + * xxxwpk todo: reconfigure the zone!!!! +@@ -3116,9 +3122,6 @@ configure_catz_zone(dns_view_t *view, const cfg_obj_t *config, + } + + cleanup: +- if (pview != NULL) { +- dns_view_detach(&pview); +- } + dns_name_free(&origin, view->mctx); + + return (result); +@@ -3130,11 +3133,11 @@ static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = { + }; + + static isc_result_t +-configure_catz(dns_view_t *view, const cfg_obj_t *config, ++configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config, + const cfg_obj_t *catz_obj) { + const cfg_listelt_t *zone_element; + const dns_catz_zones_t *old = NULL; +- dns_view_t *pview = NULL; ++ bool pview_must_detach = false; + isc_result_t result; + + /* xxxwpk TODO do it cleaner, once, somewhere */ +@@ -3149,10 +3152,15 @@ configure_catz(dns_view_t *view, const cfg_obj_t *config, + view->mctx, named_g_taskmgr, + named_g_timermgr)); + +- result = dns_viewlist_find(&named_g_server->viewlist, view->name, +- view->rdclass, &pview); +- if (result == ISC_R_SUCCESS) { ++ if (pview != NULL) { + old = pview->catzs; ++ } else { ++ result = dns_viewlist_find(&named_g_server->viewlist, ++ view->name, view->rdclass, &pview); ++ if (result == ISC_R_SUCCESS) { ++ pview_must_detach = true; ++ old = pview->catzs; ++ } + } + + if (old != NULL) { +@@ -3162,7 +3170,7 @@ configure_catz(dns_view_t *view, const cfg_obj_t *config, + } + + while (zone_element != NULL) { +- CHECK(configure_catz_zone(view, config, zone_element)); ++ CHECK(configure_catz_zone(view, pview, config, zone_element)); + zone_element = cfg_list_next(zone_element); + } + +@@ -3173,7 +3181,7 @@ configure_catz(dns_view_t *view, const cfg_obj_t *config, + result = ISC_R_SUCCESS; + + cleanup: +- if (pview != NULL) { ++ if (pview_must_detach) { + dns_view_detach(&pview); + } + +@@ -3974,6 +3982,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, + isc_mem_t *cmctx = NULL, *hmctx = NULL; + dns_dispatch_t *dispatch4 = NULL; + dns_dispatch_t *dispatch6 = NULL; ++ bool rpz_configured = false; ++ bool catz_configured = false; ++ bool zones_configured = false; + bool reused_cache = false; + bool shared_cache = false; + int i = 0, j = 0, k = 0; +@@ -4045,14 +4056,16 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, + if (view->rdclass == dns_rdataclass_in && need_hints && + named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) + { +- CHECK(configure_rpz(view, maps, obj, &old_rpz_ok)); ++ CHECK(configure_rpz(view, NULL, maps, obj, &old_rpz_ok)); ++ rpz_configured = true; + } + + obj = NULL; + if (view->rdclass == dns_rdataclass_in && need_hints && + named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) + { +- CHECK(configure_catz(view, config, obj)); ++ CHECK(configure_catz(view, NULL, config, obj)); ++ catz_configured = true; + } + + /* +@@ -4076,6 +4089,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, + viewlist, kasplist, actx, false, + old_rpz_ok, false)); + } ++ zones_configured = true; + + /* + * Check that a master or slave zone was found for each +@@ -5815,6 +5829,91 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, + result = ISC_R_SUCCESS; + + cleanup: ++ /* ++ * Revert to the old view if there was an error. ++ */ ++ if (result != ISC_R_SUCCESS) { ++ isc_result_t result2; ++ ++ result2 = dns_viewlist_find(&named_g_server->viewlist, ++ view->name, view->rdclass, &pview); ++ if (result2 == ISC_R_SUCCESS) { ++ dns_view_thaw(pview); ++ ++ obj = NULL; ++ if (rpz_configured && ++ pview->rdclass == dns_rdataclass_in && need_hints && ++ named_config_get(maps, "response-policy", &obj) == ++ ISC_R_SUCCESS) ++ { ++ /* ++ * We are swapping the places of the `view` and ++ * `pview` in the function's parameters list ++ * because we are reverting the same operation ++ * done previously in the "correct" order. ++ */ ++ result2 = configure_rpz(pview, view, maps, obj, ++ &old_rpz_ok); ++ if (result2 != ISC_R_SUCCESS) { ++ isc_log_write(named_g_lctx, ++ NAMED_LOGCATEGORY_GENERAL, ++ NAMED_LOGMODULE_SERVER, ++ ISC_LOG_ERROR, ++ "rpz configuration " ++ "revert failed for view " ++ "'%s'", ++ pview->name); ++ } ++ } ++ ++ obj = NULL; ++ if (catz_configured && ++ pview->rdclass == dns_rdataclass_in && need_hints && ++ named_config_get(maps, "catalog-zones", &obj) == ++ ISC_R_SUCCESS) ++ { ++ if (pview->catzs != NULL) { ++ dns_catz_catzs_detach(&pview->catzs); ++ } ++ /* ++ * We are swapping the places of the `view` and ++ * `pview` in the function's parameters list ++ * because we are reverting the same operation ++ * done previously in the "correct" order. ++ */ ++ result2 = configure_catz(pview, view, config, ++ obj); ++ if (result2 != ISC_R_SUCCESS) { ++ isc_log_write(named_g_lctx, ++ NAMED_LOGCATEGORY_GENERAL, ++ NAMED_LOGMODULE_SERVER, ++ ISC_LOG_ERROR, ++ "catz configuration " ++ "revert failed for view " ++ "'%s'", ++ pview->name); ++ } ++ } ++ ++ dns_view_freeze(pview); ++ } ++ ++ if (pview != NULL) { ++ dns_view_detach(&pview); ++ } ++ ++ if (zones_configured) { ++ for (element = cfg_list_first(zonelist); ++ element != NULL; element = cfg_list_next(element)) ++ { ++ const cfg_obj_t *zconfig = ++ cfg_listelt_value(element); ++ configure_zone_setviewcommit(result, zconfig, ++ view); ++ } ++ } ++ } ++ + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } +-- +2.23.0 + diff --git a/backport-0012-Improve-the-zones-view-reverting-logic-when-a-zone-i.patch b/backport-0012-Improve-the-zones-view-reverting-logic-when-a-zone-i.patch new file mode 100644 index 0000000000000000000000000000000000000000..c900fb638dc3fa5081e0738319a69b943a55181b --- /dev/null +++ b/backport-0012-Improve-the-zones-view-reverting-logic-when-a-zone-i.patch @@ -0,0 +1,39 @@ +From a663216c0e63bcbf90dc5142f9914bb02edac144 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Tue, 28 Dec 2021 12:08:48 +0000 +Subject: [PATCH] Improve the zones' view reverting logic when a zone is a + catalog zone + +When a zone is being configured with a new view, the catalog zones +structure will also be linked to that view. Later on, in case of some +error, should the zone be reverted to the previous view, the link +between the catalog zones structure and the view won't be reverted. + +Change the dns_zone_setviewrevert() function so it calls +dns_zone_catz_enable() during a zone revert, which will reset the +link between `catzs` and view. + +(cherry picked from commit 2fd967136ad014f6d7456c1e19e185803f7d99ac) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/a663216c0e63bcbf90dc5142f9914bb02edac144 +--- + lib/dns/zone.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 9205271574..74ecace4a5 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -1674,6 +1674,9 @@ dns_zone_setviewrevert(dns_zone_t *zone) { + dns_zone_setview_helper(zone, zone->prev_view); + dns_view_weakdetach(&zone->prev_view); + } ++ if (zone->catzs != NULL) { ++ zone_catz_enable(zone, zone->catzs); ++ } + if (inline_secure(zone)) { + dns_zone_setviewrevert(zone->raw); + } +-- +2.23.0 + diff --git a/backport-0012-Separate-the-locked-parts-of-dns_zone_catz_enable-di.patch b/backport-0012-Separate-the-locked-parts-of-dns_zone_catz_enable-di.patch new file mode 100644 index 0000000000000000000000000000000000000000..fcdf67524a5b88ec29a7f70d9cb9ffe19a65f088 --- /dev/null +++ b/backport-0012-Separate-the-locked-parts-of-dns_zone_catz_enable-di.patch @@ -0,0 +1,85 @@ +From 885e44650b547cff88095d01769e303474582612 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Wed, 5 Jan 2022 09:38:36 +0000 +Subject: [PATCH] Separate the locked parts of dns_zone_catz_enable/disable + functions + +Separate the locked parts of dns_zone_catz_enable() and +dns_zone_catz_disable() functions into static functions. This will +let us perform those tasks from the other parts of the module while +the zone is locked, avoiding one pair of additional unlocking and +locking operations. + +(cherry picked from commit 6b937ed5f67a13cf6ad6249380073a6e647d7897) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/885e44650b547cff88095d01769e303474582612 +--- + lib/dns/zone.c | 28 +++++++++++++++++++++++----- + 1 file changed, 23 insertions(+), 5 deletions(-) + +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 2faf12519e..9205271574 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -871,6 +871,10 @@ static inline void + zone_attachdb(dns_zone_t *zone, dns_db_t *db); + static inline void + zone_detachdb(dns_zone_t *zone); ++static void ++zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs); ++static void ++zone_catz_disable(dns_zone_t *zone); + static isc_result_t + default_journal(dns_zone_t *zone); + static void +@@ -1930,28 +1934,42 @@ dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) { + zone->rpzs->zones[zone->rpz_num]); + } + +-void +-dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) { ++static void ++zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) { + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(catzs != NULL); + +- LOCK_ZONE(zone); + INSIST(zone->catzs == NULL || zone->catzs == catzs); + dns_catz_catzs_set_view(catzs, zone->view); + if (zone->catzs == NULL) { + dns_catz_catzs_attach(catzs, &zone->catzs); + } +- UNLOCK_ZONE(zone); + } + + void +-dns_zone_catz_disable(dns_zone_t *zone) { ++dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); ++ zone_catz_enable(zone, catzs); ++ UNLOCK_ZONE(zone); ++} ++ ++static void ++zone_catz_disable(dns_zone_t *zone) { ++ REQUIRE(DNS_ZONE_VALID(zone)); ++ + if (zone->catzs != NULL) { + dns_catz_catzs_detach(&zone->catzs); + } ++} ++ ++void ++dns_zone_catz_disable(dns_zone_t *zone) { ++ REQUIRE(DNS_ZONE_VALID(zone)); ++ ++ LOCK_ZONE(zone); ++ zone_catz_disable(zone); + UNLOCK_ZONE(zone); + } + +-- +2.27.0 + diff --git a/backport-0013-Add-log-message-when-hard-quota-is-reached-in-TCP-ac.patch b/backport-0013-Add-log-message-when-hard-quota-is-reached-in-TCP-ac.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e72dca36eb84ea536c7317a974492a74233a2ca --- /dev/null +++ b/backport-0013-Add-log-message-when-hard-quota-is-reached-in-TCP-ac.patch @@ -0,0 +1,48 @@ +From 00e8bfcdfcb004c7585125b4dddd1de8dcf142ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Tue, 1 Feb 2022 18:36:12 +0100 +Subject: [PATCH] Add log message when hard quota is reached in TCP accept + +When isc_quota_attach_cb() API returns ISC_R_QUOTA (meaning hard quota +was reached) the accept_connection() would return without logging a +message about quota reached. + +Change the connection callback to log the quota reached message. + +(cherry picked from commit 2ae84702ad0482cbbd5da4113b47d63b23ffe386) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/00e8bfcdfcb004c7585125b4dddd1de8dcf142ae +--- + lib/isc/netmgr/tcp.c | 2 +- + lib/isc/netmgr/tcpdns.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index 05ef8d8cd5..133d6d9e61 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -627,7 +627,7 @@ tcp_connection_cb(uv_stream_t *server, int status) { + if (result == ISC_R_QUOTA) { + isc__nm_incstats(ssock->mgr, + ssock->statsindex[STATID_ACCEPTFAIL]); +- return; ++ goto done; + } + } + +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index a1f500b352..38c8c692e1 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -596,7 +596,7 @@ tcpdns_connection_cb(uv_stream_t *server, int status) { + if (result == ISC_R_QUOTA) { + isc__nm_incstats(ssock->mgr, + ssock->statsindex[STATID_ACCEPTFAIL]); +- return; ++ goto done; + } + } + +-- +2.23.0 + diff --git a/backport-0014-Add-TCP-TCPDNS-and-TLSDNS-write-timer.patch b/backport-0014-Add-TCP-TCPDNS-and-TLSDNS-write-timer.patch new file mode 100644 index 0000000000000000000000000000000000000000..1e124e24ec56c7da5f05b1493927046a2f6573f4 --- /dev/null +++ b/backport-0014-Add-TCP-TCPDNS-and-TLSDNS-write-timer.patch @@ -0,0 +1,452 @@ +From 6a88131d034ed58d3f0774721caa1e222fc7c245 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 9 Feb 2022 11:21:04 +0100 +Subject: [PATCH] Add TCP, TCPDNS and TLSDNS write timer + +When the outgoing TCP write buffers are full because the other party is +not reading the data, the uv_write() could wait indefinitely on the +uv_loop and never calling the callback. Add a new write timer that uses +the `tcp-idle-timeout` value to interrupt the TCP connection when we are +not able to send data for defined period of time. + +(cherry picked from commit 408b3621696e39ac6dfe58be75fad168a37b31ff) +Conflict: UV_RUNTIME_CHECK to RUNTIME_CHECK +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/6a88131d034ed58d3f0774721caa1e222fc7c245 +--- + lib/isc/netmgr/netmgr-int.h | 24 ++++++++++++++-- + lib/isc/netmgr/netmgr.c | 18 +++++++++++- + lib/isc/netmgr/tcp.c | 51 +++++++++++++++++++++++++++++++-- + lib/isc/netmgr/tcpdns.c | 56 ++++++++++++++++++++++++++++++------- + lib/isc/netmgr/udp.c | 32 +++++++++++++++++++-- + 5 files changed, 162 insertions(+), 19 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index 6c6cf13..f22ecbc 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -753,6 +753,13 @@ struct isc_nmsocket { + uint64_t read_timeout; + uint64_t connect_timeout; + ++ /*% ++ * TCP write timeout timer. ++ */ ++ uv_timer_t write_timer; ++ uint64_t write_timeout; ++ int64_t writes; ++ + /*% outer socket is for 'wrapped' sockets - e.g. tcpdns in tcp */ + isc_nmsocket_t *outer; + +@@ -1574,9 +1581,22 @@ void + isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, bool async); + + void +-isc__nmsocket_connecttimeout_cb(uv_timer_t *timer); ++isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota); + ++/* ++ * Timeout callbacks ++ */ + void +-isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota); ++isc__nmsocket_connecttimeout_cb(uv_timer_t *timer); ++void ++isc__nmsocket_readtimeout_cb(uv_timer_t *timer); ++void ++isc__nmsocket_writetimeout_cb(uv_timer_t *timer); + ++/*%< ++ * ++ * Maximum number of simultaneous handles in flight supported for a single ++ * connected TCPDNS socket. This value was chosen arbitrarily, and may be ++ * changed in the future. ++ */ + #define STREAM_CLIENTS_PER_CONN 23 +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index f7acd0c..bbc66cd 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -2000,7 +2000,21 @@ isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota) { + isc_result_totext(result)); + } + +-static void ++void ++isc__nmsocket_writetimeout_cb(uv_timer_t *timer) { ++ isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer); ++ ++ int r = uv_timer_stop(&sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); ++ ++ /* The shutdown will be handled in the respective close functions */ ++ r = uv_tcp_close_reset(&sock->uv_handle.tcp, NULL); ++ UV_RUNTIME_CHECK(uv_tcp_close_reset, r); ++ ++ isc__nmsocket_shutdown(sock); ++} ++ ++void + isc__nmsocket_readtimeout_cb(uv_timer_t *timer) { + isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer); + +@@ -2333,6 +2347,8 @@ isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value) { + atomic_store(&sock->keepalive, value); + sock->read_timeout = value ? atomic_load(&sock->mgr->keepalive) + : atomic_load(&sock->mgr->idle); ++ sock->write_timeout = value ? atomic_load(&sock->mgr->keepalive) ++ : atomic_load(&sock->mgr->idle); + break; + default: + /* +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index 7339f77..e7605de 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -142,6 +142,10 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + ++ r = uv_timer_init(&worker->loop, &sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ + r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); + if (r != 0) { + isc__nm_closesocket(sock->fd); +@@ -531,6 +535,10 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { + + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + ++ r = uv_timer_init(&worker->loop, &sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ + LOCK(&sock->parent->lock); + + r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); +@@ -971,6 +979,10 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock); + ++ r = uv_timer_init(&worker->loop, &csock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&csock->write_timer, csock); ++ + r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream); + if (r != 0) { + result = isc__nm_uverr2result(r); +@@ -1064,6 +1076,13 @@ isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region, + uvreq->cb.send = cb; + uvreq->cbarg = cbarg; + ++ if (sock->write_timeout == 0) { ++ sock->write_timeout = ++ (atomic_load(&sock->keepalive) ++ ? atomic_load(&sock->mgr->keepalive) ++ : atomic_load(&sock->mgr->idle)); ++ } ++ + ievent = isc__nm_get_netievent_tcpsend(sock->mgr, sock, uvreq); + isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid], + (isc__netievent_t *)ievent); +@@ -1074,11 +1093,17 @@ isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region, + static void + tcp_send_cb(uv_write_t *req, int status) { + isc__nm_uvreq_t *uvreq = (isc__nm_uvreq_t *)req->data; ++ + REQUIRE(VALID_UVREQ(uvreq)); + REQUIRE(VALID_NMHANDLE(uvreq->handle)); + + isc_nmsocket_t *sock = uvreq->sock; + ++ if (--sock->writes == 0) { ++ int r = uv_timer_stop(&sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); ++ } ++ + if (status < 0) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]); + failed_send_cb(sock, uvreq, isc__nm_uverr2result(status)); +@@ -1122,6 +1147,11 @@ tcp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + return (ISC_R_CANCELED); + } + ++ r = uv_timer_start(&sock->write_timer, isc__nmsocket_writetimeout_cb, ++ sock->write_timeout, 0); ++ UV_RUNTIME_CHECK(uv_timer_start, r); ++ RUNTIME_CHECK(sock->writes++ >= 0); ++ + r = uv_write(&req->uv_req.write, &sock->uv_handle.stream, &req->uvbuf, + 1, tcp_send_cb); + if (r < 0) { +@@ -1185,7 +1215,7 @@ tcp_close_cb(uv_handle_t *handle) { + } + + static void +-timer_close_cb(uv_handle_t *handle) { ++read_timer_close_cb(uv_handle_t *handle) { + isc_nmsocket_t *sock = uv_handle_get_data(handle); + uv_handle_set_data(handle, NULL); + +@@ -1198,6 +1228,17 @@ timer_close_cb(uv_handle_t *handle) { + } + } + ++static void ++write_timer_close_cb(uv_handle_t *timer) { ++ isc_nmsocket_t *sock = uv_handle_get_data(timer); ++ uv_handle_set_data(timer, NULL); ++ ++ REQUIRE(VALID_NMSOCK(sock)); ++ ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); ++} ++ + static void + stop_tcp_child(isc_nmsocket_t *sock) { + REQUIRE(sock->type == isc_nm_tcpsocket); +@@ -1250,6 +1291,8 @@ stop_tcp_parent(isc_nmsocket_t *sock) { + + static void + tcp_close_direct(isc_nmsocket_t *sock) { ++ int r; ++ + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + REQUIRE(atomic_load(&sock->closing)); +@@ -1271,8 +1314,10 @@ tcp_close_direct(isc_nmsocket_t *sock) { + isc__nmsocket_timer_stop(sock); + isc__nm_stop_reading(sock); + +- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); +- uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb); ++ r = uv_timer_stop(&sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb); + } + + void +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index 7aaaee9..a822aa2 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -35,13 +35,6 @@ + #include "netmgr-int.h" + #include "uv-compat.h" + +-/*%< +- * +- * Maximum number of simultaneous handles in flight supported for a single +- * connected TCPDNS socket. This value was chosen arbitrarily, and may be +- * changed in the future. +- */ +- + static atomic_uint_fast32_t last_tcpdnsquota_log = ATOMIC_VAR_INIT(0); + + static bool +@@ -107,6 +100,10 @@ tcpdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + ++ r = uv_timer_init(&worker->loop, &sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ + if (isc__nm_closing(sock)) { + result = ISC_R_CANCELED; + goto error; +@@ -500,6 +497,10 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + ++ r = uv_timer_init(&worker->loop, &sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ + LOCK(&sock->parent->lock); + + r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); +@@ -945,6 +946,10 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock); + ++ r = uv_timer_init(&worker->loop, &csock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&csock->write_timer, csock); ++ + r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream); + if (r != 0) { + result = isc__nm_uverr2result(r); +@@ -1059,6 +1064,13 @@ isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region, + uvreq->cb.send = cb; + uvreq->cbarg = cbarg; + ++ if (sock->write_timeout == 0) { ++ sock->write_timeout = ++ (atomic_load(&sock->keepalive) ++ ? atomic_load(&sock->mgr->keepalive) ++ : atomic_load(&sock->mgr->idle)); ++ } ++ + ievent = isc__nm_get_netievent_tcpdnssend(sock->mgr, sock, uvreq); + isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid], + (isc__netievent_t *)ievent); +@@ -1076,6 +1088,11 @@ tcpdns_send_cb(uv_write_t *req, int status) { + + sock = uvreq->sock; + ++ if (--sock->writes == 0) { ++ int r = uv_timer_stop(&sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); ++ } ++ + if (status < 0) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]); + isc__nm_failed_send_cb(sock, uvreq, +@@ -1140,6 +1157,11 @@ isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) { + goto fail; + } + ++ r = uv_timer_start(&sock->write_timer, isc__nmsocket_writetimeout_cb, ++ sock->write_timeout, 0); ++ UV_RUNTIME_CHECK(uv_timer_start, r); ++ RUNTIME_CHECK(sock->writes++ >= 0); ++ + r = uv_write(&uvreq->uv_req.write, &sock->uv_handle.stream, bufs, nbufs, + tcpdns_send_cb); + if (r < 0) { +@@ -1212,7 +1234,7 @@ tcpdns_close_cb(uv_handle_t *handle) { + } + + static void +-timer_close_cb(uv_handle_t *timer) { ++read_timer_close_cb(uv_handle_t *timer) { + isc_nmsocket_t *sock = uv_handle_get_data(timer); + uv_handle_set_data(timer, NULL); + +@@ -1227,6 +1249,17 @@ timer_close_cb(uv_handle_t *timer) { + } + } + ++static void ++write_timer_close_cb(uv_handle_t *timer) { ++ isc_nmsocket_t *sock = uv_handle_get_data(timer); ++ uv_handle_set_data(timer, NULL); ++ ++ REQUIRE(VALID_NMSOCK(sock)); ++ ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); ++} ++ + static void + stop_tcpdns_child(isc_nmsocket_t *sock) { + REQUIRE(sock->type == isc_nm_tcpdnssocket); +@@ -1279,6 +1312,7 @@ stop_tcpdns_parent(isc_nmsocket_t *sock) { + + static void + tcpdns_close_direct(isc_nmsocket_t *sock) { ++ int r; + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + REQUIRE(atomic_load(&sock->closing)); +@@ -1294,8 +1328,10 @@ tcpdns_close_direct(isc_nmsocket_t *sock) { + isc__nmsocket_timer_stop(sock); + isc__nm_stop_reading(sock); + +- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); +- uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb); ++ r = uv_timer_stop(&sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb); + } + + void +diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c +index d33dc4c..d3fffe0 100644 +--- a/lib/isc/netmgr/udp.c ++++ b/lib/isc/netmgr/udp.c +@@ -46,7 +46,10 @@ static void + udp_close_cb(uv_handle_t *handle); + + static void +-timer_close_cb(uv_handle_t *handle); ++read_timer_close_cb(uv_handle_t *handle); ++ ++static void ++write_timer_close_cb(uv_handle_t *handle); + + static void + udp_close_direct(isc_nmsocket_t *sock); +@@ -230,6 +233,10 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + ++ r = uv_timer_init(&worker->loop, &sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ + LOCK(&sock->parent->lock); + + r = uv_udp_open(&sock->uv_handle.udp, sock->fd); +@@ -628,6 +635,10 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + ++ r = uv_timer_init(&worker->loop, &sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ + r = uv_udp_open(&sock->uv_handle.udp, sock->fd); + if (r != 0) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]); +@@ -972,7 +983,7 @@ udp_close_cb(uv_handle_t *handle) { + } + + static void +-timer_close_cb(uv_handle_t *handle) { ++read_timer_close_cb(uv_handle_t *handle) { + isc_nmsocket_t *sock = uv_handle_get_data(handle); + uv_handle_set_data(handle, NULL); + +@@ -983,6 +994,17 @@ timer_close_cb(uv_handle_t *handle) { + } + } + ++static void ++write_timer_close_cb(uv_handle_t *timer) { ++ isc_nmsocket_t *sock = uv_handle_get_data(timer); ++ uv_handle_set_data(timer, NULL); ++ ++ REQUIRE(VALID_NMSOCK(sock)); ++ ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); ++} ++ + static void + stop_udp_child(isc_nmsocket_t *sock) { + REQUIRE(sock->type == isc_nm_udpsocket); +@@ -1035,10 +1057,14 @@ stop_udp_parent(isc_nmsocket_t *sock) { + + static void + udp_close_direct(isc_nmsocket_t *sock) { ++ int r; + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + +- uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb); ++ r = uv_timer_stop(&sock->write_timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); ++ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); ++ uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb); + } + + void +-- +2.27.0 + diff --git a/backport-0014-Add-TCP-write-timeout-system-test.patch b/backport-0014-Add-TCP-write-timeout-system-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..824523e94297a157b27adb9afe2da22913a4fb6b --- /dev/null +++ b/backport-0014-Add-TCP-write-timeout-system-test.patch @@ -0,0 +1,102 @@ +From 260b4c02cf3540e4a71b22f573958da24d89c7a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 9 Feb 2022 12:46:29 +0100 +Subject: [PATCH] Add TCP write timeout system test + +Extend the timeouts system test that bursts the queries for large TXT +record and never read any responses back filling up the server TCP write +buffer. The test should work with the default wmem_max value on +Linux (208k). + +(cherry picked from commit b735182ae0912759f5576557ade7660f4ea9c949) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/260b4c02cf3540e4a71b22f573958da24d89c7a2 +--- + bin/tests/system/timeouts/setup.sh | 5 ++++ + bin/tests/system/timeouts/tests-tcp.py | 36 +++++++++++++++++++++++--- + 2 files changed, 38 insertions(+), 3 deletions(-) + +diff --git a/bin/tests/system/timeouts/setup.sh b/bin/tests/system/timeouts/setup.sh +index 2e8fd6a6ba..c4019d2a27 100644 +--- a/bin/tests/system/timeouts/setup.sh ++++ b/bin/tests/system/timeouts/setup.sh +@@ -20,6 +20,11 @@ copy_setports ns1/named.conf.in ns1/named.conf + # tcp-initial-timeout interval + # + $PYTHON -c " ++print('large IN TXT', end=' ') ++for a in range(128): ++ print('\"%s\"' % ('A' * 240), end=' ') ++print('') ++ + for a in range(150000): + print('%s IN NS a' % (a)) + print('%s IN NS b' % (a))" > ns1/large.db +diff --git a/bin/tests/system/timeouts/tests-tcp.py b/bin/tests/system/timeouts/tests-tcp.py +index 2c5e99cc1c..e1f19608c8 100644 +--- a/bin/tests/system/timeouts/tests-tcp.py ++++ b/bin/tests/system/timeouts/tests-tcp.py +@@ -51,7 +51,7 @@ def test_initial_timeout(port): + try: + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + (response, rtime) = dns.query.receive_tcp(sock, timeout()) +- except ConnectionResetError as e: ++ except ConnectionError as e: + raise EOFError from e + + +@@ -83,7 +83,7 @@ def test_idle_timeout(port): + try: + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + (response, rtime) = dns.query.receive_tcp(sock, timeout()) +- except ConnectionResetError as e: ++ except ConnectionError as e: + raise EOFError from e + + +@@ -152,7 +152,7 @@ def test_pipelining_timeout(port): + try: + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + (response, rtime) = dns.query.receive_tcp(sock, timeout()) +- except ConnectionResetError as e: ++ except ConnectionError as e: + raise EOFError from e + + +@@ -190,3 +190,33 @@ def test_long_axfr(port): + if soa is not None: + break + assert soa is not None ++ ++ ++@pytest.mark.dnspython ++@pytest.mark.dnspython2 ++def test_send_timeout(port): ++ import dns.query ++ ++ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: ++ sock.connect(("10.53.0.1", port)) ++ ++ # Send and receive single large RDATA over TCP ++ msg = create_msg("large.example.", "TXT") ++ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) ++ (response, rtime) = dns.query.receive_tcp(sock, timeout()) ++ ++ # Send and receive 28 large (~32k) DNS queries that should ++ # fill the default maximum 208k TCP send buffer ++ for n in range(28): ++ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) ++ ++ # configure idle interval is 5 seconds, sleep 6 to make sure we are ++ # above the interval ++ time.sleep(6) ++ ++ with pytest.raises(EOFError): ++ try: ++ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) ++ (response, rtime) = dns.query.receive_tcp(sock, timeout()) ++ except ConnectionError as e: ++ raise EOFError from e +-- +2.23.0 + diff --git a/backport-0014-Add-isc_nmhandle_setwritetimeout-function.patch b/backport-0014-Add-isc_nmhandle_setwritetimeout-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..eee32b9a8ebd9dd097956b4cd54c52c740150b41 --- /dev/null +++ b/backport-0014-Add-isc_nmhandle_setwritetimeout-function.patch @@ -0,0 +1,64 @@ +From 1d0f2eb2c495a079101b6f6fd66ff22d95a4ab04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 9 Feb 2022 19:48:13 +0100 +Subject: [PATCH] Add isc_nmhandle_setwritetimeout() function + +In some situations (unit test and forthcoming XFR timeouts MR), we need +to modify the write timeout independently of the read timeout. Add a +isc_nmhandle_setwritetimeout() function that could be called before +isc_nm_send() to specify a custom write timeout interval. + +(cherry picked from commit a89d9e0fa68b8d915c6a1c416543dd157d8b0b5a) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/1d0f2eb2c495a079101b6f6fd66ff22d95a4ab04 +--- + lib/isc/include/isc/netmgr.h | 3 +++ + lib/isc/netmgr/netmgr.c | 8 ++++++++ + lib/isc/win32/libisc.def.in | 1 + + 3 files changed, 12 insertions(+) + +diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h +index f8477b0018..39dba1d376 100644 +--- a/lib/isc/include/isc/netmgr.h ++++ b/lib/isc/include/isc/netmgr.h +@@ -489,3 +489,6 @@ isc__nm_force_tid(int tid); + * Force the thread ID to 'tid'. This is STRICTLY for use in unit + * tests and should not be used in any production code. + */ ++ ++void ++isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout); +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 6bc8c64337..31917be101 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -639,6 +639,14 @@ isc_nm_maxudp(isc_nm_t *mgr, uint32_t maxudp) { + atomic_store(&mgr->maxudp, maxudp); + } + ++void ++isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout) { ++ REQUIRE(VALID_NMHANDLE(handle)); ++ REQUIRE(VALID_NMSOCK(handle->sock)); ++ ++ handle->sock->write_timeout = write_timeout; ++} ++ + void + isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle, + uint32_t keepalive, uint32_t advertised) { +diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in +index de65c63b7d..79e7b64a58 100644 +--- a/lib/isc/win32/libisc.def.in ++++ b/lib/isc/win32/libisc.def.in +@@ -457,6 +457,7 @@ isc_nmhandle_localaddr + isc_nmhandle_peeraddr + isc_nmhandle_setdata + isc_nmhandle_settimeout ++isc_nmhandle_setwritetimeout + isc_nm_attach + isc_nm_cancelread + isc_nm_detach +-- +2.23.0 + diff --git a/backport-0014-Rename-sock-timer-to-sock-read_timer.patch b/backport-0014-Rename-sock-timer-to-sock-read_timer.patch new file mode 100644 index 0000000000000000000000000000000000000000..eecdc8d1c580547fa873c4d3e56b272f5cb38393 --- /dev/null +++ b/backport-0014-Rename-sock-timer-to-sock-read_timer.patch @@ -0,0 +1,279 @@ +From eb2463115fcf033b7756c1eeb036696e0595acbd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 9 Feb 2022 10:59:08 +0100 +Subject: [PATCH] Rename sock->timer to sock->read_timer + +Before adding the write timer, we have to remove the generic sock->timer +to sock->read_timer. We don't touch the function names to limit the +impact of the refactoring. + +(cherry picked from commit 45a73c113f2982b7171632d75d4bbb51d4e6bb53) +Conflict: UV_RUNTIME_CHECK to RUNTIME_CHECK +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/eb2463115fcf033b7756c1eeb036696e0595acbd +--- + lib/isc/netmgr/netmgr-int.h | 2 +- + lib/isc/netmgr/netmgr.c | 13 +++++++------ + lib/isc/netmgr/tcp.c | 23 ++++++++++++----------- + lib/isc/netmgr/tcpdns.c | 20 +++++++++++--------- + lib/isc/netmgr/udp.c | 10 +++++----- + 5 files changed, 36 insertions(+), 32 deletions(-) +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index b4299d5..6c6cf13 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -749,7 +749,7 @@ struct isc_nmsocket { + /*% + * TCP read/connect timeout timers. + */ +- uv_timer_t timer; ++ uv_timer_t read_timer; + uint64_t read_timeout; + uint64_t connect_timeout; + +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 2867d25..f7acd0c 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -1913,7 +1913,7 @@ isc__nm_failed_connect_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, + REQUIRE(req->cb.connect != NULL); + + isc__nmsocket_timer_stop(sock); +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + INSIST(atomic_compare_exchange_strong(&sock->connecting, + &(bool){ true }, false)); +@@ -2036,7 +2036,7 @@ isc__nmsocket_timer_restart(isc_nmsocket_t *sock) { + return; + } + +- r = uv_timer_start(&sock->timer, ++ r = uv_timer_start(&sock->read_timer, + isc__nmsocket_connecttimeout_cb, + sock->connect_timeout + 10, 0); + +@@ -2045,7 +2045,8 @@ isc__nmsocket_timer_restart(isc_nmsocket_t *sock) { + return; + } + +- r = uv_timer_start(&sock->timer, isc__nmsocket_readtimeout_cb, ++ r = uv_timer_start(&sock->read_timer, ++ isc__nmsocket_readtimeout_cb, + sock->read_timeout, 0); + } + +@@ -2056,7 +2057,7 @@ bool + isc__nmsocket_timer_running(isc_nmsocket_t *sock) { + REQUIRE(VALID_NMSOCK(sock)); + +- return (uv_is_active((uv_handle_t *)&sock->timer)); ++ return (uv_is_active((uv_handle_t *)&sock->read_timer)); + } + + void +@@ -2076,7 +2077,7 @@ isc__nmsocket_timer_stop(isc_nmsocket_t *sock) { + + /* uv_timer_stop() is idempotent, no need to check if running */ + +- int r = uv_timer_stop(&sock->timer); ++ int r = uv_timer_stop(&sock->read_timer); + RUNTIME_CHECK(r == 0); + } + +@@ -2299,7 +2300,7 @@ isc_nmhandle_cleartimeout(isc_nmhandle_t *handle) { + default: + handle->sock->read_timeout = 0; + +- if (uv_is_active((uv_handle_t *)&handle->sock->timer)) { ++ if (uv_is_active((uv_handle_t *)&handle->sock->read_timer)) { + isc__nmsocket_timer_stop(handle->sock); + } + } +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index 1ac7808..7339f77 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -138,8 +138,9 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data(&sock->uv_handle.handle, sock); + +- r = uv_timer_init(&worker->loop, &sock->timer); ++ r = uv_timer_init(&worker->loop, &sock->read_timer); + RUNTIME_CHECK(r == 0); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); + if (r != 0) { +@@ -168,7 +169,8 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + } + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]); + +- uv_handle_set_data((uv_handle_t *)&sock->timer, &req->uv_req.connect); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, ++ &req->uv_req.connect); + isc__nmsocket_timer_start(sock); + + atomic_store(&sock->connected, true); +@@ -229,7 +231,7 @@ tcp_connect_cb(uv_connect_t *uvreq, int status) { + REQUIRE(sock->tid == isc_nm_tid()); + + isc__nmsocket_timer_stop(sock); +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + if (!atomic_load(&sock->connecting)) { + return; +@@ -524,10 +526,10 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { + /* This keeps the socket alive after everything else is gone */ + isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL }); + +- r = uv_timer_init(&worker->loop, &sock->timer); ++ r = uv_timer_init(&worker->loop, &sock->read_timer); + RUNTIME_CHECK(r == 0); + +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + LOCK(&sock->parent->lock); + +@@ -965,9 +967,9 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data(&csock->uv_handle.handle, csock); + +- r = uv_timer_init(&worker->loop, &csock->timer); ++ r = uv_timer_init(&worker->loop, &csock->read_timer); + RUNTIME_CHECK(r == 0); +- uv_handle_set_data((uv_handle_t *)&csock->timer, csock); ++ uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock); + + r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream); + if (r != 0) { +@@ -1269,8 +1271,8 @@ tcp_close_direct(isc_nmsocket_t *sock) { + isc__nmsocket_timer_stop(sock); + isc__nm_stop_reading(sock); + +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); +- uv_close((uv_handle_t *)&sock->timer, timer_close_cb); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb); + } + + void +@@ -1388,7 +1390,7 @@ isc__nm_async_tcpcancel(isc__networker_t *worker, isc__netievent_t *ev0) { + REQUIRE(sock->tid == isc_nm_tid()); + UNUSED(worker); + +- uv_timer_stop(&sock->timer); ++ uv_timer_stop(&sock->read_timer); + + isc__nm_tcp_failed_read_cb(sock, ISC_R_EOF); + } +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index 7f66da0..7aaaee9 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -103,8 +103,9 @@ tcpdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data(&sock->uv_handle.handle, sock); + +- r = uv_timer_init(&worker->loop, &sock->timer); ++ r = uv_timer_init(&worker->loop, &sock->read_timer); + RUNTIME_CHECK(r == 0); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + if (isc__nm_closing(sock)) { + result = ISC_R_CANCELED; +@@ -142,7 +143,8 @@ tcpdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + } + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]); + +- uv_handle_set_data((uv_handle_t *)&sock->timer, &req->uv_req.connect); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, ++ &req->uv_req.connect); + isc__nmsocket_timer_start(sock); + + atomic_store(&sock->connected, true); +@@ -203,7 +205,7 @@ tcpdns_connect_cb(uv_connect_t *uvreq, int status) { + REQUIRE(sock->tid == isc_nm_tid()); + + isc__nmsocket_timer_stop(sock); +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + if (!atomic_load(&sock->connecting)) { + return; +@@ -494,9 +496,9 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) { + /* This keeps the socket alive after everything else is gone */ + isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL }); + +- r = uv_timer_init(&worker->loop, &sock->timer); ++ r = uv_timer_init(&worker->loop, &sock->read_timer); + RUNTIME_CHECK(r == 0); +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + LOCK(&sock->parent->lock); + +@@ -939,9 +941,9 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data(&csock->uv_handle.handle, csock); + +- r = uv_timer_init(&worker->loop, &csock->timer); ++ r = uv_timer_init(&worker->loop, &csock->read_timer); + RUNTIME_CHECK(r == 0); +- uv_handle_set_data((uv_handle_t *)&csock->timer, csock); ++ uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock); + + r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream); + if (r != 0) { +@@ -1292,8 +1294,8 @@ tcpdns_close_direct(isc_nmsocket_t *sock) { + isc__nmsocket_timer_stop(sock); + isc__nm_stop_reading(sock); + +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); +- uv_close((uv_handle_t *)&sock->timer, timer_close_cb); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb); + } + + void +diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c +index a91c425..d33dc4c 100644 +--- a/lib/isc/netmgr/udp.c ++++ b/lib/isc/netmgr/udp.c +@@ -226,9 +226,9 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) { + /* This keeps the socket alive after everything else is gone */ + isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL }); + +- r = uv_timer_init(&worker->loop, &sock->timer); ++ r = uv_timer_init(&worker->loop, &sock->read_timer); + RUNTIME_CHECK(r == 0); +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + LOCK(&sock->parent->lock); + +@@ -624,9 +624,9 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data(&sock->uv_handle.handle, sock); + +- r = uv_timer_init(&worker->loop, &sock->timer); ++ r = uv_timer_init(&worker->loop, &sock->read_timer); + RUNTIME_CHECK(r == 0); +- uv_handle_set_data((uv_handle_t *)&sock->timer, sock); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + + r = uv_udp_open(&sock->uv_handle.udp, sock->fd); + if (r != 0) { +@@ -1038,7 +1038,7 @@ udp_close_direct(isc_nmsocket_t *sock) { + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + +- uv_close((uv_handle_t *)&sock->timer, timer_close_cb); ++ uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb); + } + + void +-- +2.27.0 + diff --git a/backport-0014-Update-writetimeout-to-be-T_IDLE-in-netmgr_test.c.patch b/backport-0014-Update-writetimeout-to-be-T_IDLE-in-netmgr_test.c.patch new file mode 100644 index 0000000000000000000000000000000000000000..72e73c4a07693914efc6a108380c1adde57f34f7 --- /dev/null +++ b/backport-0014-Update-writetimeout-to-be-T_IDLE-in-netmgr_test.c.patch @@ -0,0 +1,40 @@ +From 3f24bd2bce5134a5eaac4136e1d363c567c46a94 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Thu, 10 Feb 2022 08:42:22 +0100 +Subject: [PATCH] Update writetimeout to be T_IDLE in netmgr_test.c + +Use the isc_nmhandle_setwritetimeout() function in the netmgr unit test +to allow more time for writing and reading the responses because some of +the intervals that are used in the unit tests are really small leaving a +little room for any delays. + +(cherry picked from commit ee359d6ffa701e5f9781ec75622af22736506bdd) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/3f24bd2bce5134a5eaac4136e1d363c567c46a94 +--- + lib/isc/tests/netmgr_test.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/isc/tests/netmgr_test.c b/lib/isc/tests/netmgr_test.c +index 41113ab7c8..50890e0ab5 100644 +--- a/lib/isc/tests/netmgr_test.c ++++ b/lib/isc/tests/netmgr_test.c +@@ -418,6 +418,7 @@ connect_send(isc_nmhandle_t *handle) { + isc_nmhandle_t *sendhandle = NULL; + isc_refcount_increment0(&active_csends); + isc_nmhandle_attach(handle, &sendhandle); ++ isc_nmhandle_setwritetimeout(handle, T_IDLE); + if (atomic_fetch_sub(&nsends, 1) > 1) { + isc_nm_send(sendhandle, (isc_region_t *)&send_msg, + connect_send_cb, NULL); +@@ -529,6 +530,7 @@ listen_read_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_nmhandle_t *sendhandle = NULL; + isc_nmhandle_attach(handle, &sendhandle); + isc_refcount_increment0(&active_ssends); ++ isc_nmhandle_setwritetimeout(sendhandle, T_IDLE); + isc_nm_send(sendhandle, (isc_region_t *)&send_msg, + listen_send_cb, cbarg); + } +-- +2.23.0 + diff --git a/backport-0015-Fix-more-ns_statscounter_recursclients-underflows.patch b/backport-0015-Fix-more-ns_statscounter_recursclients-underflows.patch new file mode 100644 index 0000000000000000000000000000000000000000..b1bca109a8b759527bc0b7bfc374a9a20b8f0f8f --- /dev/null +++ b/backport-0015-Fix-more-ns_statscounter_recursclients-underflows.patch @@ -0,0 +1,185 @@ +From 60e82835ecc0791b2de5131eeb7c636b000577f2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= +Date: Wed, 23 Feb 2022 14:39:11 +0100 +Subject: [PATCH] Fix more ns_statscounter_recursclients underflows +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit aab691d51266f552a7923db32686fb9398b1d255 did not fix all possible +scenarios in which the ns_statscounter_recursclients counter underflows. +The solution implemented therein can be ineffective e.g. when CNAME +chaining happens with prefetching enabled. + +Here is an example recursive resolution scenario in which the +ns_statscounter_recursclients counter can underflow with the current +logic in effect: + + 1. Query processing starts, the answer is not found in the cache, so + recursion is started. The NS_CLIENTATTR_RECURSING attribute is set. + ns_statscounter_recursclients is incremented (Δ = +1). + + 2. Recursion completes, returning a CNAME. client->recursionquota is + non-NULL, so the NS_CLIENTATTR_RECURSING attribute remains set. + ns_statscounter_recursclients is decremented (Δ = 0). + + 3. Query processing restarts. + + 4. The current QNAME (the target of the CNAME from step 2) is found in + the cache, with a TTL low enough to trigger a prefetch. + + 5. query_prefetch() attaches to client->recursionquota. + ns_statscounter_recursclients is not incremented because + query_prefetch() does not do that (Δ = 0). + + 6. Query processing restarts. + + 7. The current QNAME (the target of the CNAME from step 4) is not found + in the cache, so recursion is started. client->recursionquota is + already attached to (since step 5) and the NS_CLIENTATTR_RECURSING + attribute is set (since step 1), so ns_statscounter_recursclients is + not incremented (Δ = 0). + + 8. The prefetch from step 5 completes. client->recursionquota is + detached from in prefetch_done(). ns_statscounter_recursclients is + not decremented because prefetch_done() does not do that (Δ = 0). + + 9. Recursion for the current QNAME completes. client->recursionquota + is already detached from, i.e. set to NULL (since step 8), and the + NS_CLIENTATTR_RECURSING attribute is set (since step 1), so + ns_statscounter_recursclients is decremented (Δ = -1). + +Another possible scenario is that after step 7, recursion for the target +of the CNAME from step 4 completes before the prefetch for the CNAME +itself. fetch_callback() then notices that client->recursionquota is +non-NULL and decrements ns_statscounter_recursclients, even though +client->recursionquota was attached to by query_prefetch() and therefore +not accompanied by an incrementation of ns_statscounter_recursclients. +The net result is also an underflow. + +Instead of trying to properly handle all possible orderings of events +set into motion by normal recursion and prefetch-triggered recursion, +adjust ns_statscounter_recursclients whenever the recursive clients +quota is successfully attached to or detached from. Remove the +NS_CLIENTATTR_RECURSING attribute altogether as its only purpose is made +obsolete by this change. + +(cherry picked from commit f7482b68b9623cad01f21fc8816d84a29183f2d1) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/60e82835ecc0791b2de5131eeb7c636b000577f2 +--- + lib/ns/include/ns/client.h | 3 +-- + lib/ns/query.c | 46 +++++++++++++++----------------------- + 2 files changed, 19 insertions(+), 30 deletions(-) + +diff --git a/lib/ns/include/ns/client.h b/lib/ns/include/ns/client.h +index 1fd08633d3..91e8ccf8dc 100644 +--- a/lib/ns/include/ns/client.h ++++ b/lib/ns/include/ns/client.h +@@ -270,8 +270,7 @@ struct ns_client { + #define NS_CLIENTATTR_WANTPAD 0x08000 /*%< pad reply */ + #define NS_CLIENTATTR_USEKEEPALIVE 0x10000 /*%< use TCP keepalive */ + +-#define NS_CLIENTATTR_NOSETFC 0x20000 /*%< don't set servfail cache */ +-#define NS_CLIENTATTR_RECURSING 0x40000 /*%< client is recursing */ ++#define NS_CLIENTATTR_NOSETFC 0x20000 /*%< don't set servfail cache */ + + /* + * Flag to use with the SERVFAIL cache to indicate +diff --git a/lib/ns/query.c b/lib/ns/query.c +index 335d877d48..176c552b41 100644 +--- a/lib/ns/query.c ++++ b/lib/ns/query.c +@@ -2486,6 +2486,8 @@ prefetch_done(isc_task_t *task, isc_event_t *event) { + */ + if (client->recursionquota != NULL) { + isc_quota_detach(&client->recursionquota); ++ ns_stats_decrement(client->sctx->nsstats, ++ ns_statscounter_recursclients); + } + + free_devent(client, &event, &devent); +@@ -2513,10 +2515,15 @@ query_prefetch(ns_client_t *client, dns_name_t *qname, + if (client->recursionquota == NULL) { + result = isc_quota_attach(&client->sctx->recursionquota, + &client->recursionquota); +- if (result == ISC_R_SOFTQUOTA) { ++ switch (result) { ++ case ISC_R_SUCCESS: ++ ns_stats_increment(client->sctx->nsstats, ++ ns_statscounter_recursclients); ++ break; ++ case ISC_R_SOFTQUOTA: + isc_quota_detach(&client->recursionquota); +- } +- if (result != ISC_R_SUCCESS) { ++ /* FALLTHROUGH */ ++ default: + return; + } + } +@@ -2726,10 +2733,15 @@ query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) { + if (client->recursionquota == NULL) { + result = isc_quota_attach(&client->sctx->recursionquota, + &client->recursionquota); +- if (result == ISC_R_SOFTQUOTA) { ++ switch (result) { ++ case ISC_R_SUCCESS: ++ ns_stats_increment(client->sctx->nsstats, ++ ns_statscounter_recursclients); ++ break; ++ case ISC_R_SOFTQUOTA: + isc_quota_detach(&client->recursionquota); +- } +- if (result != ISC_R_SUCCESS) { ++ /* FALLTHROUGH */ ++ default: + return; + } + } +@@ -6094,15 +6106,6 @@ fetch_callback(isc_task_t *task, isc_event_t *event) { + isc_quota_detach(&client->recursionquota); + ns_stats_decrement(client->sctx->nsstats, + ns_statscounter_recursclients); +- } else if (client->attributes & NS_CLIENTATTR_RECURSING) { +- client->attributes &= ~NS_CLIENTATTR_RECURSING; +- /* +- * Detached from recursionquota via prefetch_done(), +- * but need to decrement recursive client stats here anyway, +- * since it was incremented in ns_query_recurse(). +- */ +- ns_stats_decrement(client->sctx->nsstats, +- ns_statscounter_recursclients); + } + + LOCK(&client->manager->reclock); +@@ -6268,7 +6271,6 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, + if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) { + ns_stats_increment(client->sctx->nsstats, + ns_statscounter_recursclients); +- client->attributes |= NS_CLIENTATTR_RECURSING; + } + + if (result == ISC_R_SOFTQUOTA) { +@@ -6323,18 +6325,6 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, + + dns_message_clonebuffer(client->message); + ns_client_recursing(client); +- } else if ((client->attributes & NS_CLIENTATTR_RECURSING) == 0) { +- client->attributes |= NS_CLIENTATTR_RECURSING; +- /* +- * query_prefetch() attached first to client->recursionquota, +- * but we must check if NS_CLIENTATTR_RECURSING attribute is +- * on, if not then turn it on and increment recursing clients +- * stats counter only once. The attribute is also checked in +- * fetch_callback() to know if a matching decrement to this +- * counter should be applied. +- */ +- ns_stats_increment(client->sctx->nsstats, +- ns_statscounter_recursclients); + } + + /* +-- +2.23.0 + diff --git a/backport-0016-Properly-free-up-enqueued-netievents-in-nm_destroy.patch b/backport-0016-Properly-free-up-enqueued-netievents-in-nm_destroy.patch new file mode 100644 index 0000000000000000000000000000000000000000..ad4b4b8b5e43c3a0cf66bba889822ecc5147f331 --- /dev/null +++ b/backport-0016-Properly-free-up-enqueued-netievents-in-nm_destroy.patch @@ -0,0 +1,40 @@ +From af2bddc242ae963c89e2f06e5a2587479ceced99 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 23 Feb 2022 22:04:05 +0100 +Subject: [PATCH] Properly free up enqueued netievents in nm_destroy() + +When the isc_netmgr is being destroyed, the normal and priority queues +should be dequeued and netievents properly freed. This wasn't the case. + +(cherry picked from commit 88418c33729804cc86a9492e3e30f1123f56ddcd) +Conflict: isc_mem_put to isc_mempool_put +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/af2bddc242ae963c89e2f06e5a2587479ceced99 +--- + lib/isc/netmgr/netmgr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index ff5fd0f..6c24d41 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -418,14 +418,14 @@ nm_destroy(isc_nm_t **mgr0) { + + /* Empty the async event queues */ + while ((ievent = DEQUEUE_PRIORITY_NETIEVENT(worker)) != NULL) { +- isc_mempool_put(mgr->evpool, ievent); ++ isc__nm_put_netievent(mgr, ievent); + } + + INSIST(DEQUEUE_PRIVILEGED_NETIEVENT(worker) == NULL); + INSIST(DEQUEUE_TASK_NETIEVENT(worker) == NULL); + +- while ((ievent = DEQUEUE_PRIORITY_NETIEVENT(worker)) != NULL) { +- isc_mempool_put(mgr->evpool, ievent); ++ while ((ievent = DEQUEUE_NORMAL_NETIEVENT(worker)) != NULL) { ++ isc__nm_put_netievent(mgr, ievent); + } + isc_condition_destroy(&worker->cond_prio); + isc_mutex_destroy(&worker->lock); +-- +2.27.0 + diff --git a/backport-0017-Delay-isc__nm_uvreq_t-deallocation-to-connection-cal.patch b/backport-0017-Delay-isc__nm_uvreq_t-deallocation-to-connection-cal.patch new file mode 100644 index 0000000000000000000000000000000000000000..5cfbfa9a5598bb1dbb1522477960c5dc71323d30 --- /dev/null +++ b/backport-0017-Delay-isc__nm_uvreq_t-deallocation-to-connection-cal.patch @@ -0,0 +1,139 @@ +From 7b8e265a407db4adc14939acc6a3bbacda86bed1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Tue, 22 Feb 2022 18:12:18 +0100 +Subject: [PATCH] Delay isc__nm_uvreq_t deallocation to connection callback + +When the TCP, TCPDNS or TLSDNS connection times out, the isc__nm_uvreq_t +would be pushed into sock->inactivereqs before the uv_tcp_connect() +callback finishes. Because the isc__nmsocket_t keeps the list of +inactive isc__nm_uvreq_t, this would cause use-after-free only when the +sock->inactivereqs is full (which could never happen because the failure +happens in connection timeout callback) or when the sock->inactivereqs +mechanism is completely removed (f.e. when running under Address or +Thread Sanitizer). + +Delay isc__nm_uvreq_t deallocation to the connection callback and only +signal the connection callback should be called by shutting down the +libuv socket from the connection timeout callback. + +(cherry picked from commit 326862791689ea7029f381b4afd05c37abbd1fe7) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/7b8e265a407db4adc14939acc6a3bbacda86bed1 +--- + lib/isc/netmgr/netmgr-int.h | 1 + + lib/isc/netmgr/netmgr.c | 19 ++++++++----------- + lib/isc/netmgr/tcp.c | 9 +++++---- + lib/isc/netmgr/tcpdns.c | 11 ++++++----- + 4 files changed, 20 insertions(+), 20 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index 23b197179a..30f4734171 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -833,6 +833,7 @@ struct isc_nmsocket { + atomic_bool connected; + bool accepting; + bool reading; ++ atomic_bool timedout; + isc_refcount_t references; + + /*% +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 4bd45e7235..a8e3290f52 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -1509,6 +1509,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type, + atomic_init(&sock->connecting, false); + atomic_init(&sock->keepalive, false); + atomic_init(&sock->connected, false); ++ atomic_init(&sock->timedout, false); + + atomic_init(&sock->active_child_connections, 0); + +@@ -1936,18 +1937,14 @@ isc__nmsocket_connecttimeout_cb(uv_timer_t *timer) { + + isc__nmsocket_timer_stop(sock); + +- /* Call the connect callback directly */ +- +- req->cb.connect(req->handle, ISC_R_TIMEDOUT, req->cbarg); ++ /* ++ * Mark the connection as timed out and shutdown the socket. ++ */ + +- /* Timer is not running, cleanup and shutdown everything */ +- if (!isc__nmsocket_timer_running(sock)) { +- INSIST(atomic_compare_exchange_strong(&sock->connecting, +- &(bool){ true }, false)); +- isc__nm_uvreq_put(&req, sock); +- isc__nmsocket_clearcb(sock); +- isc__nmsocket_shutdown(sock); +- } ++ INSIST(atomic_compare_exchange_strong(&sock->timedout, &(bool){ false }, ++ true)); ++ isc__nmsocket_clearcb(sock); ++ isc__nmsocket_shutdown(sock); + } + + void +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index e562ef2d69..64914c29e3 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -239,15 +239,16 @@ tcp_connect_cb(uv_connect_t *uvreq, int status) { + isc__nmsocket_timer_stop(sock); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- if (!atomic_load(&sock->connecting)) { +- return; +- } +- + req = uv_handle_get_data((uv_handle_t *)uvreq); + + REQUIRE(VALID_UVREQ(req)); + REQUIRE(VALID_NMHANDLE(req->handle)); + ++ if (atomic_load(&sock->timedout)) { ++ result = ISC_R_TIMEDOUT; ++ goto error; ++ } ++ + if (!atomic_load(&sock->connecting)) { + /* + * The connect was cancelled from timeout; just clean up +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index 61a8e6b710..8fa2a43c5f 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -206,22 +206,23 @@ tcpdns_connect_cb(uv_connect_t *uvreq, int status) { + isc__nmsocket_timer_stop(sock); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- if (!atomic_load(&sock->connecting)) { +- return; +- } +- + req = uv_handle_get_data((uv_handle_t *)uvreq); + + REQUIRE(VALID_UVREQ(req)); + REQUIRE(VALID_NMHANDLE(req->handle)); + ++ if (atomic_load(&sock->timedout)) { ++ result = ISC_R_TIMEDOUT; ++ goto error; ++ } ++ + if (isc__nmsocket_closing(sock)) { + /* Socket was closed midflight by isc__nm_tcpdns_shutdown() */ + result = ISC_R_CANCELED; + goto error; + } else if (status == UV_ETIMEDOUT) { + /* Timeout status code here indicates hard error */ +- result = ISC_R_CANCELED; ++ result = ISC_R_TIMEDOUT; + goto error; + } else if (status != 0) { + result = isc__nm_uverr2result(status); +-- +2.23.0 + diff --git a/backport-0018-Handle-TCP-sockets-in-isc__nmsocket_reset.patch b/backport-0018-Handle-TCP-sockets-in-isc__nmsocket_reset.patch new file mode 100644 index 0000000000000000000000000000000000000000..a342e6ea56ed0153ec287b9fce7cbdd893b35d05 --- /dev/null +++ b/backport-0018-Handle-TCP-sockets-in-isc__nmsocket_reset.patch @@ -0,0 +1,84 @@ +From ac5952aee8a6dbe38717b637d8476a625d25d91a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Mon, 28 Feb 2022 10:25:06 +0100 +Subject: [PATCH] Handle TCP sockets in isc__nmsocket_reset() + +The isc__nmsocket_reset() was missing a case for raw TCP sockets (used +by RNDC and DoH) which would case a assertion failure when write timeout +would be triggered. + +TCP sockets are now also properly handled in isc__nmsocket_reset(). + +(cherry picked from commit b220fb32bdb3c70f80b95d3611807deceab2bd55) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/ac5952aee8a6dbe38717b637d8476a625d25d91a +--- + lib/isc/netmgr/netmgr.c | 38 +++++++++++++++++++++++++++++++++----- + 1 file changed, 33 insertions(+), 5 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 4829af52f9..b82ae64382 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -218,6 +218,9 @@ isc__nm_work_cb(uv_work_t *req); + static void + isc__nm_after_work_cb(uv_work_t *req, int status); + ++void ++isc__nmsocket_reset(isc_nmsocket_t *sock); ++ + /*%< + * Issue a 'handle closed' callback on the socket. + */ +@@ -1942,11 +1945,7 @@ isc__nmsocket_writetimeout_cb(uv_timer_t *timer) { + int r = uv_timer_stop(&sock->write_timer); + UV_RUNTIME_CHECK(uv_timer_stop, r); + +- /* The shutdown will be handled in the respective close functions */ +- r = uv_tcp_close_reset(&sock->uv_handle.tcp, NULL); +- UV_RUNTIME_CHECK(uv_tcp_close_reset, r); +- +- isc__nmsocket_shutdown(sock); ++ isc__nmsocket_reset(sock); + } + + void +@@ -2674,6 +2673,35 @@ isc__nm_async_detach(isc__networker_t *worker, isc__netievent_t *ev0) { + nmhandle_detach_cb(&ievent->handle FLARG_PASS); + } + ++void ++isc__nmsocket_reset(isc_nmsocket_t *sock) { ++ REQUIRE(VALID_NMSOCK(sock)); ++ ++ switch (sock->type) { ++ case isc_nm_tcpsocket: ++ case isc_nm_tcpdnssocket: ++ /* ++ * This can be called from the TCP write timeout. ++ */ ++ REQUIRE(sock->parent == NULL); ++ break; ++ default: ++ INSIST(0); ++ ISC_UNREACHABLE(); ++ break; ++ } ++ ++ if (!uv_is_closing(&sock->uv_handle.handle)) { ++ /* ++ * The real shutdown will be handled in the respective ++ * close functions. ++ */ ++ int r = uv_tcp_close_reset(&sock->uv_handle.tcp, NULL); ++ UV_RUNTIME_CHECK(uv_tcp_close_reset, r); ++ } ++ isc__nmsocket_shutdown(sock); ++} ++ + void + isc__nmsocket_shutdown(isc_nmsocket_t *sock) { + REQUIRE(VALID_NMSOCK(sock)); +-- +2.23.0 + diff --git a/backport-0019-Use-unsigned-arithmetic-when-shifting-by-24.patch b/backport-0019-Use-unsigned-arithmetic-when-shifting-by-24.patch new file mode 100644 index 0000000000000000000000000000000000000000..c452a6af76e75419fb502c89ebfe5108dcaeb84e --- /dev/null +++ b/backport-0019-Use-unsigned-arithmetic-when-shifting-by-24.patch @@ -0,0 +1,66 @@ +From a247d282bf138eb2fd6474053ea4a648371eb9b0 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Mon, 28 Feb 2022 13:43:20 +1100 +Subject: [PATCH] Use unsigned arithmetic when shifting by 24 + +By default C promotes short unsigned values to signed int which +leads to undefined behaviour when the value is shifted by too much. +Force unsigned arithmetic to be perform by explicitly casting to a +unsigned type. + +(cherry picked from commit b8b99603f117825f409cb2d49bc90ef188749227) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/a247d282bf138eb2fd6474053ea4a648371eb9b0 +--- + lib/dns/journal.c | 3 ++- + lib/dns/rbtdb.c | 5 +++-- + lib/dns/soa.c | 3 ++- + 3 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/lib/dns/journal.c b/lib/dns/journal.c +index 8e353f1c59..69beef7fbb 100644 +--- a/lib/dns/journal.c ++++ b/lib/dns/journal.c +@@ -111,7 +111,8 @@ index_to_disk(dns_journal_t *); + + static inline uint32_t + decode_uint32(unsigned char *p) { +- return ((p[0] << 24) + (p[1] << 16) + (p[2] << 8) + (p[3] << 0)); ++ return (((uint32_t)p[0] << 24) + ((uint32_t)p[1] << 16) + ++ ((uint32_t)p[2] << 8) + ((uint32_t)p[3] << 0)); + } + + static inline void +diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c +index acb35d22e6..f99d8a6c12 100644 +--- a/lib/dns/rbtdb.c ++++ b/lib/dns/rbtdb.c +@@ -8974,8 +8974,9 @@ rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { + #if DNS_RDATASET_FIXED + if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) != 0) { + unsigned int offset; +- offset = (raw[0] << 24) + (raw[1] << 16) + (raw[2] << 8) + +- raw[3]; ++ offset = ((unsigned int)raw[0] << 24) + ++ ((unsigned int)raw[1] << 16) + ++ ((unsigned int)raw[2] << 8) + (unsigned int)raw[3]; + raw = rdataset->private3; + raw += offset; + } +diff --git a/lib/dns/soa.c b/lib/dns/soa.c +index d02be34e86..82edfd437e 100644 +--- a/lib/dns/soa.c ++++ b/lib/dns/soa.c +@@ -25,7 +25,8 @@ + + static inline uint32_t + decode_uint32(unsigned char *p) { +- return ((p[0] << 24) + (p[1] << 16) + (p[2] << 8) + (p[3] << 0)); ++ return (((uint32_t)p[0] << 24) + ((uint32_t)p[1] << 16) + ++ ((uint32_t)p[2] << 8) + ((uint32_t)p[3] << 0)); + } + + static inline void +-- +2.23.0 + diff --git a/backport-0020-Grow-the-lex-token-buffer-in-one-more-place.patch b/backport-0020-Grow-the-lex-token-buffer-in-one-more-place.patch new file mode 100644 index 0000000000000000000000000000000000000000..34ebaf64b93b3465c2f8d706aba056d260b3d378 --- /dev/null +++ b/backport-0020-Grow-the-lex-token-buffer-in-one-more-place.patch @@ -0,0 +1,48 @@ +From 0b6af23d619e6969c481f51f7360e5a7299be8f5 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Mon, 28 Feb 2022 11:47:56 +1100 +Subject: [PATCH] Grow the lex token buffer in one more place + +when parsing key pairs, if the '=' character fell at max_token +a protective INSIST preventing buffer overrun could be triggered. +Attempt to grow the buffer immediately before the INSIST. + +Also removed an unnecessary INSIST on the opening double quote +of key buffer pair. + +(cherry picked from commit 4c356d277002d3e2f60fe43aaa85a4d524d933f8) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/0b6af23d619e6969c481f51f7360e5a7299be8f5 +--- + lib/isc/lex.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/lib/isc/lex.c b/lib/isc/lex.c +index 9546553800..aa9b549f79 100644 +--- a/lib/isc/lex.c ++++ b/lib/isc/lex.c +@@ -670,6 +670,13 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { + case lexstate_string: + if (!escaped && c == '=' && + (options & ISC_LEXOPT_VPAIR) != 0) { ++ if (remaining == 0U) { ++ result = grow_data(lex, &remaining, ++ &curr, &prev); ++ if (result != ISC_R_SUCCESS) { ++ goto done; ++ } ++ } + INSIST(remaining > 0U); + *curr++ = c; + *curr = '\0'; +@@ -682,7 +689,6 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { + if (state == lexstate_vpairstart) { + if (c == '"' && + (options & ISC_LEXOPT_QVPAIR) != 0) { +- INSIST(remaining > 0U); + no_comments = true; + state = lexstate_qvpair; + break; +-- +2.23.0 + diff --git a/backport-0021-Add-test-configurations-with-invalid-dnssec-policy-c.patch b/backport-0021-Add-test-configurations-with-invalid-dnssec-policy-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..1048ae5ec2e241ed7057b358e4b0e32be81068d6 --- /dev/null +++ b/backport-0021-Add-test-configurations-with-invalid-dnssec-policy-c.patch @@ -0,0 +1,122 @@ +From 38d930e5cb11d398a01f68f3c1658b4c22759583 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Tue, 15 Feb 2022 16:24:52 +1100 +Subject: [PATCH] Add test configurations with invalid dnssec-policy clauses + +bad-ksk-without-zsk.conf only has a ksk defined without a +matching zsk for the same algorithm. + +bad-zsk-without-ksk.conf only has a zsk defined without a +matching ksk for the same algorithm. + +bad-unpaired-keys.conf has two keys of different algorithms +one ksk only and the other zsk only + +(cherry picked from commit f23e86b96b77bb9fd485a2c8f6d3cd8a02afd7bd) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/38d930e5cb11d398a01f68f3c1658b4c22759583 +--- + .../system/checkconf/bad-ksk-without-zsk.conf | 24 +++++++++++++++++ + .../system/checkconf/bad-unpaired-keys.conf | 27 +++++++++++++++++++ + .../system/checkconf/bad-zsk-without-ksk.conf | 24 +++++++++++++++++ + 3 files changed, 75 insertions(+) + create mode 100644 bin/tests/system/checkconf/bad-ksk-without-zsk.conf + create mode 100644 bin/tests/system/checkconf/bad-unpaired-keys.conf + create mode 100644 bin/tests/system/checkconf/bad-zsk-without-ksk.conf + +diff --git a/bin/tests/system/checkconf/bad-ksk-without-zsk.conf b/bin/tests/system/checkconf/bad-ksk-without-zsk.conf +new file mode 100644 +index 0000000000..66e1b7f0c8 +--- /dev/null ++++ b/bin/tests/system/checkconf/bad-ksk-without-zsk.conf +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++ * ++ * SPDX-License-Identifier: MPL-2.0 ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, you can obtain one at https://mozilla.org/MPL/2.0/. ++ * ++ * See the COPYRIGHT file distributed with this work for additional ++ * information regarding copyright ownership. ++ */ ++ ++dnssec-policy ksk-without-zsk { ++ keys { ++ ksk lifetime 30d algorithm 13; ++ }; ++}; ++ ++zone "example" { ++ type primary; ++ file "example.db"; ++ dnssec-policy ksk-without-zsk; ++}; +diff --git a/bin/tests/system/checkconf/bad-unpaired-keys.conf b/bin/tests/system/checkconf/bad-unpaired-keys.conf +new file mode 100644 +index 0000000000..63b6dc2c65 +--- /dev/null ++++ b/bin/tests/system/checkconf/bad-unpaired-keys.conf +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++ * ++ * SPDX-License-Identifier: MPL-2.0 ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, you can obtain one at https://mozilla.org/MPL/2.0/. ++ * ++ * See the COPYRIGHT file distributed with this work for additional ++ * information regarding copyright ownership. ++ */ ++ ++dnssec-policy unpaired-keys { ++ keys { ++ /* zsk without ksk */ ++ zsk lifetime 30d algorithm 13; ++ /* ksk without zsk */ ++ ksk lifetime 30d algorithm 7; ++ }; ++}; ++ ++zone "example" { ++ type primary; ++ file "example.db"; ++ dnssec-policy unpaired-keys; ++}; +diff --git a/bin/tests/system/checkconf/bad-zsk-without-ksk.conf b/bin/tests/system/checkconf/bad-zsk-without-ksk.conf +new file mode 100644 +index 0000000000..31b031cdc8 +--- /dev/null ++++ b/bin/tests/system/checkconf/bad-zsk-without-ksk.conf +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++ * ++ * SPDX-License-Identifier: MPL-2.0 ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, you can obtain one at https://mozilla.org/MPL/2.0/. ++ * ++ * See the COPYRIGHT file distributed with this work for additional ++ * information regarding copyright ownership. ++ */ ++ ++dnssec-policy zsk-without-ksk { ++ keys { ++ zsk lifetime 30d algorithm 13; ++ }; ++}; ++ ++zone "example" { ++ type primary; ++ file "example.db"; ++ dnssec-policy zsk-without-ksk; ++}; +-- +2.23.0 + diff --git a/backport-0021-Check-dnssec-policy-key-roles-for-validity.patch b/backport-0021-Check-dnssec-policy-key-roles-for-validity.patch new file mode 100644 index 0000000000000000000000000000000000000000..05b20f8690eb1e88772e3ca486d0e80a13ad4cad --- /dev/null +++ b/backport-0021-Check-dnssec-policy-key-roles-for-validity.patch @@ -0,0 +1,80 @@ +From 2c7f02ca458dbf9ab9476b7290861a803a322ef3 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Tue, 15 Feb 2022 17:12:27 +1100 +Subject: [PATCH] Check dnssec-policy key roles for validity + +For each algorithm there must be a key performing the KSK and +ZSK rolls. After reading the keys from named.conf check that +each algorithm present has both rolls. CSK implicitly has both +rolls. + +(cherry picked from commit 9bcf45f4cecdb2fe577c426aae23e5d105531472) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/2c7f02ca458dbf9ab9476b7290861a803a322ef3 +--- + lib/isccfg/kaspconf.c | 35 ++++++++++++++++++++++++++++++++++- + 1 file changed, 34 insertions(+), 1 deletion(-) + +diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c +index 6e831e1465..32f76849cd 100644 +--- a/lib/isccfg/kaspconf.c ++++ b/lib/isccfg/kaspconf.c +@@ -262,7 +262,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx, + const cfg_listelt_t *element = NULL; + const char *kaspname = NULL; + dns_kasp_t *kasp = NULL; +- int i = 0; ++ size_t i = 0; + + REQUIRE(kaspp != NULL && *kaspp == NULL); + +@@ -323,6 +323,9 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx, + + (void)confget(maps, "keys", &keys); + if (keys != NULL) { ++ char role[256] = { 0 }; ++ dns_kasp_key_t *kkey = NULL; ++ + for (element = cfg_list_first(keys); element != NULL; + element = cfg_list_next(element)) + { +@@ -333,6 +336,36 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx, + } + } + INSIST(!(dns_kasp_keylist_empty(kasp))); ++ dns_kasp_freeze(kasp); ++ for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL; ++ kkey = ISC_LIST_NEXT(kkey, link)) ++ { ++ uint32_t keyalg = dns_kasp_key_algorithm(kkey); ++ INSIST(keyalg < ARRAY_SIZE(role)); ++ ++ if (dns_kasp_key_zsk(kkey)) { ++ role[keyalg] |= DNS_KASP_KEY_ROLE_ZSK; ++ } ++ ++ if (dns_kasp_key_ksk(kkey)) { ++ role[keyalg] |= DNS_KASP_KEY_ROLE_KSK; ++ } ++ } ++ dns_kasp_thaw(kasp); ++ for (i = 0; i < ARRAY_SIZE(role); i++) { ++ if (role[i] != 0 && role[i] != (DNS_KASP_KEY_ROLE_ZSK | ++ DNS_KASP_KEY_ROLE_KSK)) ++ { ++ cfg_obj_log(keys, logctx, ISC_LOG_ERROR, ++ "dnssec-policy: algorithm %zu " ++ "requires both KSK and ZSK roles", ++ i); ++ result = ISC_R_FAILURE; ++ } ++ } ++ if (result != ISC_R_SUCCESS) { ++ goto cleanup; ++ } + } else if (strcmp(kaspname, "insecure") == 0) { + /* "dnssec-policy insecure": key list must be empty */ + INSIST(strcmp(kaspname, "insecure") == 0); +-- +2.23.0 + diff --git a/backport-0022-Add-network-manager-based-timer-API.patch b/backport-0022-Add-network-manager-based-timer-API.patch new file mode 100644 index 0000000000000000000000000000000000000000..41dd4e658b60b9aec38f5d1c961833ca41c06578 --- /dev/null +++ b/backport-0022-Add-network-manager-based-timer-API.patch @@ -0,0 +1,189 @@ +From 914a7e14e2af8260a1b0d797cc95e0552ccae53f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 2 Feb 2022 10:50:27 +0100 +Subject: [PATCH] Add network manager based timer API + +This commits adds API that allows to create arbitrary timers associated +with the network manager handles. + +(cherry picked from commit 3c7b04d0150ae6d6192747d90d52247bd598bd9a) +Conflict: UV_RUNTIME_CHECK to RUNTIME_CHECK +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/914a7e14e2af8260a1b0d797cc95e0552ccae53f +--- + lib/isc/include/isc/netmgr.h | 24 ++++++++++ + lib/isc/netmgr/netmgr-int.h | 8 ++++ + lib/isc/netmgr/netmgr.c | 91 ++++++++++++++++++++++++++++++++++++ + lib/isc/win32/libisc.def.in | 5 ++ + 4 files changed, 128 insertions(+) + +diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h +index 39dba1d376..7ec40e81b6 100644 +--- a/lib/isc/include/isc/netmgr.h ++++ b/lib/isc/include/isc/netmgr.h +@@ -492,3 +492,27 @@ isc__nm_force_tid(int tid); + + void + isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout); ++ ++/* ++ * Timer related functions ++ */ ++ ++typedef struct isc_nm_timer isc_nm_timer_t; ++ ++typedef void (*isc_nm_timer_cb)(void *, isc_result_t); ++ ++void ++isc_nm_timer_create(isc_nmhandle_t *, isc_nm_timer_cb, void *, ++ isc_nm_timer_t **); ++ ++void ++isc_nm_timer_attach(isc_nm_timer_t *, isc_nm_timer_t **); ++ ++void ++isc_nm_timer_detach(isc_nm_timer_t **); ++ ++void ++isc_nm_timer_start(isc_nm_timer_t *, uint64_t); ++ ++void ++isc_nm_timer_stop(isc_nm_timer_t *); +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index 3871d70939..23b197179a 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -350,6 +350,14 @@ struct isc__nm_uvreq { + ISC_LINK(isc__nm_uvreq_t) link; + }; + ++struct isc_nm_timer { ++ isc_refcount_t references; ++ uv_timer_t timer; ++ isc_nmhandle_t *handle; ++ isc_nm_timer_cb cb; ++ void *cbarg; ++}; ++ + void * + isc__nm_get_netievent(isc_nm_t *mgr, isc__netievent_type type); + /*%< +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 31917be101..fb9d77d3b4 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -3179,6 +3179,97 @@ isc_nm_work_offload(isc_nm_t *netmgr, isc_nm_workcb_t work_cb, + RUNTIME_CHECK(r == 0); + } + ++void ++isc_nm_timer_create(isc_nmhandle_t *handle, isc_nm_timer_cb cb, void *cbarg, ++ isc_nm_timer_t **timerp) { ++ isc__networker_t *worker = NULL; ++ isc_nmsocket_t *sock = NULL; ++ isc_nm_timer_t *timer = NULL; ++ int r; ++ ++ REQUIRE(isc__nm_in_netthread()); ++ REQUIRE(VALID_NMHANDLE(handle)); ++ REQUIRE(VALID_NMSOCK(handle->sock)); ++ ++ sock = handle->sock; ++ worker = &sock->mgr->workers[isc_nm_tid()]; ++ ++ timer = isc_mem_get(sock->mgr->mctx, sizeof(*timer)); ++ *timer = (isc_nm_timer_t){ .cb = cb, .cbarg = cbarg }; ++ isc_refcount_init(&timer->references, 1); ++ isc_nmhandle_attach(handle, &timer->handle); ++ ++ r = uv_timer_init(&worker->loop, &timer->timer); ++ UV_RUNTIME_CHECK(uv_timer_init, r); ++ ++ uv_handle_set_data((uv_handle_t *)&timer->timer, timer); ++ ++ *timerp = timer; ++} ++ ++void ++isc_nm_timer_attach(isc_nm_timer_t *timer, isc_nm_timer_t **timerp) { ++ REQUIRE(timer != NULL); ++ REQUIRE(timerp != NULL && *timerp == NULL); ++ ++ isc_refcount_increment(&timer->references); ++ *timerp = timer; ++} ++ ++static void ++timer_destroy(uv_handle_t *uvhandle) { ++ isc_nm_timer_t *timer = uv_handle_get_data(uvhandle); ++ isc_nmhandle_t *handle = timer->handle; ++ isc_mem_t *mctx = timer->handle->sock->mgr->mctx; ++ ++ isc_mem_put(mctx, timer, sizeof(*timer)); ++ ++ isc_nmhandle_detach(&handle); ++} ++ ++void ++isc_nm_timer_detach(isc_nm_timer_t **timerp) { ++ isc_nm_timer_t *timer = NULL; ++ isc_nmhandle_t *handle = NULL; ++ ++ REQUIRE(timerp != NULL && *timerp != NULL); ++ ++ timer = *timerp; ++ *timerp = NULL; ++ ++ handle = timer->handle; ++ ++ REQUIRE(isc__nm_in_netthread()); ++ REQUIRE(VALID_NMHANDLE(handle)); ++ REQUIRE(VALID_NMSOCK(handle->sock)); ++ ++ if (isc_refcount_decrement(&timer->references) == 1) { ++ uv_timer_stop(&timer->timer); ++ uv_close((uv_handle_t *)&timer->timer, timer_destroy); ++ } ++} ++ ++static void ++timer_cb(uv_timer_t *uvtimer) { ++ isc_nm_timer_t *timer = uv_handle_get_data((uv_handle_t *)uvtimer); ++ ++ REQUIRE(timer->cb != NULL); ++ ++ timer->cb(timer->cbarg, ISC_R_TIMEDOUT); ++} ++ ++void ++isc_nm_timer_start(isc_nm_timer_t *timer, uint64_t timeout) { ++ int r = uv_timer_start(&timer->timer, timer_cb, timeout, 0); ++ UV_RUNTIME_CHECK(uv_timer_start, r); ++} ++ ++void ++isc_nm_timer_stop(isc_nm_timer_t *timer) { ++ int r = uv_timer_stop(&timer->timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); ++} ++ + #ifdef NETMGR_TRACE + /* + * Dump all active sockets in netmgr. We output to stderr +diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in +index 79e7b64a58..ab7ad73d20 100644 +--- a/lib/isc/win32/libisc.def.in ++++ b/lib/isc/win32/libisc.def.in +@@ -480,6 +480,11 @@ isc_nm_tcpconnect + isc_nm_tcpdnsconnect + isc_nm_tcpdns_sequential + isc_nm_tid ++isc_nm_timer_create ++isc_nm_timer_attach ++isc_nm_timer_detach ++isc_nm_timer_start ++isc_nm_timer_stop + isc_nm_udpconnect + isc_nm_work_offload + isc_nmsocket_close +-- +2.27.0 \ No newline at end of file diff --git a/backport-0022-Change-single-write-timer-to-per-send-timers.patch b/backport-0022-Change-single-write-timer-to-per-send-timers.patch new file mode 100644 index 0000000000000000000000000000000000000000..b382139dd3578fe6a524b7537f130c28f28991ff --- /dev/null +++ b/backport-0022-Change-single-write-timer-to-per-send-timers.patch @@ -0,0 +1,494 @@ +From d17d043499b0a6927738fa0a09daa71a53e90e11 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Thu, 10 Mar 2022 13:51:08 +0100 +Subject: [PATCH] Change single write timer to per-send timers + +Previously, there was a single per-socket write timer that would get +restarted for every new write. This turned out to be insufficient +because the other side could keep reseting the timer, and never reading +back the responses. + +Change the single write timer to per-send timer which would in turn +reset the TCP connection on the first send timeout. + +(cherry picked from commit a761aa59e3d988b53e2f42f45bce53f2bea863ec) +Conflict: UV_RUNTIME_CHECK to RUNTIME_CHECK +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/d17d043499b0a6927738fa0a09daa71a53e90e11 +--- + lib/isc/netmgr/netmgr-int.h | 22 +++++------ + lib/isc/netmgr/netmgr.c | 26 +++++++++---- + lib/isc/netmgr/tcp.c | 74 ++++++++----------------------------- + lib/isc/netmgr/tcpdns.c | 49 ++++++------------------ + lib/isc/netmgr/udp.c | 29 +-------------- + 5 files changed, 58 insertions(+), 142 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index e8b043f..e43bc9f 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -306,15 +306,15 @@ struct isc__nm_uvreq { + int magic; + isc_nmsocket_t *sock; + isc_nmhandle_t *handle; +- char tcplen[2]; /* The TCP DNS message length */ +- uv_buf_t uvbuf; /* translated isc_region_t, to be +- * sent or received */ +- isc_sockaddr_t local; /* local address */ +- isc_sockaddr_t peer; /* peer address */ +- isc__nm_cb_t cb; /* callback */ +- void *cbarg; /* callback argument */ +- uv_pipe_t ipc; /* used for sending socket +- * uv_handles to other threads */ ++ char tcplen[2]; /* The TCP DNS message length */ ++ uv_buf_t uvbuf; /* translated isc_region_t, to be ++ * sent or received */ ++ isc_sockaddr_t local; /* local address */ ++ isc_sockaddr_t peer; /* peer address */ ++ isc__nm_cb_t cb; /* callback */ ++ void *cbarg; /* callback argument */ ++ isc_nm_timer_t *timer; /* TCP write timer */ ++ + union { + uv_handle_t handle; + uv_req_t req; +@@ -764,9 +764,7 @@ struct isc_nmsocket { + /*% + * TCP write timeout timer. + */ +- uv_timer_t write_timer; + uint64_t write_timeout; +- int64_t writes; + + /*% outer socket is for 'wrapped' sockets - e.g. tcpdns in tcp */ + isc_nmsocket_t *outer; +@@ -1600,7 +1598,7 @@ isc__nmsocket_connecttimeout_cb(uv_timer_t *timer); + void + isc__nmsocket_readtimeout_cb(uv_timer_t *timer); + void +-isc__nmsocket_writetimeout_cb(uv_timer_t *timer); ++isc__nmsocket_writetimeout_cb(void *data, isc_result_t eresult); + + /*%< + * +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 9e44b76..0fe12f9 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -2009,11 +2009,15 @@ isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota) { + } + + void +-isc__nmsocket_writetimeout_cb(uv_timer_t *timer) { +- isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer); ++isc__nmsocket_writetimeout_cb(void *data, isc_result_t eresult) { ++ isc__nm_uvreq_t *req = data; ++ isc_nmsocket_t *sock = NULL; + +- int r = uv_timer_stop(&sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_stop, r); ++ REQUIRE(eresult == ISC_R_TIMEDOUT); ++ REQUIRE(VALID_UVREQ(req)); ++ REQUIRE(VALID_NMSOCK(req->sock)); ++ ++ sock = req->sock; + + isc__nmsocket_reset(sock); + } +@@ -2724,6 +2728,13 @@ isc__nm_async_detach(isc__networker_t *worker, isc__netievent_t *ev0) { + nmhandle_detach_cb(&ievent->handle FLARG_PASS); + } + ++static void ++reset_shutdown(uv_handle_t *handle) { ++ isc_nmsocket_t *sock = uv_handle_get_data(handle); ++ ++ isc__nmsocket_shutdown(sock); ++} ++ + void + isc__nmsocket_reset(isc_nmsocket_t *sock) { + REQUIRE(VALID_NMSOCK(sock)); +@@ -2747,10 +2758,10 @@ isc__nmsocket_reset(isc_nmsocket_t *sock) { + * The real shutdown will be handled in the respective + * close functions. + */ +- int r = uv_tcp_close_reset(&sock->uv_handle.tcp, NULL); ++ int r = uv_tcp_close_reset(&sock->uv_handle.tcp, ++ reset_shutdown); + UV_RUNTIME_CHECK(uv_tcp_close_reset, r); + } +- isc__nmsocket_shutdown(sock); + } + + void +@@ -3285,7 +3296,8 @@ isc_nm_timer_detach(isc_nm_timer_t **timerp) { + REQUIRE(VALID_NMSOCK(handle->sock)); + + if (isc_refcount_decrement(&timer->references) == 1) { +- uv_timer_stop(&timer->timer); ++ int r = uv_timer_stop(&timer->timer); ++ UV_RUNTIME_CHECK(uv_timer_stop, r); + uv_close((uv_handle_t *)&timer->timer, timer_destroy); + } + } +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index 21327af..009e431 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -76,9 +76,6 @@ quota_accept_cb(isc_quota_t *quota, void *sock0); + static void + failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult); + +-static void +-failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, +- isc_result_t eresult); + static void + stop_tcp_parent(isc_nmsocket_t *sock); + static void +@@ -142,10 +139,6 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- r = uv_timer_init(&worker->loop, &sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- + r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); + if (r != 0) { + isc__nm_closesocket(sock->fd); +@@ -536,10 +529,6 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { + + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- r = uv_timer_init(&worker->loop, &sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- + LOCK(&sock->parent->lock); + + r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); +@@ -712,19 +701,6 @@ destroy: + } + } + +-static void +-failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, +- isc_result_t eresult) { +- REQUIRE(VALID_NMSOCK(sock)); +- REQUIRE(VALID_UVREQ(req)); +- +- if (req->cb.send != NULL) { +- isc__nm_sendcb(sock, req, eresult, true); +- } else { +- isc__nm_uvreq_put(&req, sock); +- } +-} +- + void + isc__nm_tcp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { + REQUIRE(VALID_NMHANDLE(handle)); +@@ -980,10 +956,6 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock); + +- r = uv_timer_init(&worker->loop, &csock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&csock->write_timer, csock); +- + r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream); + if (r != 0) { + result = isc__nm_uverr2result(r); +@@ -1094,20 +1066,20 @@ isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region, + static void + tcp_send_cb(uv_write_t *req, int status) { + isc__nm_uvreq_t *uvreq = (isc__nm_uvreq_t *)req->data; ++ isc_nmsocket_t *sock = NULL; + + REQUIRE(VALID_UVREQ(uvreq)); +- REQUIRE(VALID_NMHANDLE(uvreq->handle)); ++ REQUIRE(VALID_NMSOCK(uvreq->sock)); + +- isc_nmsocket_t *sock = uvreq->sock; ++ sock = uvreq->sock; + +- if (--sock->writes == 0) { +- int r = uv_timer_stop(&sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_stop, r); +- } ++ isc_nm_timer_stop(uvreq->timer); ++ isc_nm_timer_detach(&uvreq->timer); + + if (status < 0) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]); +- failed_send_cb(sock, uvreq, isc__nm_uverr2result(status)); ++ isc__nm_failed_send_cb(sock, uvreq, ++ isc__nm_uverr2result(status)); + return; + } + +@@ -1131,7 +1103,7 @@ isc__nm_async_tcpsend(isc__networker_t *worker, isc__netievent_t *ev0) { + result = tcp_send_direct(sock, uvreq); + if (result != ISC_R_SUCCESS) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]); +- failed_send_cb(sock, uvreq, result); ++ isc__nm_failed_send_cb(sock, uvreq, result); + } + } + +@@ -1148,17 +1120,18 @@ tcp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + return (ISC_R_CANCELED); + } + +- r = uv_timer_start(&sock->write_timer, isc__nmsocket_writetimeout_cb, +- sock->write_timeout, 0); +- UV_RUNTIME_CHECK(uv_timer_start, r); +- RUNTIME_CHECK(sock->writes++ >= 0); +- + r = uv_write(&req->uv_req.write, &sock->uv_handle.stream, &req->uvbuf, + 1, tcp_send_cb); + if (r < 0) { + return (isc__nm_uverr2result(r)); + } + ++ isc_nm_timer_create(req->handle, isc__nmsocket_writetimeout_cb, req, ++ &req->timer); ++ if (sock->write_timeout > 0) { ++ isc_nm_timer_start(req->timer, sock->write_timeout); ++ } ++ + return (ISC_R_SUCCESS); + } + +@@ -1229,17 +1202,6 @@ read_timer_close_cb(uv_handle_t *handle) { + } + } + +-static void +-write_timer_close_cb(uv_handle_t *timer) { +- isc_nmsocket_t *sock = uv_handle_get_data(timer); +- uv_handle_set_data(timer, NULL); +- +- REQUIRE(VALID_NMSOCK(sock)); +- +- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); +- uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); +-} +- + static void + stop_tcp_child(isc_nmsocket_t *sock) { + REQUIRE(sock->type == isc_nm_tcpsocket); +@@ -1292,8 +1254,6 @@ stop_tcp_parent(isc_nmsocket_t *sock) { + + static void + tcp_close_direct(isc_nmsocket_t *sock) { +- int r; +- + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + REQUIRE(atomic_load(&sock->closing)); +@@ -1315,10 +1275,8 @@ tcp_close_direct(isc_nmsocket_t *sock) { + isc__nmsocket_timer_stop(sock); + isc__nm_stop_reading(sock); + +- r = uv_timer_stop(&sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_stop, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); + } + + void +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index 89d1554..4689f56 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -100,10 +100,6 @@ tcpdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- r = uv_timer_init(&worker->loop, &sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- + if (isc__nm_closing(sock)) { + result = ISC_R_CANCELED; + goto error; +@@ -498,10 +494,6 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- r = uv_timer_init(&worker->loop, &sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- + LOCK(&sock->parent->lock); + + r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); +@@ -947,10 +939,6 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock); + +- r = uv_timer_init(&worker->loop, &csock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&csock->write_timer, csock); +- + r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream); + if (r != 0) { + result = isc__nm_uverr2result(r); +@@ -1085,14 +1073,12 @@ tcpdns_send_cb(uv_write_t *req, int status) { + isc_nmsocket_t *sock = NULL; + + REQUIRE(VALID_UVREQ(uvreq)); +- REQUIRE(VALID_NMHANDLE(uvreq->handle)); ++ REQUIRE(VALID_NMSOCK(uvreq->sock)); + + sock = uvreq->sock; + +- if (--sock->writes == 0) { +- int r = uv_timer_stop(&sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_stop, r); +- } ++ isc_nm_timer_stop(uvreq->timer); ++ isc_nm_timer_detach(&uvreq->timer); + + if (status < 0) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]); +@@ -1158,11 +1144,6 @@ isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) { + goto fail; + } + +- r = uv_timer_start(&sock->write_timer, isc__nmsocket_writetimeout_cb, +- sock->write_timeout, 0); +- UV_RUNTIME_CHECK(uv_timer_start, r); +- RUNTIME_CHECK(sock->writes++ >= 0); +- + r = uv_write(&uvreq->uv_req.write, &sock->uv_handle.stream, bufs, nbufs, + tcpdns_send_cb); + if (r < 0) { +@@ -1170,6 +1151,12 @@ isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) { + goto fail; + } + ++ isc_nm_timer_create(uvreq->handle, isc__nmsocket_writetimeout_cb, uvreq, ++ &uvreq->timer); ++ if (sock->write_timeout > 0) { ++ isc_nm_timer_start(uvreq->timer, sock->write_timeout); ++ } ++ + return; + + fail: +@@ -1250,17 +1237,6 @@ read_timer_close_cb(uv_handle_t *timer) { + } + } + +-static void +-write_timer_close_cb(uv_handle_t *timer) { +- isc_nmsocket_t *sock = uv_handle_get_data(timer); +- uv_handle_set_data(timer, NULL); +- +- REQUIRE(VALID_NMSOCK(sock)); +- +- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); +- uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); +-} +- + static void + stop_tcpdns_child(isc_nmsocket_t *sock) { + REQUIRE(sock->type == isc_nm_tcpdnssocket); +@@ -1313,7 +1289,6 @@ stop_tcpdns_parent(isc_nmsocket_t *sock) { + + static void + tcpdns_close_direct(isc_nmsocket_t *sock) { +- int r; + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + REQUIRE(atomic_load(&sock->closing)); +@@ -1329,10 +1304,8 @@ tcpdns_close_direct(isc_nmsocket_t *sock) { + isc__nmsocket_timer_stop(sock); + isc__nm_stop_reading(sock); + +- r = uv_timer_stop(&sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_stop, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); + } + + void +diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c +index d3fffe0..305ac29 100644 +--- a/lib/isc/netmgr/udp.c ++++ b/lib/isc/netmgr/udp.c +@@ -48,9 +48,6 @@ udp_close_cb(uv_handle_t *handle); + static void + read_timer_close_cb(uv_handle_t *handle); + +-static void +-write_timer_close_cb(uv_handle_t *handle); +- + static void + udp_close_direct(isc_nmsocket_t *sock); + +@@ -233,10 +230,6 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- r = uv_timer_init(&worker->loop, &sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- + LOCK(&sock->parent->lock); + + r = uv_udp_open(&sock->uv_handle.udp, sock->fd); +@@ -635,10 +628,6 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { + RUNTIME_CHECK(r == 0); + uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); + +- r = uv_timer_init(&worker->loop, &sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_init, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- + r = uv_udp_open(&sock->uv_handle.udp, sock->fd); + if (r != 0) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]); +@@ -994,17 +983,6 @@ read_timer_close_cb(uv_handle_t *handle) { + } + } + +-static void +-write_timer_close_cb(uv_handle_t *timer) { +- isc_nmsocket_t *sock = uv_handle_get_data(timer); +- uv_handle_set_data(timer, NULL); +- +- REQUIRE(VALID_NMSOCK(sock)); +- +- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); +- uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); +-} +- + static void + stop_udp_child(isc_nmsocket_t *sock) { + REQUIRE(sock->type == isc_nm_udpsocket); +@@ -1057,14 +1035,11 @@ stop_udp_parent(isc_nmsocket_t *sock) { + + static void + udp_close_direct(isc_nmsocket_t *sock) { +- int r; + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + +- r = uv_timer_stop(&sock->write_timer); +- UV_RUNTIME_CHECK(uv_timer_stop, r); +- uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock); +- uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb); ++ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock); ++ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb); + } + + void +-- +2.27.0 + diff --git a/backport-0022-On-shutdown-reset-the-established-TCP-connections.patch b/backport-0022-On-shutdown-reset-the-established-TCP-connections.patch new file mode 100644 index 0000000000000000000000000000000000000000..a9020f68624107860201ff9dce900495243a34b2 --- /dev/null +++ b/backport-0022-On-shutdown-reset-the-established-TCP-connections.patch @@ -0,0 +1,84 @@ +From 7a386256b6e80520637583268b9e9fef5fe0f743 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Thu, 10 Mar 2022 13:58:58 +0100 +Subject: [PATCH] On shutdown, reset the established TCP connections + +Previously, the established TCP connections (both client and server) +would be gracefully closed waiting for the write timeout. + +Don't wait for TCP connections to gracefully shutdown, but directly +reset them for faster shutdown. + +(cherry picked from commit 6ddac2d56de980717aaba7fc0ad73af0f3890399) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/7a386256b6e80520637583268b9e9fef5fe0f743 +--- + lib/isc/netmgr/netmgr.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 41e4bce616..24947a562a 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -2686,6 +2686,7 @@ reset_shutdown(uv_handle_t *handle) { + isc_nmsocket_t *sock = uv_handle_get_data(handle); + + isc__nmsocket_shutdown(sock); ++ isc__nmsocket_detach(&sock); + } + + void +@@ -2706,14 +2707,19 @@ isc__nmsocket_reset(isc_nmsocket_t *sock) { + break; + } + +- if (!uv_is_closing(&sock->uv_handle.handle)) { ++ if (!uv_is_closing(&sock->uv_handle.handle) && ++ uv_is_active(&sock->uv_handle.handle)) ++ { + /* + * The real shutdown will be handled in the respective + * close functions. + */ ++ isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL }); + int r = uv_tcp_close_reset(&sock->uv_handle.tcp, + reset_shutdown); + UV_RUNTIME_CHECK(uv_tcp_close_reset, r); ++ } else { ++ isc__nmsocket_shutdown(sock); + } + } + +@@ -2751,13 +2757,26 @@ shutdown_walk_cb(uv_handle_t *handle, void *arg) { + + switch (handle->type) { + case UV_UDP: ++ isc__nmsocket_shutdown(sock); ++ return; + case UV_TCP: +- break; ++ switch (sock->type) { ++ case isc_nm_tcpsocket: ++ case isc_nm_tcpdnssocket: ++ if (sock->parent == NULL) { ++ /* Reset the TCP connections on shutdown */ ++ isc__nmsocket_reset(sock); ++ return; ++ } ++ /* FALLTHROUGH */ ++ default: ++ isc__nmsocket_shutdown(sock); ++ } ++ ++ return; + default: + return; + } +- +- isc__nmsocket_shutdown(sock); + } + + void +-- +2.23.0 + diff --git a/backport-0023-Log-not-authoritative-for-update-zone-more-clearly.patch b/backport-0023-Log-not-authoritative-for-update-zone-more-clearly.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d445bc5f8f4e391b92f684c7fc70a64d46a876b --- /dev/null +++ b/backport-0023-Log-not-authoritative-for-update-zone-more-clearly.patch @@ -0,0 +1,84 @@ +From a5d65815bc9812f7b55664d564f9592765c88e6d Mon Sep 17 00:00:00 2001 +From: Tony Finch +Date: Tue, 15 Mar 2022 17:57:43 +0000 +Subject: [PATCH] Log "not authoritative for update zone" more clearly + +Ensure the update zone name is mentioned in the NOTAUTH error message +in the server log, so that it is easier to track down problematic +update clients. There are two cases: either the update zone is +unrelated to any of the server's zones (previously no zone was +mentioned); or the update zone is a subdomain of one or more of the +server's zones (previously the name of the irrelevant parent zone was +misleadingly logged). + +Closes #3209 + +(cherry picked from commit 84c4eb02e7a4599acfb5d2abc0e62e7d64fd1bd6) +Conflict: delete CHANGES +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/a5d65815bc9812f7b55664d564f9592765c88e6d +--- + bin/tests/system/nsupdate/tests.sh | 26 ++++++++++++++++++++++++++ + lib/ns/update.c | 10 +++++++++- + 3 files changed, 40 insertions(+), 1 deletion(-) + +diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh +index b3cb85aada..e4f96eb126 100755 +--- a/bin/tests/system/nsupdate/tests.sh ++++ b/bin/tests/system/nsupdate/tests.sh +@@ -83,6 +83,32 @@ digcomp knowngood.ns1.before dig.out.ns1 || ret=1 + digcomp knowngood.ns1.before dig.out.ns2 || ret=1 + [ $ret = 0 ] || { echo_i "failed"; status=1; } + ++ret=0 ++echo_i "ensure an unrelated zone is mentioned in its NOTAUTH log" ++$NSUPDATE -k ns1/ddns.key > nsupdate.out 2>&1 << END && ret=1 ++server 10.53.0.1 ${PORT} ++zone unconfigured.test ++update add unconfigured.test 600 IN A 10.53.0.1 ++send ++END ++grep NOTAUTH nsupdate.out > /dev/null 2>&1 || ret=1 ++grep ' unconfigured.test: not authoritative' ns1/named.run \ ++ > /dev/null 2>&1 || ret=1 ++[ $ret = 0 ] || { echo_i "failed"; status=1; } ++ ++ret=0 ++echo_i "ensure a subdomain is mentioned in its NOTAUTH log" ++$NSUPDATE -k ns1/ddns.key > nsupdate.out 2>&1 << END && ret=1 ++server 10.53.0.1 ${PORT} ++zone sub.sub.example.nil ++update add sub.sub.sub.example.nil 600 IN A 10.53.0.1 ++send ++END ++grep NOTAUTH nsupdate.out > /dev/null 2>&1 || ret=1 ++grep ' sub.sub.example.nil: not authoritative' ns1/named.run \ ++ > /dev/null 2>&1 || ret=1 ++[ $ret = 0 ] || { echo_i "failed"; status=1; } ++ + ret=0 + echo_i "updating zone" + # nsupdate will print a ">" prompt to stdout as it gets each input line. +diff --git a/lib/ns/update.c b/lib/ns/update.c +index 9ab13e3301..067ff990bd 100644 +--- a/lib/ns/update.c ++++ b/lib/ns/update.c +@@ -1631,7 +1631,15 @@ ns_update_start(ns_client_t *client, isc_nmhandle_t *handle, + + result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, &zone); + if (result != ISC_R_SUCCESS) { +- FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); ++ /* ++ * If we found a zone that is a parent of the update zonename, ++ * detach it so it isn't mentioned in log - it is irrelevant. ++ */ ++ if (zone != NULL) { ++ dns_zone_detach(&zone); ++ } ++ FAILN(DNS_R_NOTAUTH, zonename, ++ "not authoritative for update zone"); + } + + /* +-- +2.27.0 + diff --git a/backport-0024-Prevent-arithmetic-overflow-of-i-in-master.c-generat.patch b/backport-0024-Prevent-arithmetic-overflow-of-i-in-master.c-generat.patch new file mode 100644 index 0000000000000000000000000000000000000000..631a66fb11becc015a055fd8fff5971f53160d4d --- /dev/null +++ b/backport-0024-Prevent-arithmetic-overflow-of-i-in-master.c-generat.patch @@ -0,0 +1,43 @@ +From c284112becef6b6605ae4f18363afac3b0e173fd Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Fri, 4 Mar 2022 09:37:39 +1100 +Subject: [PATCH] Prevent arithmetic overflow of 'i' in master.c:generate + +the value of 'i' in generate could overflow when adding 'step' to +it in the 'for' loop. Use an unsigned int for 'i' which will give +an additional bit and prevent the overflow. The inputs are both +less than 2^31 and and the result will be less than 2^32-1. + +(cherry picked from commit 5abdee9004f118b2c1301229418f93de7626e66f) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/c284112becef6b6605ae4f18363afac3b0e173fd +--- + lib/dns/master.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/dns/master.c b/lib/dns/master.c +index 75f59396a7..e1ba723104 100644 +--- a/lib/dns/master.c ++++ b/lib/dns/master.c +@@ -800,7 +800,8 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, + isc_buffer_t target; + isc_result_t result; + isc_textregion_t r; +- int i, n, start, stop, step = 0; ++ int n, start, stop, step = 0; ++ unsigned int i; + dns_incctx_t *ictx; + char dummy[2]; + +@@ -855,7 +856,7 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, + goto insist_cleanup; + } + +- for (i = start; i <= stop; i += step) { ++ for (i = start; i <= (unsigned int)stop; i += step) { + result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS); + if (result != ISC_R_SUCCESS) { + goto error_cleanup; +-- +2.23.0 + diff --git a/backport-0024-add-a-system-test-for-GENERATE-with-an-integer-overf.patch b/backport-0024-add-a-system-test-for-GENERATE-with-an-integer-overf.patch new file mode 100644 index 0000000000000000000000000000000000000000..6a47a599be3ac18fc95879a165718008f9de12dc --- /dev/null +++ b/backport-0024-add-a-system-test-for-GENERATE-with-an-integer-overf.patch @@ -0,0 +1,68 @@ +From 975a3da84e3eb1f3825e486ebda384b73163ee65 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Fri, 4 Mar 2022 15:19:52 -0800 +Subject: [PATCH] add a system test for $GENERATE with an integer overflow + +the line "$GENERATE 19-28/2147483645 $ CNAME x" should generate +a single CNAME with the owner "19.example.com", but prior to the +overflow bug it generated several CNAMEs, half of them with large +negative values. + +we now test for the bugfix by using "named-checkzone -D" and +grepping for a single CNAME in the output. + +(cherry picked from commit bd814b79d4a87faf80e306d705a6a9cc0ae08c11) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/975a3da84e3eb1f3825e486ebda384b73163ee65 +--- + bin/tests/system/checkzone/tests.sh | 10 ++++++++++ + .../system/checkzone/zones/generate-overflow.db | 17 +++++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100644 bin/tests/system/checkzone/zones/generate-overflow.db + +diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh +index 1e772f9d72..ab2a54db84 100644 +--- a/bin/tests/system/checkzone/tests.sh ++++ b/bin/tests/system/checkzone/tests.sh +@@ -184,5 +184,15 @@ n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status+ret)) + ++n=$((n+1)) ++ret=0 ++echo_i "checking integer overflow is prevented in \$GENERATE ($n)" ++$CHECKZONE -D example.com zones/generate-overflow.db > test.out.$n 2>&1 || ret=1 ++lines=$(grep -c CNAME test.out.$n) ++echo $lines ++[ "$lines" -eq 1 ] || ret=1 ++if [ $ret != 0 ]; then echo_i "failed"; fi ++status=$((status+ret)) ++ + echo_i "exit status: $status" + [ $status -eq 0 ] || exit 1 +diff --git a/bin/tests/system/checkzone/zones/generate-overflow.db b/bin/tests/system/checkzone/zones/generate-overflow.db +new file mode 100644 +index 0000000000..c16b517481 +--- /dev/null ++++ b/bin/tests/system/checkzone/zones/generate-overflow.db +@@ -0,0 +1,17 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 600 ++@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 ++ NS ns ++ns A 192.0.2.1 ++ ++$GENERATE 19-28/2147483645 $ CNAME x +-- +2.27.0 + diff --git a/backport-0024-update-shell-syntax.patch b/backport-0024-update-shell-syntax.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb0c6f404842e9740cd85228a0a5e037ec1d7472 --- /dev/null +++ b/backport-0024-update-shell-syntax.patch @@ -0,0 +1,172 @@ +From fc7ed00d70e616d3cce026dc35fc9b19a7598b9f Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Fri, 4 Mar 2022 15:13:25 -0800 +Subject: [PATCH] update shell syntax + +clean up the shell syntax in the checkzone test prior to adding +a new test. + +(cherry picked from commit 2261c853b521e60500ed355961646bc2d3b0ed06) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/fc7ed00d70e616d3cce026dc35fc9b19a7598b9f +--- + bin/tests/system/checkzone/tests.sh | 54 ++++++++++++++--------------- + 1 file changed, 27 insertions(+), 27 deletions(-) + +diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh +index 10c218925c..1e772f9d72 100644 +--- a/bin/tests/system/checkzone/tests.sh ++++ b/bin/tests/system/checkzone/tests.sh +@@ -30,9 +30,9 @@ do + $CHECKZONE -i local example $db > test.out.$n 2>&1 || ret=1 + ;; + esac +- n=`expr $n + 1` ++ n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +- status=`expr $status + $ret` ++ status=$((status+ret)) + done + + for db in zones/bad*.db +@@ -48,9 +48,9 @@ do + ;; + esac + test $v = 1 || ret=1 +- n=`expr $n + 1` ++ n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +- status=`expr $status + $ret` ++ status=$((status+ret)) + done + + echo_i "checking with journal file ($n)" +@@ -58,16 +58,16 @@ ret=0 + $CHECKZONE -D -o test.orig.db test zones/test1.db > /dev/null 2>&1 || ret=1 + $CHECKZONE -D -o test.changed.db test zones/test2.db > /dev/null 2>&1 || ret=1 + $MAKEJOURNAL test test.orig.db test.changed.db test.orig.db.jnl 2>&1 || ret=1 +-jlines=`$JOURNALPRINT test.orig.db.jnl | wc -l` ++jlines=$($JOURNALPRINT test.orig.db.jnl | wc -l) + [ $jlines = 3 ] || ret=1 + $CHECKZONE -D -j -o test.out1.db test test.orig.db > /dev/null 2>&1 || ret=1 + cmp -s test.changed.db test.out1.db || ret=1 + mv -f test.orig.db.jnl test.journal + $CHECKZONE -D -J test.journal -o test.out2.db test test.orig.db > /dev/null 2>&1 || ret=1 + cmp -s test.changed.db test.out2.db || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking with spf warnings ($n)" + ret=0 +@@ -79,25 +79,25 @@ grep "'example' found type SPF" test.out1.$n > /dev/null && ret=1 + grep "'x.example' found type SPF" test.out2.$n > /dev/null && ret=1 + grep "'y.example' found type SPF" test.out2.$n > /dev/null && ret=1 + grep "'example' found type SPF" test.out2.$n > /dev/null && ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking with max ttl (text) ($n)" + ret=0 + $CHECKZONE -l 300 example zones/good1.db > test.out1.$n 2>&1 && ret=1 + $CHECKZONE -l 600 example zones/good1.db > test.out2.$n 2>&1 || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking with max ttl (raw) ($n)" + ret=0 + $CHECKZONE -f raw -l 300 example good1.db.raw > test.out1.$n 2>&1 && ret=1 + $CHECKZONE -f raw -l 600 example good1.db.raw > test.out2.$n 2>&1 || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking with max ttl (map) ($n)" + ret=0 +@@ -111,33 +111,33 @@ echo_i "checking for no 'inherited owner' warning on '\$INCLUDE file' with no ne + ret=0 + $CHECKZONE example zones/nowarn.inherited.owner.db > test.out1.$n 2>&1 || ret=1 + grep "inherited.owner" test.out1.$n > /dev/null && ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking for 'inherited owner' warning on '\$ORIGIN + \$INCLUDE file' ($n)" + ret=0 + $CHECKZONE example zones/warn.inherit.origin.db > test.out1.$n 2>&1 || ret=1 + grep "inherited.owner" test.out1.$n > /dev/null || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking for 'inherited owner' warning on '\$INCLUDE file origin' ($n)" + ret=0 + $CHECKZONE example zones/warn.inherited.owner.db > test.out1.$n 2>&1 || ret=1 + grep "inherited.owner" test.out1.$n > /dev/null || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking that raw zone with bad class is handled ($n)" + ret=0 + $CHECKZONE -f raw example zones/bad-badclass.raw > test.out.$n 2>&1 && ret=1 + grep "failed: bad class" test.out.$n >/dev/null || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking that expirations that loop using serial arithmetic are handled ($n)" + ret=0 +@@ -164,25 +164,25 @@ test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 + test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 + test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 + test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking that nameserver below DNAME is reported even with occulted address record present ($n)" + ret=0 + $CHECKZONE example.com zones/ns-address-below-dname.db > test.out.$n 2>&1 && ret=1 + grep "is below a DNAME" test.out.$n >/dev/null || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking that delegating nameserver below DNAME is reported even with occulted address record present ($n)" + ret=0 + $CHECKZONE example.com zones/delegating-ns-address-below-dname.db > test.out.$n 2>&1 || ret=1 + grep "is below a DNAME" test.out.$n >/dev/null || ret=1 +-n=`expr $n + 1` ++n=$((n+1)) + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "exit status: $status" + [ $status -eq 0 ] || exit 1 +-- +2.23.0 + diff --git a/backport-0025-Test-CDS-DELETE-persists-after-zone-sign.patch b/backport-0025-Test-CDS-DELETE-persists-after-zone-sign.patch new file mode 100644 index 0000000000000000000000000000000000000000..59c4558f824f169c6f17005ab45ef1af18e410dd --- /dev/null +++ b/backport-0025-Test-CDS-DELETE-persists-after-zone-sign.patch @@ -0,0 +1,297 @@ +From e5a5b23f410f60899453a713b98530f083647863 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Mon, 10 Jan 2022 15:46:25 +0100 +Subject: [PATCH] Test CDS DELETE persists after zone sign + +Add a test case for a dynamically added CDS DELETE record and make +sure it is not removed when signing the zone. This happens because +BIND maintains CDS and CDNSKEY publishing and it will only allow +CDS DELETE records if the zone is transitioning to insecure. This is +a state that can be identified when using KASP through 'dnssec-policy', +but not when using 'auto-dnssec'. + +(cherry picked from commit f08277f9fbbf3e38b855d6849c6d430d64bd3713) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/e5a5b23f410f60899453a713b98530f083647863 +--- + bin/tests/system/autosign/clean.sh | 2 + + bin/tests/system/autosign/ns2/keygen.sh | 5 +- + .../autosign/ns3/cdnskey-delete.example.db.in | 28 +++++++ + .../autosign/ns3/cds-delete.example.db.in | 28 +++++++ + bin/tests/system/autosign/ns3/keygen.sh | 25 +++++- + bin/tests/system/autosign/ns3/named.conf.in | 14 ++++ + bin/tests/system/autosign/tests.sh | 83 +++++++++++++++++++ + 7 files changed, 180 insertions(+), 5 deletions(-) + create mode 100644 bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in + create mode 100644 bin/tests/system/autosign/ns3/cds-delete.example.db.in + +diff --git a/bin/tests/system/autosign/clean.sh b/bin/tests/system/autosign/clean.sh +index bb738af862..f4ab636e8e 100644 +--- a/bin/tests/system/autosign/clean.sh ++++ b/bin/tests/system/autosign/clean.sh +@@ -35,6 +35,8 @@ rm -f ns2/private.secure.example.db ns2/bar.db + rm -f ns3/*.nzd ns3/*.nzd-lock ns3/*.nzf + rm -f ns3/*.nzf + rm -f ns3/autonsec3.example.db ++rm -f ns3/cdnskey-delete.example.db ++rm -f ns3/cds-delete.example.db + rm -f ns3/delzsk.example.db + rm -f ns3/dname-at-apex-nsec3.example.db + rm -f ns3/inacksk2.example.db +diff --git a/bin/tests/system/autosign/ns2/keygen.sh b/bin/tests/system/autosign/ns2/keygen.sh +index 8c9c80071c..383be7d3be 100644 +--- a/bin/tests/system/autosign/ns2/keygen.sh ++++ b/bin/tests/system/autosign/ns2/keygen.sh +@@ -17,8 +17,9 @@ SYSTEMTESTTOP=../.. + # Have the child generate subdomain keys and pass DS sets to us. + ( cd ../ns3 && $SHELL keygen.sh ) + +-for subdomain in secure nsec3 autonsec3 optout rsasha256 rsasha512 nsec3-to-nsec oldsigs sync \ +- dname-at-apex-nsec3 ++for subdomain in secure nsec3 autonsec3 optout rsasha256 rsasha512 \ ++ nsec3-to-nsec oldsigs sync dname-at-apex-nsec3 cds-delete \ ++ cdnskey-delete + do + cp ../ns3/dsset-$subdomain.example$TP . + done +diff --git a/bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in b/bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in +new file mode 100644 +index 0000000000..3083a79f7d +--- /dev/null ++++ b/bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in +@@ -0,0 +1,28 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, You can obtain one at http://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 300 ; 5 minutes ++@ IN SOA mname1. . ( ++ 2009102722 ; serial ++ 20 ; refresh (20 seconds) ++ 20 ; retry (20 seconds) ++ 1814400 ; expire (3 weeks) ++ 3600 ; minimum (1 hour) ++ ) ++ NS ns ++ns A 10.53.0.3 ++ ++a A 10.0.0.1 ++b A 10.0.0.2 ++d A 10.0.0.4 ++z A 10.0.0.26 ++a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 ++x CNAME a +diff --git a/bin/tests/system/autosign/ns3/cds-delete.example.db.in b/bin/tests/system/autosign/ns3/cds-delete.example.db.in +new file mode 100644 +index 0000000000..3083a79f7d +--- /dev/null ++++ b/bin/tests/system/autosign/ns3/cds-delete.example.db.in +@@ -0,0 +1,28 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, You can obtain one at http://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 300 ; 5 minutes ++@ IN SOA mname1. . ( ++ 2009102722 ; serial ++ 20 ; refresh (20 seconds) ++ 20 ; retry (20 seconds) ++ 1814400 ; expire (3 weeks) ++ 3600 ; minimum (1 hour) ++ ) ++ NS ns ++ns A 10.53.0.3 ++ ++a A 10.0.0.1 ++b A 10.0.0.2 ++d A 10.0.0.4 ++z A 10.0.0.26 ++a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 ++x CNAME a +diff --git a/bin/tests/system/autosign/ns3/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh +index 52b439f2bf..23d69f2fd5 100644 +--- a/bin/tests/system/autosign/ns3/keygen.sh ++++ b/bin/tests/system/autosign/ns3/keygen.sh +@@ -333,7 +333,7 @@ $KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 $zone > kg.out 2>&1 || du + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +-# A zone that starts with a active KSK + ZSK and a inactive ZSK. ++# A zone that starts with a active KSK + ZSK and a inactive ZSK. + # + setup inacksk3.example + cp $infile $zonefile +@@ -343,7 +343,7 @@ $KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP + + # +-# A zone that starts with a active KSK + ZSK and a inactive ZSK. ++# A zone that starts with a active KSK + ZSK and a inactive ZSK. + # + setup inaczsk3.example + cp $infile $zonefile +@@ -364,10 +364,29 @@ zsk=`$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -I now-1w $zone 2>kg.out` || dumpit kg. + echo $zsk > ../delzsk.key + + # +-# Check that NSEC3 are correctly signed and returned from below a DNAME ++# Check that NSEC3 are correctly signed and returned from below a DNAME + # + setup dname-at-apex-nsec3.example + cp $infile $zonefile + ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out + $KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key > dsset-${zone}$TP ++ ++# ++# Check that dynamically added CDS (DELETE) is kept in the zone after signing. ++# ++setup cds-delete.example ++cp $infile $zonefile ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out ++$DSFROMKEY $ksk.key > dsset-${zone}$TP ++ ++# ++# Check that dynamically added CDNSKEY (DELETE) is kept in the zone after ++# signing. ++# ++setup cdnskey-delete.example ++cp $infile $zonefile ++ksk=`$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out` || dumpit kg.out ++$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out ++$DSFROMKEY $ksk.key > dsset-${zone}$TP +diff --git a/bin/tests/system/autosign/ns3/named.conf.in b/bin/tests/system/autosign/ns3/named.conf.in +index 66d0e027a5..8f2eb5675a 100644 +--- a/bin/tests/system/autosign/ns3/named.conf.in ++++ b/bin/tests/system/autosign/ns3/named.conf.in +@@ -317,4 +317,18 @@ zone "dname-at-apex-nsec3.example" { + auto-dnssec maintain; + }; + ++zone "cds-delete.example" { ++ type primary; ++ file "cds-delete.example.db"; ++ allow-update { any; }; ++ auto-dnssec maintain; ++}; ++ ++zone "cdnskey-delete.example" { ++ type primary; ++ file "cdnskey-delete.example.db"; ++ allow-update { any; }; ++ auto-dnssec maintain; ++}; ++ + include "trusted.conf"; +diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh +index 448de3c55c..962ca4e546 100755 +--- a/bin/tests/system/autosign/tests.sh ++++ b/bin/tests/system/autosign/tests.sh +@@ -1638,6 +1638,89 @@ inac=`grep "DNSKEY .* is now inactive" ns1/named.run | wc -l` + [ "$inac" -eq 1 ] || ret=1 + del=`grep "DNSKEY .* is now deleted" ns1/named.run | wc -l` + [ "$del" -eq 1 ] || ret=1 ++n=`expr $n + 1` ++if [ $ret != 0 ]; then echo_i "failed"; fi ++status=`expr $status + $ret` ++ ++echo_i "checking that CDS (DELETE) persists after zone sign ($n)" ++echo_i "update add cds-delete.example. CDS 0 0 00" ++ret=0 ++$NSUPDATE > nsupdate.out 2>&1 < dig.out.ns3.test$n || return 1 ++ grep "CDS.*0.*0.*0.*00" dig.out.ns3.test$n > /dev/null 2>&1 || return 1 ++ return 0 ++) ++_cdnskey_delete_nx() { ++ $DIG $DIGOPTS +noall +answer $1 cdnskey @10.53.0.3 > dig.out.ns3.test$n || return 1 ++ grep "CDNSKEY.*0.*3.*0.*AA==" dig.out.ns3.test$n > /dev/null 2>&1 && return 1 ++ return 0 ++} ++ ++echo_i "query cds-delete.example. CDS" ++retry_quiet 10 _cds_delete cds-delete.example. || ret=1 ++echo_i "query cds-delete.example. CDNSKEY" ++retry_quiet 1 _cdnskey_delete_nx cds-delete.example. || ret=1 ++ ++echo_i "sign cds-delete.example." ++nextpart ns3/named.run >/dev/null ++$RNDCCMD 10.53.0.3 sign cds-delete.example > /dev/null 2>&1 || ret=1 ++wait_for_log 10 "zone cds-delete.example/IN: next key event" ns3/named.run ++# The CDS (DELETE) record should still be here. ++echo_i "query cds-delete.example. CDS" ++retry_quiet 1 _cds_delete cds-delete.example. || ret=1 ++# The CDNSKEY (DELETE) record should still not be added. ++echo_i "query cds-delete.example. CDNSKEY" ++retry_quiet 1 _cdnskey_delete_nx cds-delete.example. || ret=1 ++ ++n=`expr $n + 1` ++if [ $ret != 0 ]; then echo_i "failed"; fi ++status=`expr $status + $ret` ++ ++echo_i "checking that CDNSKEY (DELETE) persists after zone sign ($n)" ++echo_i "update add cdnskey-delete.example. CDNSKEY 0 3 0 AA==" ++ret=0 ++$NSUPDATE > nsupdate.out 2>&1 < dig.out.ns3.test$n || return 1 ++ grep "CDS.*0.*0.*0.*00" dig.out.ns3.test$n > /dev/null 2>&1 && return 1 ++ return 0 ++) ++_cdnskey_delete() { ++ $DIG $DIGOPTS +noall +answer $1 cdnskey @10.53.0.3 > dig.out.ns3.test$n || return 1 ++ grep "CDNSKEY.*0.*3.*0.*AA==" dig.out.ns3.test$n > /dev/null 2>&1 || return 1 ++ return 0 ++} ++ ++echo_i "query cdnskey-delete.example. CDNSKEY" ++retry_quiet 10 _cdnskey_delete cdnskey-delete.example. || ret=1 ++echo_i "query cdnskey-delete.example. CDS" ++retry_quiet 1 _cds_delete_nx cdnskey-delete.example. || ret=1 ++ ++echo_i "sign cdsnskey-delete.example." ++nextpart ns3/named.run >/dev/null ++$RNDCCMD 10.53.0.3 sign cdnskey-delete.example > /dev/null 2>&1 || ret=1 ++wait_for_log 10 "zone cdnskey-delete.example/IN: next key event" ns3/named.run ++# The CDNSKEY (DELETE) record should still be here. ++echo_i "query cdnskey-delete.example. CDNSKEY" ++retry_quiet 1 _cdnskey_delete cdnskey-delete.example. || ret=1 ++# The CDS (DELETE) record should still not be added. ++echo_i "query cdnskey-delete.example. CDS" ++retry_quiet 1 _cds_delete_nx cdnskey-delete.example. || ret=1 ++ ++n=`expr $n + 1` + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +-- +2.23.0 + diff --git a/backport-0025-Update-dns_dnssec_syncdelete-function.patch b/backport-0025-Update-dns_dnssec_syncdelete-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..97773ca616f9164af3746436995f38ad14cfa309 --- /dev/null +++ b/backport-0025-Update-dns_dnssec_syncdelete-function.patch @@ -0,0 +1,264 @@ +From 42f43cebdd6887d42e9b440c2f2e15dd0812f252 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Mon, 10 Jan 2022 17:18:47 +0100 +Subject: [PATCH] Update dns_dnssec_syncdelete() function + +Update the function that synchronizes the CDS and CDNSKEY DELETE +records. It now allows for the possibility that the CDS DELETE record +is published and the CDNSKEY DELETE record is not, and vice versa. + +Also update the code in zone.c how 'dns_dnssec_syncdelete()' is called. + +With KASP, we still maintain the DELETE records our self. Otherwise, +we publish the CDS and CDNSKEY DELETE record only if they are added +to the zone. We do still check if these records can be signed by a KSK. + +This change will allow users to add a CDS and/or CDNSKEY DELETE record +manually, without BIND removing them on the next zone sign. + +Note that this commit removes the check whether the key is a KSK, this +check is redundant because this check is also made in +'dst_key_is_signing()' when the role is set to DST_BOOL_KSK. + +(cherry picked from commit 3d05c99abbfc34644ffeffe2884b6335fc12e055) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/42f43cebdd6887d42e9b440c2f2e15dd0812f252 +--- + lib/dns/dnssec.c | 44 +++++++++--------- + lib/dns/include/dns/dnssec.h | 9 ++-- + lib/dns/zone.c | 87 +++++++++++++++++++++++++++++------- + 3 files changed, 99 insertions(+), 41 deletions(-) + +diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c +index f9ae6acbb4..64c72b5d7a 100644 +--- a/lib/dns/dnssec.c ++++ b/lib/dns/dnssec.c +@@ -2147,7 +2147,7 @@ isc_result_t + dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey, + dns_name_t *origin, dns_rdataclass_t zclass, + dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx, +- bool dnssec_insecure) { ++ bool expect_cds_delete, bool expect_cdnskey_delete) { + unsigned char dsbuf[5] = { 0, 0, 0, 0, 0 }; /* CDS DELETE rdata */ + unsigned char keybuf[5] = { 0, 0, 3, 0, 0 }; /* CDNSKEY DELETE rdata */ + char namebuf[DNS_NAME_FORMATSIZE]; +@@ -2167,26 +2167,39 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey, + + dns_name_format(origin, namebuf, sizeof(namebuf)); + +- if (dnssec_insecure) { +- if (!dns_rdataset_isassociated(cdnskey) || +- !exists(cdnskey, &cdnskey_delete)) { ++ if (expect_cds_delete) { ++ if (!dns_rdataset_isassociated(cds) || ++ !exists(cds, &cds_delete)) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, +- "CDNSKEY (DELETE) for zone %s is now " ++ "CDS (DELETE) for zone %s is now " + "published", + namebuf); +- RETERR(addrdata(&cdnskey_delete, diff, origin, ttl, ++ RETERR(addrdata(&cds_delete, diff, origin, ttl, mctx)); ++ } ++ } else { ++ if (dns_rdataset_isassociated(cds) && exists(cds, &cds_delete)) ++ { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, ++ DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, ++ "CDS (DELETE) for zone %s is now " ++ "deleted", ++ namebuf); ++ RETERR(delrdata(&cds_delete, diff, origin, cds->ttl, + mctx)); + } ++ } + +- if (!dns_rdataset_isassociated(cds) || +- !exists(cds, &cds_delete)) { ++ if (expect_cdnskey_delete) { ++ if (!dns_rdataset_isassociated(cdnskey) || ++ !exists(cdnskey, &cdnskey_delete)) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, +- "CDS (DELETE) for zone %s is now " ++ "CDNSKEY (DELETE) for zone %s is now " + "published", + namebuf); +- RETERR(addrdata(&cds_delete, diff, origin, ttl, mctx)); ++ RETERR(addrdata(&cdnskey_delete, diff, origin, ttl, ++ mctx)); + } + } else { + if (dns_rdataset_isassociated(cdnskey) && +@@ -2199,17 +2212,6 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey, + RETERR(delrdata(&cdnskey_delete, diff, origin, + cdnskey->ttl, mctx)); + } +- +- if (dns_rdataset_isassociated(cds) && exists(cds, &cds_delete)) +- { +- isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, +- DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, +- "CDS (DELETE) for zone %s is now " +- "deleted", +- namebuf); +- RETERR(delrdata(&cds_delete, diff, origin, cds->ttl, +- mctx)); +- } + } + + result = ISC_R_SUCCESS; +diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h +index 0ac96fceb5..9791ef128d 100644 +--- a/lib/dns/include/dns/dnssec.h ++++ b/lib/dns/include/dns/dnssec.h +@@ -370,11 +370,14 @@ isc_result_t + dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey, + dns_name_t *origin, dns_rdataclass_t zclass, + dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx, +- bool dnssec_insecure); ++ bool expect_cds_delete, bool expect_cdnskey_delete); + /*%< + * Add or remove the CDS DELETE record and the CDNSKEY DELETE record. +- * If 'dnssec_insecure' is true, the DELETE records should be present. +- * Otherwise, the DELETE records must be removed from the RRsets (if present). ++ * If 'expect_cds_delete' is true, the CDS DELETE record should be present. ++ * Otherwise, the CDS DELETE record must be removed from the RRsets (if ++ * present). If 'expect_cdnskey_delete' is true, the CDNSKEY DELETE record ++ * should be present. Otherwise, the CDNSKEY DELETE record must be removed ++ * from the RRsets (if present). + * + * Returns: + *\li ISC_R_SUCCESS +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 131e3200d2..76f03683de 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -21483,16 +21483,69 @@ zone_rekey(dns_zone_t *zone) { + KASP_UNLOCK(kasp); + + if (result == ISC_R_SUCCESS) { +- bool cds_delete = false; ++ bool cdsdel = false; ++ bool cdnskeydel = false; + isc_stdtime_t when; + + /* + * Publish CDS/CDNSKEY DELETE records if the zone is + * transitioning from secure to insecure. + */ +- if (kasp != NULL && +- strcmp(dns_kasp_getname(kasp), "insecure") == 0) { +- cds_delete = true; ++ if (kasp != NULL) { ++ if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) { ++ cdsdel = true; ++ cdnskeydel = true; ++ } ++ } else { ++ /* Check if there is a CDS DELETE record. */ ++ if (dns_rdataset_isassociated(&cdsset)) { ++ for (result = dns_rdataset_first(&cdsset); ++ result == ISC_R_SUCCESS; ++ result = dns_rdataset_next(&cdsset)) ++ { ++ dns_rdata_t crdata = DNS_RDATA_INIT; ++ dns_rdataset_current(&cdsset, &crdata); ++ /* ++ * CDS deletion record has this form ++ * "0 0 0 00" which is 5 zero octets. ++ */ ++ if (crdata.length == 5U && ++ memcmp(crdata.data, ++ (unsigned char[5]){ 0, 0, 0, ++ 0, 0 }, ++ 5) == 0) ++ { ++ cdsdel = true; ++ break; ++ } ++ } ++ } ++ ++ /* Check if there is a CDNSKEY DELETE record. */ ++ if (dns_rdataset_isassociated(&cdnskeyset)) { ++ for (result = dns_rdataset_first(&cdnskeyset); ++ result == ISC_R_SUCCESS; ++ result = dns_rdataset_next(&cdnskeyset)) ++ { ++ dns_rdata_t crdata = DNS_RDATA_INIT; ++ dns_rdataset_current(&cdnskeyset, ++ &crdata); ++ /* ++ * CDNSKEY deletion record has this form ++ * "0 3 0 AA==" which is 2 zero octets, ++ * a 3, and 2 zero octets. ++ */ ++ if (crdata.length == 5U && ++ memcmp(crdata.data, ++ (unsigned char[5]){ 0, 0, 3, ++ 0, 0 }, ++ 5) == 0) ++ { ++ cdnskeydel = true; ++ break; ++ } ++ } ++ } + } + + /* +@@ -21529,36 +21582,36 @@ zone_rekey(dns_zone_t *zone) { + goto failure; + } + +- if (cds_delete) { ++ if (cdsdel || cdnskeydel) { + /* + * Only publish CDS/CDNSKEY DELETE records if there is + * a KSK that can be used to verify the RRset. This + * means there must be a key with the KSK role that is + * published and is used for signing. + */ +- cds_delete = false; ++ bool allow = false; + for (key = ISC_LIST_HEAD(dnskeys); key != NULL; + key = ISC_LIST_NEXT(key, link)) { + dst_key_t *dstk = key->key; +- bool ksk = false; +- (void)dst_key_getbool(dstk, DST_BOOL_KSK, &ksk); +- if (!ksk) { +- continue; +- } + +- if (dst_key_haskasp(dstk) && +- dst_key_is_published(dstk, now, &when) && ++ if (dst_key_is_published(dstk, now, &when) && + dst_key_is_signing(dstk, DST_BOOL_KSK, now, + &when)) + { +- cds_delete = true; ++ allow = true; + break; + } + } ++ if (cdsdel) { ++ cdsdel = allow; ++ } ++ if (cdnskeydel) { ++ cdnskeydel = allow; ++ } + } +- result = dns_dnssec_syncdelete(&cdsset, &cdnskeyset, +- &zone->origin, zone->rdclass, +- ttl, &diff, mctx, cds_delete); ++ result = dns_dnssec_syncdelete( ++ &cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl, ++ &diff, mctx, cdsdel, cdnskeydel); + if (result != ISC_R_SUCCESS) { + dnssec_log(zone, ISC_LOG_ERROR, + "zone_rekey:couldn't update CDS/CDNSKEY " +-- +2.23.0 + diff --git a/backport-0026-Check-that-pending-negative-cache-entries-for-DS-can.patch b/backport-0026-Check-that-pending-negative-cache-entries-for-DS-can.patch new file mode 100644 index 0000000000000000000000000000000000000000..ca1459b787b2bbff590429f75fbe890d31afeca7 --- /dev/null +++ b/backport-0026-Check-that-pending-negative-cache-entries-for-DS-can.patch @@ -0,0 +1,118 @@ +From b5f2ab9cd4e7d0fbcdce35e39e8b81f37699b5ad Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 14 Apr 2022 10:57:11 +1000 +Subject: [PATCH] Check that pending negative cache entries for DS can be used + successfully + +Prime the cache with a negative cache DS entry then make a query for +name beneath that entry. This will cause the DS entry to be retieved +as part of the validation process. Each RRset in the ncache entry +will be validated and the trust level for each will be updated. + +(cherry picked from commit d2d9910da23951bf310c7be8ba68e1030eb13caa) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/b5f2ab9cd4e7d0fbcdce35e39e8b81f37699b5ad +--- + bin/tests/system/dnssec/ns2/example.db.in | 4 +++ + .../system/dnssec/ns3/insecure2.example.db | 27 +++++++++++++++++++ + bin/tests/system/dnssec/ns3/named.conf.in | 6 +++++ + bin/tests/system/dnssec/tests.sh | 18 +++++++++++++ + 4 files changed, 55 insertions(+) + create mode 100644 bin/tests/system/dnssec/ns3/insecure2.example.db + +diff --git a/bin/tests/system/dnssec/ns2/example.db.in b/bin/tests/system/dnssec/ns2/example.db.in +index 5ec88013c9..f711f5823f 100644 +--- a/bin/tests/system/dnssec/ns2/example.db.in ++++ b/bin/tests/system/dnssec/ns2/example.db.in +@@ -55,6 +55,10 @@ ns3.secure A 10.53.0.3 + insecure NS ns.insecure + ns.insecure A 10.53.0.3 + ++; A second insecure subdomain ++insecure2 NS ns.insecure2 ++ns.insecure2 A 10.53.0.3 ++ + ; A secure subdomain we're going to inject bogus data into + bogus NS ns.bogus + ns.bogus A 10.53.0.3 +diff --git a/bin/tests/system/dnssec/ns3/insecure2.example.db b/bin/tests/system/dnssec/ns3/insecure2.example.db +new file mode 100644 +index 0000000000..76e3f47f21 +--- /dev/null ++++ b/bin/tests/system/dnssec/ns3/insecure2.example.db +@@ -0,0 +1,27 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 300 ; 5 minutes ++@ IN SOA mname1. . ( ++ 2000042407 ; serial ++ 20 ; refresh (20 seconds) ++ 20 ; retry (20 seconds) ++ 1814400 ; expire (3 weeks) ++ 3600 ; minimum (1 hour) ++ ) ++ NS ns ++ns A 10.53.0.3 ++ ++a A 10.0.0.1 ++b A 10.0.0.2 ++d A 10.0.0.4 ++x DNSKEY 258 3 5 Cg== ++z A 10.0.0.26 +diff --git a/bin/tests/system/dnssec/ns3/named.conf.in b/bin/tests/system/dnssec/ns3/named.conf.in +index 202f6a931d..bd0771dd49 100644 +--- a/bin/tests/system/dnssec/ns3/named.conf.in ++++ b/bin/tests/system/dnssec/ns3/named.conf.in +@@ -78,6 +78,12 @@ zone "insecure.example" { + allow-update { any; }; + }; + ++zone "insecure2.example" { ++ type primary; ++ file "insecure2.example.db"; ++ allow-update { any; }; ++}; ++ + zone "insecure.nsec3.example" { + type primary; + file "insecure.nsec3.example.db"; +diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh +index c6410ae79e..db3e19533e 100644 +--- a/bin/tests/system/dnssec/tests.sh ++++ b/bin/tests/system/dnssec/tests.sh +@@ -4412,5 +4412,23 @@ n=$((n+1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + ++# Check that a query against a validating resolver succeeds when there is ++# a negative cache entry with trust level "pending" for the DS. Prime ++# with a +cd DS query to produce the negative cache entry, then send a ++# query that uses that entry as part of the validation process. [GL #3279] ++echo_i "check that pending negative DS cache entry validates ($n)" ++ret=0 ++dig_with_opts @10.53.0.4 +cd insecure2.example. ds > dig.out.prime.ns4.test$n || ret=1 ++grep "flags: qr rd ra cd;" dig.out.prime.ns4.test$n >/dev/null || ret=1 ++grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1 ++grep "ANSWER: 0, AUTHORITY: 4, " dig.out.prime.ns4.test$n > /dev/null || ret=1 ++dig_with_opts @10.53.0.4 a.insecure2.example. a > dig.out.ns4.test$n || ret=1 ++grep "ANSWER: 1, AUTHORITY: 1, " dig.out.ns4.test$n > /dev/null || ret=1 ++grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 ++grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 ++n=$((n+1)) ++if [ "$ret" -ne 0 ]; then echo_i "failed"; fi ++status=$((status+ret)) ++ + echo_i "exit status: $status" + [ $status -eq 0 ] || exit 1 +-- +2.23.0 + diff --git a/backport-0026-Update-the-rdataset-trust-field-in-ncache.c-rdataset.patch b/backport-0026-Update-the-rdataset-trust-field-in-ncache.c-rdataset.patch new file mode 100644 index 0000000000000000000000000000000000000000..417c4a08a262389c968e5cef2bb2dca3cae330f7 --- /dev/null +++ b/backport-0026-Update-the-rdataset-trust-field-in-ncache.c-rdataset.patch @@ -0,0 +1,31 @@ +From cb3c29cf8e77223d34f52e9fdf2ffb05337afe33 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 14 Apr 2022 11:16:32 +1000 +Subject: [PATCH] Update the rdataset->trust field in + ncache.c:rdataset_settrust + +Both the trust recorded in the slab stucture and the trust on +rdataset need to be updated. + +(cherry picked from commit d043a41499f5cc52920841ca7332b7cce7460aad) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/cb3c29cf8e77223d34f52e9fdf2ffb05337afe33 +--- + lib/dns/ncache.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c +index 2316eb04a7..7bea3d376c 100644 +--- a/lib/dns/ncache.c ++++ b/lib/dns/ncache.c +@@ -504,6 +504,7 @@ rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { + unsigned char *raw = rdataset->private3; + + raw[-1] = (unsigned char)trust; ++ rdataset->trust = trust; + } + + static dns_rdatasetmethods_t rdataset_methods = { +-- +2.23.0 + diff --git a/backport-0027-Prevent-memory-bloat-caused-by-a-jemalloc-quirk.patch b/backport-0027-Prevent-memory-bloat-caused-by-a-jemalloc-quirk.patch new file mode 100644 index 0000000000000000000000000000000000000000..418214fc87f1ba20b323fb60991800cc364a9188 --- /dev/null +++ b/backport-0027-Prevent-memory-bloat-caused-by-a-jemalloc-quirk.patch @@ -0,0 +1,91 @@ +From e850946557469f2cbe4fab76d1c52227ddf81a93 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= +Date: Thu, 21 Apr 2022 14:19:39 +0200 +Subject: [PATCH] Prevent memory bloat caused by a jemalloc quirk + +Since version 5.0.0, decay-based purging is the only available dirty +page cleanup mechanism in jemalloc. It relies on so-called tickers, +which are simple data structures used for ensuring that certain actions +are taken "once every N times". Ticker data (state) is stored in a +thread-specific data structure called tsd in jemalloc parlance. Ticks +are triggered when extents are allocated and deallocated. Once every +1000 ticks, jemalloc attempts to release some of the dirty pages hanging +around (if any). This allows memory use to be kept in check over time. + +This dirty page cleanup mechanism has a quirk. If the first +allocator-related action for a given thread is a free(), a +minimally-initialized tsd is set up which does not include ticker data. +When that thread subsequently calls *alloc(), the tsd transitions to its +nominal state, but due to a certain flag being set during minimal tsd +initialization, ticker data remains unallocated. This prevents +decay-based dirty page purging from working, effectively enabling memory +exhaustion over time. [1] + +The quirk described above has been addressed (by moving ticker state to +a different structure) in jemalloc's development branch [2], but not in +any numbered jemalloc version released to date (the latest one being +5.2.1 as of this writing). + +Work around the problem by ensuring that every thread spawned by +isc_thread_create() starts with a malloc() call. Avoid immediately +calling free() for the dummy allocation to prevent an optimizing +compiler from stripping away the malloc() + free() pair altogether. + +An alternative implementation of this workaround was considered that +used a pair of isc_mem_create() + isc_mem_destroy() calls instead of +malloc() + free(), enabling the change to be fully contained within +isc__trampoline_run() (i.e. to not touch struct isc__trampoline), as the +compiler is not allowed to strip away arbitrary function calls. +However, that solution was eventually dismissed as it triggered +ThreadSanitizer reports when tools like dig, nsupdate, or rndc exited +abruptly without waiting for all worker threads to finish their work. + +[1] https://github.com/jemalloc/jemalloc/issues/2251 +[2] https://github.com/jemalloc/jemalloc/commit/c259323ab3082324100c708109dbfff660d0f4b8 + +(cherry picked from commit 7aa7b6474bc5ea2b4ec4806c7509dc5ea73396e1) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/e850946557469f2cbe4fab76d1c52227ddf81a93 +--- + lib/isc/trampoline.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/lib/isc/trampoline.c b/lib/isc/trampoline.c +index 4caa2e7574..e133c40084 100644 +--- a/lib/isc/trampoline.c ++++ b/lib/isc/trampoline.c +@@ -31,6 +31,7 @@ struct isc__trampoline { + uintptr_t self; + isc_threadfunc_t start; + isc_threadarg_t arg; ++ void *jemalloc_enforce_init; + }; + + static isc_once_t isc__trampoline_initialize_once = ISC_ONCE_INIT; +@@ -170,6 +171,7 @@ isc__trampoline_detach(isc__trampoline_t *trampoline) { + isc__trampoline_min = trampoline->tid; + } + ++ free(trampoline->jemalloc_enforce_init); + free(trampoline); + + UNLOCK(&isc__trampoline_lock); +@@ -185,6 +187,15 @@ isc__trampoline_attach(isc__trampoline_t *trampoline) { + /* Initialize the trampoline */ + isc_tid_v = trampoline->tid; + trampoline->self = isc_thread_self(); ++ ++ /* ++ * Ensure every thread starts with a malloc() call to prevent memory ++ * bloat caused by a jemalloc quirk. While this dummy allocation is ++ * not used for anything, free() must not be immediately called for it ++ * so that an optimizing compiler does not strip away such a pair of ++ * malloc() + free() calls altogether, as it would foil the fix. ++ */ ++ trampoline->jemalloc_enforce_init = malloc(8); + } + + isc_threadresult_t +-- +2.23.0 + diff --git a/backport-0028-Ensure-diff-variable-is-not-read-uninitialized.patch b/backport-0028-Ensure-diff-variable-is-not-read-uninitialized.patch new file mode 100644 index 0000000000000000000000000000000000000000..b0707a670b3e16b42bb72769d36d038ef59dd30a --- /dev/null +++ b/backport-0028-Ensure-diff-variable-is-not-read-uninitialized.patch @@ -0,0 +1,42 @@ +From 1bc75522035142a986466b321eefa42bb7bdb47a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 19 Jan 2022 13:35:32 +0100 +Subject: [PATCH] Ensure diff variable is not read uninitialized + +Coverity detected issues: +- var_decl: Declaring variable "diff" without initializer. +- uninit_use_in_call: Using uninitialized value "diff.tuples.head" when + calling "dns_diff_clear". + +(cherry picked from commit 67e773c93c2fe164e3791e0b843f724a6d9358d4) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/1bc75522035142a986466b321eefa42bb7bdb47a +--- + lib/dns/zone.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 76f03683de..b7b02ae5f9 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -23328,7 +23328,7 @@ setserial(isc_task_t *task, isc_event_t *event) { + ENTER; + + if (zone->update_disabled) { +- goto failure; ++ goto disabled; + } + + desired = sse->serial; +@@ -23407,6 +23407,8 @@ failure: + dns_db_detach(&db); + } + dns_diff_clear(&diff); ++ ++disabled: + isc_event_free(&event); + dns_zone_idetach(&zone); + +-- +2.23.0 + diff --git a/backport-0029-Initialize-printed-buffer.patch b/backport-0029-Initialize-printed-buffer.patch new file mode 100644 index 0000000000000000000000000000000000000000..37bedce9d92da150fc6ed96c796b209cb72d90df --- /dev/null +++ b/backport-0029-Initialize-printed-buffer.patch @@ -0,0 +1,46 @@ +From 1e88c0196c427de538f8ddfd6c1c3c7dd72f11d5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 19 Jan 2022 14:47:13 +0100 +Subject: [PATCH] Initialize printed buffer + +- var_decl: Declaring variable "tbuf" without initializer +- assign: Assigning: "target.base" = "tbuf", which points to + uninitialized data +- assign: Assigning: "r.base" = "target.base", which points to + uninitialized data + +I expect it would correctly initialize length always. Add simple +initialization to silent coverity. + +(cherry picked from commit 59132bd3ec8a9f648a1e1cf59f5f3b2d59f17927) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/1e88c0196c427de538f8ddfd6c1c3c7dd72f11d5 +--- + bin/dig/host.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/bin/dig/host.c b/bin/dig/host.c +index 646c89783e..971cd974b7 100644 +--- a/bin/dig/host.c ++++ b/bin/dig/host.c +@@ -208,15 +208,9 @@ printsection(dns_message_t *msg, dns_section_t sectionid, + isc_result_t result, loopresult; + isc_region_t r; + dns_name_t empty_name; +- char tbuf[4096]; ++ char tbuf[4096] = { 0 }; + bool first; +- bool no_rdata; +- +- if (sectionid == DNS_SECTION_QUESTION) { +- no_rdata = true; +- } else { +- no_rdata = false; +- } ++ bool no_rdata = (sectionid == DNS_SECTION_QUESTION); + + if (headers) { + printf(";; %s SECTION:\n", section_name); +-- +2.23.0 + diff --git a/backport-0030-Additional-safety-check-for-negative-array-index.patch b/backport-0030-Additional-safety-check-for-negative-array-index.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc8d28c0a509026781f676bd6fd7a753888d4e16 --- /dev/null +++ b/backport-0030-Additional-safety-check-for-negative-array-index.patch @@ -0,0 +1,35 @@ +From c1b3862c4aef91b7b6a30c7cabb1f578839db83a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 19 Jan 2022 17:05:00 +0100 +Subject: [PATCH] Additional safety check for negative array index + +inet_ntop result should always protect against empty string accepted +without an error. Make additional check to satisfy coverity scans. + +(cherry picked from commit 656a0f076f7f49d166b414d7cf5972d2919877d5) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/c1b3862c4aef91b7b6a30c7cabb1f578839db83a +--- + lib/dns/rdata.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c +index 2c94d11765..b44894adbe 100644 +--- a/lib/dns/rdata.c ++++ b/lib/dns/rdata.c +@@ -1890,9 +1890,9 @@ inet_totext(int af, uint32_t flags, isc_region_t *src, isc_buffer_t *target) { + * parsing, so append 0 in that case. + */ + if (af == AF_INET6 && (flags & DNS_STYLEFLAG_YAML) != 0) { +- isc_textregion_t tr; +- isc_buffer_usedregion(target, (isc_region_t *)&tr); +- if (tr.base[tr.length - 1] == ':') { ++ isc_region_t r; ++ isc_buffer_usedregion(target, &r); ++ if (r.length > 0 && r.base[r.length - 1] == ':') { + if (isc_buffer_availablelength(target) == 0) { + return (ISC_R_NOSPACE); + } +-- +2.23.0 + diff --git a/backport-0031-Fix-dig-nssearch-race-between-recv_done-and-send_don.patch b/backport-0031-Fix-dig-nssearch-race-between-recv_done-and-send_don.patch new file mode 100644 index 0000000000000000000000000000000000000000..04df5063c65519b4935b4b76ed8f572dec25b521 --- /dev/null +++ b/backport-0031-Fix-dig-nssearch-race-between-recv_done-and-send_don.patch @@ -0,0 +1,77 @@ +From 1f2d2611ee23f0b9200dbea8a7b65fa9f3b86e3f Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Tue, 12 Apr 2022 13:00:45 +0000 +Subject: [PATCH] Fix dig +nssearch race between recv_done() and send_done() + +The `send_done()` callback needs to access query's `link.next` pointer +when running in `+nssearch` mode, even if the query is already canceled +or serviced, which can happen when `recv_done()` happens to be called +earlier than `send_done()`. + +Keep the next query's pointer before unlinking the query from the +lookup's queries list in `clear_query()` so that `send_done()` can +use it even if the query is cleared. +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/1f2d2611ee23f0b9200dbea8a7b65fa9f3b86e3f +--- + bin/dig/dighost.c | 8 ++++++-- + bin/dig/include/dig/dig.h | 1 + + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c +index 27af3c80f1..e0ba9c2aae 100644 +--- a/bin/dig/dighost.c ++++ b/bin/dig/dighost.c +@@ -1591,6 +1591,7 @@ clear_query(dig_query_t *query) { + } + + if (ISC_LINK_LINKED(query, link)) { ++ query->saved_next = ISC_LIST_NEXT(query, link); + ISC_LIST_UNLINK(lookup->q, query, link); + } + if (ISC_LINK_LINKED(query, clink)) { +@@ -1609,6 +1610,7 @@ clear_query(dig_query_t *query) { + isc_buffer_invalidate(&query->lengthbuf); + + if (query->waiting_senddone) { ++ debug("waiting senddone, delay freeing query"); + query->pending_free = true; + } else { + query->magic = 0; +@@ -2583,6 +2585,7 @@ setup_lookup(dig_lookup_t *lookup) { + + ISC_LINK_INIT(query, clink); + ISC_LINK_INIT(query, link); ++ query->saved_next = NULL; + + query->magic = DIG_QUERY_MAGIC; + +@@ -2617,10 +2620,11 @@ send_done(isc_task_t *_task, isc_event_t *event) { + query->waiting_senddone = false; + l = query->lookup; + +- if (!query->pending_free && l->ns_search_only && !l->trace_root && ++ if (l == current_lookup && l->ns_search_only && !l->trace_root && + !l->tcp_mode) { + debug("sending next, since searching"); +- next = ISC_LIST_NEXT(query, link); ++ next = query->pending_free ? query->saved_next ++ : ISC_LIST_NEXT(query, link); + if (next != NULL) { + send_udp(next); + } +diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h +index 79a868d1ef..9683e39892 100644 +--- a/bin/dig/include/dig/dig.h ++++ b/bin/dig/include/dig/dig.h +@@ -183,6 +183,7 @@ struct dig_query { + isc_socket_t *sock; + ISC_LINK(dig_query_t) link; + ISC_LINK(dig_query_t) clink; ++ dig_query_t *saved_next; + isc_sockaddr_t sockaddr; + isc_time_t time_sent; + isc_time_t time_recv; +-- +2.23.0 + diff --git a/backport-0032-Add-test-cases-using-static-and-static-stub-zones.patch b/backport-0032-Add-test-cases-using-static-and-static-stub-zones.patch new file mode 100644 index 0000000000000000000000000000000000000000..22d130cac6beeabe81104bae9d00b151a3a34940 --- /dev/null +++ b/backport-0032-Add-test-cases-using-static-and-static-stub-zones.patch @@ -0,0 +1,308 @@ +From 967e5e09cd80bd74f96ad49d65b564ac58023f0c Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Mon, 28 Mar 2022 16:36:03 +1100 +Subject: [PATCH] Add test cases using static and static-stub zones + +RPZ NSIP and NSDNAME checks were failing with "unrecognized NS +rpz_rrset_find() failed: glue" when static or static-stub zones +where used to resolve the query name. + +Add tests using stub and static-stub zones that are expected to +be filtered and not-filtered against NSIP and NSDNAME rules. + +stub and static-stub queries are expected to be filtered + +stub-nomatch and static-stub-nomatch queries are expected to be passed + +(cherry picked from commit 30cb70c82671e345810be546ffa902631b43d306) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/967e5e09cd80bd74f96ad49d65b564ac58023f0c +--- + bin/tests/system/rpz/ns10/hints | 13 ++++++++ + bin/tests/system/rpz/ns10/named.conf.in | 42 +++++++++++++++++++++++++ + bin/tests/system/rpz/ns10/stub.db | 21 +++++++++++++ + bin/tests/system/rpz/ns2/named.conf.in | 4 +++ + bin/tests/system/rpz/ns2/stub.db | 20 ++++++++++++ + bin/tests/system/rpz/ns3/named.conf.in | 20 ++++++++++++ + bin/tests/system/rpz/setup.sh | 1 + + bin/tests/system/rpz/tests.sh | 37 ++++++++++++++++++---- + 8 files changed, 152 insertions(+), 6 deletions(-) + create mode 100644 bin/tests/system/rpz/ns10/hints + create mode 100644 bin/tests/system/rpz/ns10/named.conf.in + create mode 100644 bin/tests/system/rpz/ns10/stub.db + create mode 100644 bin/tests/system/rpz/ns2/stub.db + +diff --git a/bin/tests/system/rpz/ns10/hints b/bin/tests/system/rpz/ns10/hints +new file mode 100644 +index 0000000000..b657c3980e +--- /dev/null ++++ b/bin/tests/system/rpz/ns10/hints +@@ -0,0 +1,13 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++. 120 NS ns. ++ns. 120 A 10.53.0.1 +diff --git a/bin/tests/system/rpz/ns10/named.conf.in b/bin/tests/system/rpz/ns10/named.conf.in +new file mode 100644 +index 0000000000..b34ce79bb4 +--- /dev/null ++++ b/bin/tests/system/rpz/ns10/named.conf.in +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++ * ++ * SPDX-License-Identifier: MPL-2.0 ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, you can obtain one at https://mozilla.org/MPL/2.0/. ++ * ++ * See the COPYRIGHT file distributed with this work for additional ++ * information regarding copyright ownership. ++ */ ++ ++options { ++ query-source address 10.53.0.10; ++ notify-source 10.53.0.10; ++ transfer-source 10.53.0.10; ++ port @PORT@; ++ pid-file "named.pid"; ++ session-keyfile "session.key"; ++ listen-on { 10.53.0.10; }; ++ listen-on-v6 { none; }; ++ notify no; ++ minimal-responses no; ++ recursion yes; ++ dnssec-validation yes; ++}; ++ ++key rndc_key { ++ secret "1234abcd8765"; ++ algorithm hmac-sha256; ++}; ++controls { ++ inet 10.53.0.10 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; ++}; ++ ++include "../trusted.conf"; ++zone "." { type hint; file "hints"; }; ++ ++# grafted on zones using stub and static-stub ++zone "stub-nomatch." {type primary; file "stub.db"; }; ++zone "static-stub-nomatch." {type primary; file "stub.db"; }; +diff --git a/bin/tests/system/rpz/ns10/stub.db b/bin/tests/system/rpz/ns10/stub.db +new file mode 100644 +index 0000000000..8ecac8c2b2 +--- /dev/null ++++ b/bin/tests/system/rpz/ns10/stub.db +@@ -0,0 +1,21 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++; RPZ rewrite responses from this zone ++ ++$TTL 120 ++@ SOA ns hostmaster.ns ( 1 3600 1200 604800 60 ) ++ NS ns ++ns A 10.53.0.10 ++ ++a3-1 A 10.53.99.99 ++ ++a4-1 A 10.53.99.99 +diff --git a/bin/tests/system/rpz/ns2/named.conf.in b/bin/tests/system/rpz/ns2/named.conf.in +index 48ab311a97..1dde354562 100644 +--- a/bin/tests/system/rpz/ns2/named.conf.in ++++ b/bin/tests/system/rpz/ns2/named.conf.in +@@ -49,3 +49,7 @@ zone "tld2s." {type primary; file "tld2s.db";}; + + zone "bl.tld2." {type primary; file "bl.tld2.db"; + notify yes; notify-delay 0;}; ++ ++# grafted on zones using stub and static-stub ++zone "stub." {type primary; file "stub.db"; }; ++zone "static-stub." {type primary; file "stub.db"; }; +diff --git a/bin/tests/system/rpz/ns2/stub.db b/bin/tests/system/rpz/ns2/stub.db +new file mode 100644 +index 0000000000..e4b87817e7 +--- /dev/null ++++ b/bin/tests/system/rpz/ns2/stub.db +@@ -0,0 +1,20 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++; RPZ rewrite responses from this zone ++ ++$TTL 120 ++@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) ++ NS ns.sub1.tld2. ++ ++a3-1 A 10.53.99.99 ++ ++a4-1 A 10.53.99.99 +diff --git a/bin/tests/system/rpz/ns3/named.conf.in b/bin/tests/system/rpz/ns3/named.conf.in +index e5545a8720..30f08c804c 100644 +--- a/bin/tests/system/rpz/ns3/named.conf.in ++++ b/bin/tests/system/rpz/ns3/named.conf.in +@@ -128,3 +128,23 @@ zone "fast-expire." { + primaries { 10.53.0.5; }; + notify no; + }; ++ ++zone "stub." { ++ type stub; ++ primaries { 10.53.0.2; }; ++}; ++ ++zone "static-stub." { ++ type static-stub; ++ server-addresses { 10.53.0.2; }; ++}; ++ ++zone "stub-nomatch." { ++ type stub; ++ primaries { 10.53.0.10; }; ++}; ++ ++zone "static-stub-nomatch." { ++ type static-stub; ++ server-addresses { 10.53.0.10; }; ++}; +diff --git a/bin/tests/system/rpz/setup.sh b/bin/tests/system/rpz/setup.sh +index f9897b34de..fea43bdc36 100644 +--- a/bin/tests/system/rpz/setup.sh ++++ b/bin/tests/system/rpz/setup.sh +@@ -54,6 +54,7 @@ copy_setports ns6/named.conf.in ns6/named.conf + copy_setports ns7/named.conf.in ns7/named.conf + copy_setports ns8/named.conf.in ns8/named.conf + copy_setports ns9/named.conf.in ns9/named.conf ++copy_setports ns10/named.conf.in ns10/named.conf + + copy_setports dnsrpzd.conf.in dnsrpzd.conf + +diff --git a/bin/tests/system/rpz/tests.sh b/bin/tests/system/rpz/tests.sh +index 56a7f2e683..9fc5d08cf2 100644 +--- a/bin/tests/system/rpz/tests.sh ++++ b/bin/tests/system/rpz/tests.sh +@@ -28,6 +28,8 @@ ns5=$ns.5 # another rewriting resolver + ns6=$ns.6 # a forwarding server + ns7=$ns.7 # another rewriting resolver + ns8=$ns.8 # another rewriting resolver ++ns9=$ns.9 # another rewriting resolver ++ns10=$ns.10 # authoritative server + + HAVE_CORE= + +@@ -406,6 +408,13 @@ nochange () { + ckresult "$*" ${DIGNM}_OK && clean_result ${DIGNM}_OK + } + ++nochange_ns10 () { ++ make_dignm ++ digcmd $* >$DIGNM ++ digcmd $* @$ns10 >${DIGNM}_OK ++ ckresult "$*" ${DIGNM}_OK && clean_result ${DIGNM}_OK ++} ++ + # check against a 'here document' + here () { + make_dignm +@@ -618,6 +627,7 @@ EOF + + # these tests assume "min-ns-dots 0" + start_group "NSDNAME rewrites" test3 ++ nextpart ns3/named.run > /dev/null + nochange a3-1.tld2 # 1 + nochange a3-1.tld2 +dnssec # 2 this once caused problems + nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME +@@ -630,25 +640,39 @@ EOF + addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME + addr 127.0.0.2 a3-1.subsub.sub3.tld2 # 11 + nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash ++ ++ nxdomain a3-1.stub # 13 ++ nxdomain a3-1.static-stub # 14 ++ nochange_ns10 a3-1.stub-nomatch # 15 ++ nochange_ns10 a3-1.static-stub-nomatch # 16 + if [ "$mode" = dnsrps ]; then +- addr 12.12.12.12 as-ns.tld5. # 13 qname-as-ns ++ addr 12.12.12.12 as-ns.tld5. # 17 qname-as-ns + fi ++ nextpart ns3/named.run | grep -q "unrecognized NS rpz_rrset_find() failed: glue" && ++ setret "seen: unrecognized NS rpz_rrset_find() failed: glue" + end_group + if [ "$mode" = dnsrps ]; then +- ckstats $ns3 test3 ns3 8 ++ ckstats $ns3 test3 ns3 10 + else +- ckstats $ns3 test3 ns3 7 ++ ckstats $ns3 test3 ns3 9 + fi + + # these tests assume "min-ns-dots 0" + start_group "NSIP rewrites" test4 ++ nextpart ns3/named.run > /dev/null + nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2 + nochange a3-2.tld2. # 2 exempt rewrite by name + nochange a0-1.tld2. # 3 exempt rewrite by address block + nochange a3-1.tld4 # 4 different NS IP address ++ nxdomain a4-1.stub # 5 ++ nxdomain a4-1.static-stub # 6 ++ nochange_ns10 a4-1.stub-nomatch # 7 ++ nochange_ns10 a4-1.static-stub-nomatch # 8 + if [ "$mode" = dnsrps ]; then +- addr 12.12.12.12 as-ns.tld5. # 5 ip-as-ns ++ addr 12.12.12.12 as-ns.tld5. # 9 ip-as-ns + fi ++ nextpart ns3/named.run | grep -q "unrecognized NS rpz_rrset_find() failed: glue" && ++ setret "seen: unrecognized NS rpz_rrset_find() failed: glue" + end_group + + start_group "walled garden NSIP rewrites" test4a +@@ -660,9 +684,9 @@ EOF + EOF + end_group + if [ "$mode" = dnsrps ]; then +- ckstats $ns3 test4 ns3 5 ++ ckstats $ns3 test4 ns3 7 + else +- ckstats $ns3 test4 ns3 4 ++ ckstats $ns3 test4 ns3 6 + fi + + # policies in ./test5 overridden by response-policy{} in ns3/named.conf +@@ -785,6 +809,7 @@ EOF + fi + + # Ensure ns3 manages to transfer the fast-expire zone before shutdown. ++ nextpartreset ns3/named.run + wait_for_log 20 "zone fast-expire/IN: transferred serial 1" ns3/named.run + + # reconfigure the ns5 primary server without the fast-expire zone, so +-- +2.23.0 + diff --git a/backport-0032-Allow-DNS_RPZ_POLICY_ERROR-to-be-converted-to-a-stri.patch b/backport-0032-Allow-DNS_RPZ_POLICY_ERROR-to-be-converted-to-a-stri.patch new file mode 100644 index 0000000000000000000000000000000000000000..aaa4ad2608da8b08fb430339aaf5415dc1a4bd12 --- /dev/null +++ b/backport-0032-Allow-DNS_RPZ_POLICY_ERROR-to-be-converted-to-a-stri.patch @@ -0,0 +1,29 @@ +From 36612dadff74e57139fe176729fa284b149b420f Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Wed, 4 May 2022 17:03:15 +1000 +Subject: [PATCH] Allow DNS_RPZ_POLICY_ERROR to be converted to a string + +(cherry picked from commit f498d2db0d9f3344d314956253beda73ac29ea4f) +Conflict: adapt INSIST(0), ISC_UNREACHABLE +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/36612dadff74e57139fe176729fa284b149b420f +--- + lib/dns/rpz.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c +index d3baa71..1bdaac9 100644 +--- a/lib/dns/rpz.c ++++ b/lib/dns/rpz.c +@@ -277,6 +277,9 @@ dns_rpz_policy2str(dns_rpz_policy_t policy) { + case DNS_RPZ_POLICY_DNS64: + str = "DNS64"; + break; ++ case DNS_RPZ_POLICY_ERROR: ++ str = "ERROR"; ++ break; + default: + INSIST(0); + ISC_UNREACHABLE(); +-- +2.27.0 + diff --git a/backport-0032-Check-the-cache-as-well-when-glue-NS-are-returned-pr.patch b/backport-0032-Check-the-cache-as-well-when-glue-NS-are-returned-pr.patch new file mode 100644 index 0000000000000000000000000000000000000000..a31d6fc528045b95735856ded1cd4ea689950982 --- /dev/null +++ b/backport-0032-Check-the-cache-as-well-when-glue-NS-are-returned-pr.patch @@ -0,0 +1,86 @@ +From 8f23d56fba79ca063e3deacca973d89b327ccaed Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Wed, 4 May 2022 17:08:27 +1000 +Subject: [PATCH] Check the cache as well when glue NS are returned processing + RPZ + +(cherry picked from commit 8fb72012e36961ff62a29d5f4599b3c41e48e7c9) +Conflict: adapt seg3 and FALLTHROUGH +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/8f23d56fba79ca063e3deacca973d89b327ccaed +--- + lib/ns/query.c | 28 ++++++++++++++++++++++------ + 1 file changed, 22 insertions(+), 6 deletions(-) + +diff --git a/lib/ns/query.c b/lib/ns/query.c +index f4547a5..5ba732f 100644 +--- a/lib/ns/query.c ++++ b/lib/ns/query.c +@@ -3937,6 +3937,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, + dns_rpz_have_t have; + dns_rpz_popt_t popt; + int rpz_ver; ++ unsigned int options; + #ifdef USE_DNSRPS + librpz_emsg_t emsg; + #endif /* ifdef USE_DNSRPS */ +@@ -4187,7 +4188,9 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, + + dns_fixedname_init(&nsnamef); + dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); ++ options = DNS_DBFIND_GLUEOK; + while (st->r.label > st->popt.min_ns_labels) { ++ bool was_glue = false; + /* + * Get NS rrset for each domain in the current qname. + */ +@@ -4202,7 +4205,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, + !dns_rdataset_isassociated(st->r.ns_rdataset)) { + dns_db_t *db = NULL; + result = rpz_rrset_find(client, nsname, +- dns_rdatatype_ns, ++ dns_rdatatype_ns, options, + DNS_RPZ_TYPE_NSDNAME, &db, NULL, + &st->r.ns_rdataset, resuming); + if (db != NULL) { +@@ -4212,8 +4215,10 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, + goto cleanup; + } + switch (result) { +- case ISC_R_SUCCESS: + case DNS_R_GLUE: ++ was_glue = true; ++ /* FALLTHROUGH */ ++ case ISC_R_SUCCESS: + result = dns_rdataset_first(st->r.ns_rdataset); + if (result != ISC_R_SUCCESS) { + goto cleanup; +@@ -4252,6 +4257,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, + continue; + } + } ++ + /* + * Check all NS names. + */ +@@ -4302,7 +4308,17 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, + result = dns_rdataset_next(st->r.ns_rdataset); + } while (result == ISC_R_SUCCESS); + dns_rdataset_disassociate(st->r.ns_rdataset); +- st->r.label--; ++ ++ /* ++ * If we just checked a glue NS RRset retry without allowing ++ * glue responses, otherwise setup for the next name. ++ */ ++ if (was_glue) { ++ options = 0; ++ } else { ++ options = DNS_DBFIND_GLUEOK; ++ st->r.label--; ++ } + + if (rpz_get_zbits(client, dns_rdatatype_any, + DNS_RPZ_TYPE_NSDNAME) == 0 && +-- +2.27.0 + diff --git a/backport-0032-Process-learned-records-as-well-as-glue.patch b/backport-0032-Process-learned-records-as-well-as-glue.patch new file mode 100644 index 0000000000000000000000000000000000000000..d5763f2263eba75e8d68bfb7d94673c61caa6cb1 --- /dev/null +++ b/backport-0032-Process-learned-records-as-well-as-glue.patch @@ -0,0 +1,207 @@ +From 8c2ede6edcc917496eb7d6603c05427cbb9793cc Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Wed, 4 May 2022 15:40:53 +1000 +Subject: [PATCH] Process learned records as well as glue + +(cherry picked from commit 07c828531cb49deeba3e14d7a5ffef7934973562) +Conflict: adapt seg2 and delete rpz_rewrite modify +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/8c2ede6edcc917496eb7d6603c05427cbb9793cc +--- + lib/ns/query.c | 167 ++++++++++++++++++++++++++++--------------------- + 1 file changed, 94 insertions(+), 73 deletions(-) + +diff --git a/lib/ns/query.c b/lib/ns/query.c +index 5ba732f..e6b25bc 100644 +--- a/lib/ns/query.c ++++ b/lib/ns/query.c +@@ -2774,7 +2774,7 @@ query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) { + */ + static isc_result_t + rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, +- dns_rpz_type_t rpz_type, dns_db_t **dbp, ++ unsigned int options, dns_rpz_type_t rpz_type, dns_db_t **dbp, + dns_dbversion_t *version, dns_rdataset_t **rdatasetp, + bool resuming) { + dns_rpz_st_t *st; +@@ -2843,7 +2843,7 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, + found = dns_fixedname_initname(&fixed); + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client, NULL); +- result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK, ++ result = dns_db_findext(*dbp, name, version, type, options, + client->now, &node, found, &cm, &ci, *rdatasetp, + NULL); + if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) { +@@ -3588,82 +3588,104 @@ rpz_rewrite_ip_rrset(ns_client_t *client, dns_name_t *name, + struct in_addr ina; + struct in6_addr in6a; + isc_result_t result; ++ unsigned int options = DNS_DBFIND_GLUEOK; ++ bool done = false; + + CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset"); + +- zbits = rpz_get_zbits(client, ip_type, rpz_type); +- if (zbits == 0) { +- return (ISC_R_SUCCESS); +- } ++ do { ++ zbits = rpz_get_zbits(client, ip_type, rpz_type); ++ if (zbits == 0) { ++ return (ISC_R_SUCCESS); ++ } + +- /* +- * Get the A or AAAA rdataset. +- */ +- result = rpz_rrset_find(client, name, ip_type, rpz_type, ip_dbp, +- ip_version, ip_rdatasetp, resuming); +- switch (result) { +- case ISC_R_SUCCESS: +- case DNS_R_GLUE: +- case DNS_R_ZONECUT: +- break; +- case DNS_R_EMPTYNAME: +- case DNS_R_EMPTYWILD: +- case DNS_R_NXDOMAIN: +- case DNS_R_NCACHENXDOMAIN: +- case DNS_R_NXRRSET: +- case DNS_R_NCACHENXRRSET: +- case ISC_R_NOTFOUND: +- return (ISC_R_SUCCESS); +- case DNS_R_DELEGATION: +- case DNS_R_DUPLICATE: +- case DNS_R_DROP: +- return (result); +- case DNS_R_CNAME: +- case DNS_R_DNAME: +- rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, rpz_type, +- "NS address rewrite rrset", result); +- return (ISC_R_SUCCESS); +- default: +- if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { +- client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR; +- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, ++ /* ++ * Get the A or AAAA rdataset. ++ */ ++ result = rpz_rrset_find(client, name, ip_type, options, ++ rpz_type, ip_dbp, ip_version, ++ ip_rdatasetp, resuming); ++ switch (result) { ++ case ISC_R_SUCCESS: ++ case DNS_R_GLUE: ++ case DNS_R_ZONECUT: ++ break; ++ case DNS_R_EMPTYNAME: ++ case DNS_R_EMPTYWILD: ++ case DNS_R_NXDOMAIN: ++ case DNS_R_NCACHENXDOMAIN: ++ case DNS_R_NXRRSET: ++ case DNS_R_NCACHENXRRSET: ++ case ISC_R_NOTFOUND: ++ return (ISC_R_SUCCESS); ++ case DNS_R_DELEGATION: ++ case DNS_R_DUPLICATE: ++ case DNS_R_DROP: ++ return (result); ++ case DNS_R_CNAME: ++ case DNS_R_DNAME: ++ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, + rpz_type, "NS address rewrite rrset", + result); ++ return (ISC_R_SUCCESS); ++ default: ++ if (client->query.rpz_st->m.policy != ++ DNS_RPZ_POLICY_ERROR) { ++ client->query.rpz_st->m.policy = ++ DNS_RPZ_POLICY_ERROR; ++ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, ++ rpz_type, ++ "NS address rewrite rrset", ++ result); ++ } ++ CTRACE(ISC_LOG_ERROR, ++ "rpz_rewrite_ip_rrset: unexpected " ++ "result"); ++ return (DNS_R_SERVFAIL); + } +- CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip_rrset: unexpected " +- "result"); +- return (DNS_R_SERVFAIL); +- } + +- /* +- * Check all of the IP addresses in the rdataset. +- */ +- for (result = dns_rdataset_first(*ip_rdatasetp); +- result == ISC_R_SUCCESS; result = dns_rdataset_next(*ip_rdatasetp)) +- { +- dns_rdata_t rdata = DNS_RDATA_INIT; +- dns_rdataset_current(*ip_rdatasetp, &rdata); +- switch (rdata.type) { +- case dns_rdatatype_a: +- INSIST(rdata.length == 4); +- memmove(&ina.s_addr, rdata.data, 4); +- isc_netaddr_fromin(&netaddr, &ina); +- break; +- case dns_rdatatype_aaaa: +- INSIST(rdata.length == 16); +- memmove(in6a.s6_addr, rdata.data, 16); +- isc_netaddr_fromin6(&netaddr, &in6a); +- break; +- default: +- continue; ++ /* ++ * If we are processing glue setup for the next loop ++ * otherwise we are done. ++ */ ++ if (result == DNS_R_GLUE) { ++ options = 0; ++ } else { ++ done = true; + } + +- result = rpz_rewrite_ip(client, &netaddr, qtype, rpz_type, +- zbits, p_rdatasetp); +- if (result != ISC_R_SUCCESS) { +- return (result); ++ /* ++ * Check all of the IP addresses in the rdataset. ++ */ ++ for (result = dns_rdataset_first(*ip_rdatasetp); ++ result == ISC_R_SUCCESS; ++ result = dns_rdataset_next(*ip_rdatasetp)) ++ { ++ dns_rdata_t rdata = DNS_RDATA_INIT; ++ dns_rdataset_current(*ip_rdatasetp, &rdata); ++ switch (rdata.type) { ++ case dns_rdatatype_a: ++ INSIST(rdata.length == 4); ++ memmove(&ina.s_addr, rdata.data, 4); ++ isc_netaddr_fromin(&netaddr, &ina); ++ break; ++ case dns_rdatatype_aaaa: ++ INSIST(rdata.length == 16); ++ memmove(in6a.s6_addr, rdata.data, 16); ++ isc_netaddr_fromin6(&netaddr, &in6a); ++ break; ++ default: ++ continue; ++ } ++ ++ result = rpz_rewrite_ip(client, &netaddr, qtype, ++ rpz_type, zbits, p_rdatasetp); ++ if (result != ISC_R_SUCCESS) { ++ return (result); ++ } + } +- } ++ } while (!done && ++ client->query.rpz_st->m.policy == DNS_RPZ_POLICY_MISS); + + return (ISC_R_SUCCESS); + } +-- +2.27.0 + diff --git a/backport-0032-Process-the-delegating-NS-RRset-when-checking-rpz-ru.patch b/backport-0032-Process-the-delegating-NS-RRset-when-checking-rpz-ru.patch new file mode 100644 index 0000000000000000000000000000000000000000..214c7d57f5d1407f6f20d5b89a94d83d58d12a58 --- /dev/null +++ b/backport-0032-Process-the-delegating-NS-RRset-when-checking-rpz-ru.patch @@ -0,0 +1,27 @@ +From 13129872eb0b3c9d63782f42d7f1752e5dabefcf Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Wed, 4 May 2022 14:45:19 +1000 +Subject: [PATCH] Process the delegating NS RRset when checking rpz rules + +(cherry picked from commit cf97c61f48f6cea6d9e67158485106f659433309) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/13129872eb0b3c9d63782f42d7f1752e5dabefcf +--- + lib/ns/query.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/ns/query.c b/lib/ns/query.c +index 771aa7b970..4eb95b808d 100644 +--- a/lib/ns/query.c ++++ b/lib/ns/query.c +@@ -4211,6 +4211,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, + } + switch (result) { + case ISC_R_SUCCESS: ++ case DNS_R_GLUE: + result = dns_rdataset_first(st->r.ns_rdataset); + if (result != ISC_R_SUCCESS) { + goto cleanup; +-- +2.23.0 + diff --git a/backport-0033-Lock-the-trampoline-when-attaching.patch b/backport-0033-Lock-the-trampoline-when-attaching.patch new file mode 100644 index 0000000000000000000000000000000000000000..1204f85c639c5205ea61337e084b56db741711d3 --- /dev/null +++ b/backport-0033-Lock-the-trampoline-when-attaching.patch @@ -0,0 +1,207 @@ +From be7f672fcc20a03d08c1f50b5b7a9f353ccd5dac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 4 May 2022 09:26:34 +0200 +Subject: [PATCH] Lock the trampoline when attaching + +When attaching to the trampoline, the isc__trampoline_max was access +unlocked. This would not manifest under normal circumstances because we +initialize 65 trampolines by default and that's enough for most +commodity hardware, but there are ARM machines with 128+ cores where +this would be reported by ThreadSanitizer. + +Add locking around the code in isc__trampoline_attach(). This also +requires the lock to leak on exit (along with memory that we already) +because a new thread might be attaching to the trampoline while we are +running the library destructor at the same time. + +(cherry picked from commit 933162ae1400ed4d854c32613a7e0a6bbe0b31f7) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/be7f672fcc20a03d08c1f50b5b7a9f353ccd5dac +--- + lib/isc/trampoline.c | 87 ++++++++++++++++++++------------------------ + 1 file changed, 39 insertions(+), 48 deletions(-) + +diff --git a/lib/isc/trampoline.c b/lib/isc/trampoline.c +index e133c40084..965fd0552e 100644 +--- a/lib/isc/trampoline.c ++++ b/lib/isc/trampoline.c +@@ -15,9 +15,9 @@ + + #include + #include ++#include + + #include +-#include + #include + #include + #include +@@ -34,9 +34,26 @@ struct isc__trampoline { + void *jemalloc_enforce_init; + }; + +-static isc_once_t isc__trampoline_initialize_once = ISC_ONCE_INIT; +-static isc_once_t isc__trampoline_shutdown_once = ISC_ONCE_INIT; +-static isc_mutex_t isc__trampoline_lock; ++/* ++ * We can't use isc_mem API here, because it's called too ++ * early and when the isc_mem_debugging flags are changed ++ * later and ISC_MEM_DEBUGSIZE or ISC_MEM_DEBUGCTX flags are ++ * added, neither isc_mem_put() nor isc_mem_free() can be used ++ * to free up the memory allocated here because the flags were ++ * not set when calling isc_mem_get() or isc_mem_allocate() ++ * here. ++ * ++ * Since this is a single allocation at library load and deallocation at library ++ * unload, using the standard allocator without the tracking is fine for this ++ * single purpose. ++ * ++ * We can't use isc_mutex API either, because we track whether the mutexes get ++ * properly destroyed, and we intentionally leak the static mutex here without ++ * destroying it to prevent data race between library destructor running while ++ * thread is being still created. ++ */ ++ ++static uv_mutex_t isc__trampoline_lock; + static isc__trampoline_t **trampolines; + #if defined(HAVE_THREAD_LOCAL) + #include +@@ -49,19 +66,6 @@ __declspec(thread) size_t isc_tid_v = SIZE_MAX; + static size_t isc__trampoline_min = 1; + static size_t isc__trampoline_max = 65; + +-/* +- * We can't use isc_mem API here, because it's called too +- * early and when the isc_mem_debugging flags are changed +- * later and ISC_MEM_DEBUGSIZE or ISC_MEM_DEBUGCTX flags are +- * added, neither isc_mem_put() nor isc_mem_free() can be used +- * to free up the memory allocated here because the flags were +- * not set when calling isc_mem_get() or isc_mem_allocate() +- * here. +- * +- * Actually, since this is a single allocation at library load +- * and deallocation at library unload, using the standard +- * allocator without the tracking is fine for this purpose. +- */ + static isc__trampoline_t * + isc__trampoline_new(int tid, isc_threadfunc_t start, isc_threadarg_t arg) { + isc__trampoline_t *trampoline = calloc(1, sizeof(*trampoline)); +@@ -77,17 +81,17 @@ isc__trampoline_new(int tid, isc_threadfunc_t start, isc_threadarg_t arg) { + return (trampoline); + } + +-static void +-trampoline_initialize(void) { +- isc_mutex_init(&isc__trampoline_lock); ++void ++isc__trampoline_initialize(void) { ++ uv_mutex_init(&isc__trampoline_lock); + + trampolines = calloc(isc__trampoline_max, sizeof(trampolines[0])); + RUNTIME_CHECK(trampolines != NULL); + + /* Get the trampoline slot 0 for the main thread */ + trampolines[0] = isc__trampoline_new(0, NULL, NULL); +- trampolines[0]->self = isc_thread_self(); + isc_tid_v = trampolines[0]->tid; ++ trampolines[0]->self = isc_thread_self(); + + /* Initialize the other trampolines */ + for (size_t i = 1; i < isc__trampoline_max; i++) { +@@ -97,38 +101,22 @@ trampoline_initialize(void) { + } + + void +-isc__trampoline_initialize(void) { +- isc_result_t result = isc_once_do(&isc__trampoline_initialize_once, +- trampoline_initialize); +- RUNTIME_CHECK(result == ISC_R_SUCCESS); +-} +- +-static void +-trampoline_shutdown(void) { ++isc__trampoline_shutdown(void) { + /* + * When the program using the library exits abruptly and the library + * gets unloaded, there might be some existing trampolines from unjoined + * threads. We intentionally ignore those and don't check whether all +- * trampolines have been cleared before exiting. ++ * trampolines have been cleared before exiting, so we leak a little bit ++ * of resources here, including the lock. + */ + free(trampolines[0]); +- free(trampolines); +- trampolines = NULL; +- isc_mutex_destroy(&isc__trampoline_lock); +-} +- +-void +-isc__trampoline_shutdown(void) { +- isc_result_t result = isc_once_do(&isc__trampoline_shutdown_once, +- trampoline_shutdown); +- RUNTIME_CHECK(result == ISC_R_SUCCESS); + } + + isc__trampoline_t * + isc__trampoline_get(isc_threadfunc_t start, isc_threadarg_t arg) { + isc__trampoline_t **tmp = NULL; + isc__trampoline_t *trampoline = NULL; +- LOCK(&isc__trampoline_lock); ++ uv_mutex_lock(&isc__trampoline_lock); + again: + for (size_t i = isc__trampoline_min; i < isc__trampoline_max; i++) { + if (trampolines[i] == NULL) { +@@ -152,17 +140,17 @@ again: + goto again; + done: + INSIST(trampoline != NULL); +- UNLOCK(&isc__trampoline_lock); ++ uv_mutex_unlock(&isc__trampoline_lock); + + return (trampoline); + } + + void + isc__trampoline_detach(isc__trampoline_t *trampoline) { +- LOCK(&isc__trampoline_lock); +- REQUIRE(trampoline->tid > 0 && +- (size_t)trampoline->tid < isc__trampoline_max); ++ uv_mutex_lock(&isc__trampoline_lock); + REQUIRE(trampoline->self == isc_thread_self()); ++ REQUIRE(trampoline->tid > 0); ++ REQUIRE((size_t)trampoline->tid < isc__trampoline_max); + REQUIRE(trampolines[trampoline->tid] == trampoline); + + trampolines[trampoline->tid] = NULL; +@@ -174,15 +162,17 @@ isc__trampoline_detach(isc__trampoline_t *trampoline) { + free(trampoline->jemalloc_enforce_init); + free(trampoline); + +- UNLOCK(&isc__trampoline_lock); ++ uv_mutex_unlock(&isc__trampoline_lock); + return; + } + + void + isc__trampoline_attach(isc__trampoline_t *trampoline) { +- REQUIRE(trampoline->tid > 0 && +- (size_t)trampoline->tid < isc__trampoline_max); ++ uv_mutex_lock(&isc__trampoline_lock); + REQUIRE(trampoline->self == ISC__TRAMPOLINE_UNUSED); ++ REQUIRE(trampoline->tid > 0); ++ REQUIRE((size_t)trampoline->tid < isc__trampoline_max); ++ REQUIRE(trampolines[trampoline->tid] == trampoline); + + /* Initialize the trampoline */ + isc_tid_v = trampoline->tid; +@@ -196,6 +186,7 @@ isc__trampoline_attach(isc__trampoline_t *trampoline) { + * malloc() + free() calls altogether, as it would foil the fix. + */ + trampoline->jemalloc_enforce_init = malloc(8); ++ uv_mutex_unlock(&isc__trampoline_lock); + } + + isc_threadresult_t +-- +2.23.0 + diff --git a/backport-0034-prevent-a-possible-buffer-overflow-in-configuration-.patch b/backport-0034-prevent-a-possible-buffer-overflow-in-configuration-.patch new file mode 100644 index 0000000000000000000000000000000000000000..28f9e9b104073a12a1042d35002280163dd8d497 --- /dev/null +++ b/backport-0034-prevent-a-possible-buffer-overflow-in-configuration-.patch @@ -0,0 +1,42 @@ +From b6670787d25743ddf39dfe8e615828efc928f50d Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Fri, 13 May 2022 19:59:58 -0700 +Subject: [PATCH] prevent a possible buffer overflow in configuration check + +corrected code that could have allowed a buffer overfow while +parsing named.conf. + +(cherry picked from commit 921043b54161c7a3e6dc4036b038ca4dbc5fe472) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/b6670787d25743ddf39dfe8e615828efc928f50d +--- + lib/bind9/check.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/bind9/check.c b/lib/bind9/check.c +index d446df3cd3..0be4871020 100644 +--- a/lib/bind9/check.c ++++ b/lib/bind9/check.c +@@ -2500,8 +2500,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, + } else if (dns_name_isula(zname)) { + ula = true; + } +- tmp += strlen(tmp); + len -= strlen(tmp); ++ tmp += strlen(tmp); + (void)snprintf(tmp, len, "%u/%s", zclass, + (ztype == CFG_ZONE_INVIEW) ? target + : (viewname != NULL) ? viewname +@@ -3247,8 +3247,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, + char *tmp = keydirbuf; + size_t len = sizeof(keydirbuf); + dns_name_format(zname, keydirbuf, sizeof(keydirbuf)); +- tmp += strlen(tmp); + len -= strlen(tmp); ++ tmp += strlen(tmp); + (void)snprintf(tmp, len, "/%s", (dir == NULL) ? "(null)" : dir); + tresult = keydirexist(zconfig, (const char *)keydirbuf, + kaspname, keydirs, logctx, mctx); +-- +2.23.0 + diff --git a/backport-0035-Add-lower-bound-checks-to-fetchlimit-test.patch b/backport-0035-Add-lower-bound-checks-to-fetchlimit-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..345a28355a190a4b9ef8da2253ad3b8d9ed61eb6 --- /dev/null +++ b/backport-0035-Add-lower-bound-checks-to-fetchlimit-test.patch @@ -0,0 +1,160 @@ +From 6edbe8452cc4a5eb0e5cd6aa92039bb17d8fc9ef Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Sun, 8 May 2022 17:17:29 -0700 +Subject: [PATCH] Add lower bound checks to fetchlimit test + +Check that the recursing client count is above a reasonable +minimum, as well as below a maximum, so that we can detect +bugs that cause recursion to fail too early or too often. + +(cherry picked from commit 8834c44683f76b3e9fff795eb3d9ec52bc063b6a) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/6edbe8452cc4a5eb0e5cd6aa92039bb17d8fc9ef +--- + bin/tests/system/fetchlimit/tests.sh | 41 +++++++++++++++------------- + 1 file changed, 22 insertions(+), 19 deletions(-) + +diff --git a/bin/tests/system/fetchlimit/tests.sh b/bin/tests/system/fetchlimit/tests.sh +index e7df552af0..55f4bf6a48 100644 +--- a/bin/tests/system/fetchlimit/tests.sh ++++ b/bin/tests/system/fetchlimit/tests.sh +@@ -21,7 +21,7 @@ burst() { + num=${3:-20} + rm -f burst.input.$$ + while [ $num -gt 0 ]; do +- num=`expr $num - 1` ++ num=$((num-1)) + echo "${num}${1}${2}.lamesub.example A" >> burst.input.$$ + done + $PERL ../ditch.pl -p ${PORT} -s 10.53.0.3 burst.input.$$ +@@ -33,7 +33,9 @@ stat() { + sed 's;.*: \([^/][^/]*\)/.*;\1;'` + echo_i "clients: $clients" + [ "$clients" = "" ] && return 1 +- [ "$clients" -le $1 ] ++ [ "$clients" -ge $1 ] || return 1 ++ [ "$clients" -le $2 ] || return 1 ++ return 0 + } + + status=0 +@@ -47,13 +49,14 @@ for try in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + burst a $try + # fetches-per-server is at 400, but at 20qps against a lame server, + # we'll reach 200 at the tenth second, and the quota should have been +- # tuned to less than that by then +- stat 200 || ret=1 ++ # tuned to less than that by then. ++ [ $try -le 5 ] && low=$((try*10)) ++ stat 20 200 || ret=1 + [ $ret -eq 1 ] && break + sleep 1 + done + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "dumping ADB data" + $RNDCCMD dumpdb -adb +@@ -77,14 +80,14 @@ fails=`grep 'queries resulted in SERVFAIL' ns3/named.stats | sed 's/\([0-9][0-9] + [ -z "$fails" ] && fails=0 + [ "$fails" -ge "$sspill" ] || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking lame server recovery" + ret=0 + rm -f ans4/norespond + for try in 1 2 3 4 5; do + burst b $try +- stat 200 || ret=1 ++ stat 0 200 || ret=1 + [ $ret -eq 1 ] && break + sleep 1 + done +@@ -99,7 +102,7 @@ quota=$5 + + for try in 1 2 3 4 5 6 7 8 9 10; do + burst c $try +- stat 20 || ret=1 ++ stat 0 20 || ret=1 + [ $ret -eq 1 ] && break + sleep 1 + done +@@ -112,7 +115,7 @@ set -- $info + [ ${5:-${quota}} -gt $quota ] || ret=1 + quota=$5 + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + copy_setports ns3/named2.conf.in ns3/named.conf + rndc_reconfig ns3 10.53.0.3 +@@ -126,17 +129,17 @@ for try in 1 2 3 4 5; do + burst b $try 300 + $DIGCMD a ${try}.example > dig.out.ns3.$try + grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \ +- success=`expr $success + 1` ++ success=$((success+1)) + grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \ +- fail=`expr $fail + 1` +- stat 50 || ret=1 ++ fail=$(($fail+1)) ++ stat 30 50 || ret=1 + [ $ret -eq 1 ] && break + $RNDCCMD recursing 2>&1 | sed 's/^/ns3 /' | cat_i + sleep 1 + done + echo_i "$success successful valid queries, $fail SERVFAIL" + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking drop statistics" + rm -f ns3/named.stats +@@ -151,7 +154,7 @@ drops=`grep 'queries dropped' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.* + [ -z "$drops" ] && drops=0 + [ "$drops" -ge "$zspill" ] || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + copy_setports ns3/named3.conf.in ns3/named.conf + rndc_reconfig ns3 10.53.0.3 +@@ -165,11 +168,11 @@ touch ans4/norespond + for try in 1 2 3 4 5; do + burst b $try 400 + $DIGCMD +time=2 a ${try}.example > dig.out.ns3.$try +- stat 400 || exceeded=`expr $exceeded + 1` ++ stat 100 400 || exceeded=$((exceeded + 1)) + grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \ +- success=`expr $success + 1` ++ success=$((success+1)) + grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \ +- fail=`expr $fail + 1` ++ fail=$(($fail+1)) + sleep 1 + done + echo_i "$success successful valid queries (expected 5)" +@@ -179,7 +182,7 @@ echo_i "$fail SERVFAIL responses (expected 0)" + echo_i "clients count exceeded 400 on $exceeded trials (expected 0)" + [ "$exceeded" -eq 0 ] || { echo_i "failed"; ret=1; } + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "checking drop statistics" + rm -f ns3/named.stats +@@ -191,7 +194,7 @@ done + drops=`grep 'queries dropped due to recursive client limit' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/'` + [ "${drops:-0}" -ne 0 ] || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++status=$((status+ret)) + + echo_i "exit status: $status" + [ $status -eq 0 ] || exit 1 +-- +2.23.0 + diff --git a/backport-0035-Disable-EDNS-for-the-fetchlimit-test-server.patch b/backport-0035-Disable-EDNS-for-the-fetchlimit-test-server.patch new file mode 100644 index 0000000000000000000000000000000000000000..896f001272e19f2a63d5fed15a286c7b9cdd74be --- /dev/null +++ b/backport-0035-Disable-EDNS-for-the-fetchlimit-test-server.patch @@ -0,0 +1,71 @@ +From 9582d05683742c4920c7125e8364a3345e6035b8 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Thu, 5 May 2022 14:52:15 -0700 +Subject: [PATCH] Disable EDNS for the fetchlimit test server + +The fetchlimit test depends on a resolver continuing to try UDP +and timing out while the client waits for resolution to succeed. +but since commit bb990030 (flag day 2020), a fetch will always +switch to TCP after two timeouts, unless EDNS was disabled for +the query. + +This commit adds "edns no;" to server statements in the fetchlimit +resolver, to restore the behavior expected by the test. + +(cherry picked from commit 81deb24deb26095cbf3eaec8e7763973ec4177c3) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/9582d05683742c4920c7125e8364a3345e6035b8 +--- + bin/tests/system/fetchlimit/ns3/named1.conf.in | 4 ++++ + bin/tests/system/fetchlimit/ns3/named2.conf.in | 4 ++++ + bin/tests/system/fetchlimit/ns3/named3.conf.in | 4 ++++ + 3 files changed, 12 insertions(+) + +diff --git a/bin/tests/system/fetchlimit/ns3/named1.conf.in b/bin/tests/system/fetchlimit/ns3/named1.conf.in +index ab7c25a0af..3adfe473eb 100644 +--- a/bin/tests/system/fetchlimit/ns3/named1.conf.in ++++ b/bin/tests/system/fetchlimit/ns3/named1.conf.in +@@ -28,6 +28,10 @@ options { + fetches-per-server 400; + }; + ++server 10.53.0.4 { ++ edns no; ++}; ++ + key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +diff --git a/bin/tests/system/fetchlimit/ns3/named2.conf.in b/bin/tests/system/fetchlimit/ns3/named2.conf.in +index 27c5f33e3b..74374b106f 100644 +--- a/bin/tests/system/fetchlimit/ns3/named2.conf.in ++++ b/bin/tests/system/fetchlimit/ns3/named2.conf.in +@@ -26,6 +26,10 @@ options { + fetches-per-zone 40; + }; + ++server 10.53.0.4 { ++ edns no; ++}; ++ + key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +diff --git a/bin/tests/system/fetchlimit/ns3/named3.conf.in b/bin/tests/system/fetchlimit/ns3/named3.conf.in +index a5d1c165fb..3df353b07d 100644 +--- a/bin/tests/system/fetchlimit/ns3/named3.conf.in ++++ b/bin/tests/system/fetchlimit/ns3/named3.conf.in +@@ -26,6 +26,10 @@ options { + recursive-clients 400; + }; + ++server 10.53.0.4 { ++ edns no; ++}; ++ + key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +-- +2.23.0 + diff --git a/backport-0035-Fix-the-fetches-per-server-quota-calculation.patch b/backport-0035-Fix-the-fetches-per-server-quota-calculation.patch new file mode 100644 index 0000000000000000000000000000000000000000..191b084522269ddde2b848e541450dcbd32f96d5 --- /dev/null +++ b/backport-0035-Fix-the-fetches-per-server-quota-calculation.patch @@ -0,0 +1,44 @@ +From 8516efa4fda80d99b0376db6681fb6f31326061e Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Wed, 4 May 2022 17:27:56 -0700 +Subject: [PATCH] Fix the fetches-per-server quota calculation + +Since commit bad5a523c2e, when the fetches-per-server quota +was increased or decreased, instead of the value being set to +the newly calculated quota, it was set to the *minimum* of +the new quota or 1 - which effectively meant it was always set to 1. +it should instead have been the maximum, to prevent the value from +ever dropping to zero. + +(cherry picked from commit 694bc50273ddc01c571dd917415d24b42ca39de8) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/8516efa4fda80d99b0376db6681fb6f31326061e +--- + lib/dns/adb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/dns/adb.c b/lib/dns/adb.c +index d5ef99bb61..f86e5125e5 100644 +--- a/lib/dns/adb.c ++++ b/lib/dns/adb.c +@@ -4324,7 +4324,7 @@ maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr, bool timeout) { + uint_fast32_t new_quota = + adb->quota * quota_adj[--addr->entry->mode] / 10000; + atomic_store_release(&addr->entry->quota, +- ISC_MIN(1, new_quota)); ++ ISC_MAX(1, new_quota)); + log_quota(addr->entry, + "atr %0.2f, quota increased to %" PRIuFAST32, + addr->entry->atr, new_quota); +@@ -4334,7 +4334,7 @@ maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr, bool timeout) { + uint_fast32_t new_quota = + adb->quota * quota_adj[++addr->entry->mode] / 10000; + atomic_store_release(&addr->entry->quota, +- ISC_MIN(1, new_quota)); ++ ISC_MAX(1, new_quota)); + log_quota(addr->entry, + "atr %0.2f, quota decreased to %" PRIuFAST32, + addr->entry->atr, new_quota); +-- +2.23.0 + diff --git a/backport-0036-Add-kasp-test-for-3302.patch b/backport-0036-Add-kasp-test-for-3302.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea5903bc668aa7fa7f4bcdd9d830aac7589709ab --- /dev/null +++ b/backport-0036-Add-kasp-test-for-3302.patch @@ -0,0 +1,113 @@ +From 6226ab2fa910f01d75fd5b5c91c6452e38d1e7d0 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Tue, 3 May 2022 12:24:58 +0200 +Subject: [PATCH] Add kasp test for #3302 + +Add a test case that triggers a keymgr run that will not trigger any +metadata changes. Ensure that the last status change of the key files +is unmodified. + +(cherry picked from commit 7249bad706ab7e15660f4317dbfb76c65bd059cd) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/6226ab2fa910f01d75fd5b5c91c6452e38d1e7d0 +--- + bin/tests/system/kasp.sh | 12 ++++++++++- + bin/tests/system/kasp/tests.sh | 38 ++++++++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+), 1 deletion(-) + +diff --git a/bin/tests/system/kasp.sh b/bin/tests/system/kasp.sh +index 01bcce3fd0..f41911a68e 100644 +--- a/bin/tests/system/kasp.sh ++++ b/bin/tests/system/kasp.sh +@@ -64,6 +64,9 @@ VIEW3="C1Azf+gGPMmxrUg/WQINP6eV9Y0=" + # EXPECT_KRRSIG + # LEGACY + # PRIVATE ++# PRIVKEY_STAT ++# PUBKEY_STAT ++# STATE_STAT + + key_key() { + echo "${1}__${2}" +@@ -86,6 +89,10 @@ key_save() + key_set "$1" BASEFILE "$BASE_FILE" + # Save creation date. + key_set "$1" CREATED "${KEY_CREATED}" ++ # Save key change time. ++ key_set "$1" PRIVKEY_STAT $(stat -c '%Z' "${BASE_FILE}.private") ++ key_set "$1" PUBKEY_STAT $(stat -c '%Z' "${BASE_FILE}.key") ++ key_set "$1" STATE_STAT $(stat -c '%Z' "${BASE_FILE}.state") + } + + # Clear key state. +@@ -98,6 +105,7 @@ key_clear() { + key_set "$1" "ROLE" 'none' + key_set "$1" "KSK" 'no' + key_set "$1" "ZSK" 'no' ++ key_set "$1" "FLAGS" '0' + key_set "$1" "LIFETIME" 'none' + key_set "$1" "ALG_NUM" '0' + key_set "$1" "ALG_STR" 'none' +@@ -118,7 +126,9 @@ key_clear() { + key_set "$1" "EXPECT_KRRSIG" 'no' + key_set "$1" "LEGACY" 'no' + key_set "$1" "PRIVATE" 'yes' +- key_set "$1" "FLAGS" '0' ++ key_set "$1" "PRIVKEY_STAT" '0' ++ key_set "$1" "PUBKEY_STAT" '0' ++ key_set "$1" "STATE_STAT" '0' + } + + # Start clear. +diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh +index f4b3714a54..eccf33a2d3 100644 +--- a/bin/tests/system/kasp/tests.sh ++++ b/bin/tests/system/kasp/tests.sh +@@ -294,6 +294,44 @@ check_apex + check_subdomain + dnssec_verify + ++# Trigger a keymgr run. Make sure the key files are not touched if there are ++# no modifications to the key metadata. ++n=$((n+1)) ++echo_i "make sure key files are untouched if metadata does not change ($n)" ++ret=0 ++basefile=$(key_get KEY1 BASEFILE) ++privkey_stat=$(key_get KEY1 PRIVKEY_STAT) ++pubkey_stat=$(key_get KEY1 PUBKEY_STAT) ++state_stat=$(key_get KEY1 STATE_STAT) ++ ++nextpart $DIR/named.run > /dev/null ++rndccmd 10.53.0.3 loadkeys "$ZONE" > /dev/null || log_error "rndc loadkeys zone ${ZONE} failed" ++wait_for_log 3 "keymgr: $ZONE done" $DIR/named.run ++privkey_stat2=$(stat -c '%Z' "${basefile}.private") ++pubkey_stat2=$(stat -c '%Z' "${basefile}.key") ++state_stat2=$(stat -c '%Z' "${basefile}.state") ++test "$privkey_stat" = "$privkey_stat2" || log_error "wrong private key file stat (expected $privkey_stat got $privkey_stat2)" ++test "$pubkey_stat" = "$pubkey_stat2" || log_error "wrong public key file stat (expected $pubkey_stat got $pubkey_stat2)" ++test "$state_stat" = "$state_stat2" || log_error "wrong state file stat (expected $state_stat got $state_stat2)" ++test "$ret" -eq 0 || echo_i "failed" ++status=$((status+ret)) ++ ++n=$((n+1)) ++echo_i "again ($n)" ++ret=0 ++ ++nextpart $DIR/named.run > /dev/null ++rndccmd 10.53.0.3 loadkeys "$ZONE" > /dev/null || log_error "rndc loadkeys zone ${ZONE} failed" ++wait_for_log 3 "keymgr: done" $DIR/named.run ++privkey_stat2=$(stat -c '%Z' "${basefile}.private") ++pubkey_stat2=$(stat -c '%Z' "${basefile}.key") ++state_stat2=$(stat -c '%Z' "${basefile}.state") ++test "$privkey_stat" = "$privkey_stat2" || log_error "wrong private key file stat (expected $privkey_stat got $privkey_stat2)" ++test "$pubkey_stat" = "$pubkey_stat2" || log_error "wrong public key file stat (expected $pubkey_stat got $pubkey_stat2)" ++test "$state_stat" = "$state_stat2" || log_error "wrong state file stat (expected $state_stat got $state_stat2)" ++test "$ret" -eq 0 || echo_i "failed" ++status=$((status+ret)) ++ + # Update zone. + n=$((n+1)) + echo_i "modify unsigned zone file and check that new record is signed for zone ${ZONE} ($n)" +-- +2.23.0 + diff --git a/backport-0036-Check-if-key-metadata-is-modified-before-writing.patch b/backport-0036-Check-if-key-metadata-is-modified-before-writing.patch new file mode 100644 index 0000000000000000000000000000000000000000..f11e7ee965889b3e1b7adce2aef5e5ed7973bb05 --- /dev/null +++ b/backport-0036-Check-if-key-metadata-is-modified-before-writing.patch @@ -0,0 +1,235 @@ +From c2e8c722980cd40e163f748e8502c9637ea55cf3 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Tue, 3 May 2022 12:28:31 +0200 +Subject: [PATCH] Check if key metadata is modified before writing + +Add a new parameter to the dst_key structure, mark a key modified if +dst_key_(un)set[bool,num,state,time] is called. Only write out key +files during a keymgr run if the metadata has changed. + +(cherry picked from commit 1da91b3ab46b3d875213a473595e671d9ff9c76f) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/c2e8c722980cd40e163f748e8502c9637ea55cf3 +--- + lib/dns/dst_api.c | 26 ++++++++++++++++++++++++++ + lib/dns/dst_internal.h | 1 + + lib/dns/include/dst/dst.h | 20 ++++++++++++++++++++ + lib/dns/keymgr.c | 17 ++++++++++++++++- + 4 files changed, 63 insertions(+), 1 deletion(-) + +diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c +index ab371330f0..8873a041b8 100644 +--- a/lib/dns/dst_api.c ++++ b/lib/dns/dst_api.c +@@ -490,6 +490,16 @@ dst_key_isexternal(dst_key_t *key) { + return (key->external); + } + ++void ++dst_key_setmodified(dst_key_t *key, bool value) { ++ key->modified = value; ++} ++ ++bool ++dst_key_ismodified(dst_key_t *key) { ++ return (key->modified); ++} ++ + isc_result_t + dst_key_getfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg, + int type, const char *directory, isc_mem_t *mctx, +@@ -637,6 +647,7 @@ dst_key_fromnamedfile(const char *filename, const char *dirname, int type, + (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) + { + RETERR(computeid(pubkey)); ++ pubkey->modified = false; + *keyp = pubkey; + pubkey = NULL; + goto out; +@@ -690,6 +701,7 @@ dst_key_fromnamedfile(const char *filename, const char *dirname, int type, + RETERR(DST_R_INVALIDPRIVATEKEY); + } + ++ key->modified = false; + *keyp = key; + key = NULL; + +@@ -1047,6 +1059,8 @@ dst_key_setbool(dst_key_t *key, int type, bool value) { + REQUIRE(type <= DST_MAX_BOOLEAN); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || !key->boolset[type] || ++ key->bools[type] != value; + key->bools[type] = value; + key->boolset[type] = true; + isc_mutex_unlock(&key->mdlock); +@@ -1058,6 +1072,7 @@ dst_key_unsetbool(dst_key_t *key, int type) { + REQUIRE(type <= DST_MAX_BOOLEAN); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || key->boolset[type]; + key->boolset[type] = false; + isc_mutex_unlock(&key->mdlock); + } +@@ -1089,6 +1104,8 @@ dst_key_setnum(dst_key_t *key, int type, uint32_t value) { + REQUIRE(type <= DST_MAX_NUMERIC); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || !key->numset[type] || ++ key->nums[type] != value; + key->nums[type] = value; + key->numset[type] = true; + isc_mutex_unlock(&key->mdlock); +@@ -1100,6 +1117,7 @@ dst_key_unsetnum(dst_key_t *key, int type) { + REQUIRE(type <= DST_MAX_NUMERIC); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || key->numset[type]; + key->numset[type] = false; + isc_mutex_unlock(&key->mdlock); + } +@@ -1130,6 +1148,8 @@ dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) { + REQUIRE(type <= DST_MAX_TIMES); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || !key->timeset[type] || ++ key->times[type] != when; + key->times[type] = when; + key->timeset[type] = true; + isc_mutex_unlock(&key->mdlock); +@@ -1141,6 +1161,7 @@ dst_key_unsettime(dst_key_t *key, int type) { + REQUIRE(type <= DST_MAX_TIMES); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || key->timeset[type]; + key->timeset[type] = false; + isc_mutex_unlock(&key->mdlock); + } +@@ -1172,6 +1193,8 @@ dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state) { + REQUIRE(type <= DST_MAX_KEYSTATES); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || !key->keystateset[type] || ++ key->keystates[type] != state; + key->keystates[type] = state; + key->keystateset[type] = true; + isc_mutex_unlock(&key->mdlock); +@@ -1183,6 +1206,7 @@ dst_key_unsetstate(dst_key_t *key, int type) { + REQUIRE(type <= DST_MAX_KEYSTATES); + + isc_mutex_lock(&key->mdlock); ++ key->modified = key->modified || key->keystateset[type]; + key->keystateset[type] = false; + isc_mutex_unlock(&key->mdlock); + } +@@ -2747,4 +2771,6 @@ dst_key_copy_metadata(dst_key_t *to, dst_key_t *from) { + dst_key_unsetstate(to, i); + } + } ++ ++ dst_key_setmodified(to, dst_key_ismodified(from)); + } +diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h +index e26837bfe4..4933cfd5aa 100644 +--- a/lib/dns/dst_internal.h ++++ b/lib/dns/dst_internal.h +@@ -147,6 +147,7 @@ struct dst_key { + bool inactive; /*%< private key not present as it is + * inactive */ + bool external; /*%< external key */ ++ bool modified; /*%< set to true if key file metadata has changed */ + + int fmt_major; /*%< private key format, major version + * */ +diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h +index d50761a63c..eab5501029 100644 +--- a/lib/dns/include/dst/dst.h ++++ b/lib/dns/include/dst/dst.h +@@ -1107,6 +1107,26 @@ dst_key_isexternal(dst_key_t *key); + * 'key' to be valid. + */ + ++void ++dst_key_setmodified(dst_key_t *key, bool value); ++/*%< ++ * If 'value' is true, this marks the key to indicate that key file metadata ++ * has been modified. If 'value' is false, this resets the value, for example ++ * after you have written the key to file. ++ * ++ * Requires: ++ * 'key' to be valid. ++ */ ++ ++bool ++dst_key_ismodified(dst_key_t *key); ++/*%< ++ * Check if the key file has been modified. ++ * ++ * Requires: ++ * 'key' to be valid. ++ */ ++ + bool + dst_key_haskasp(dst_key_t *key); + /*%< +diff --git a/lib/dns/keymgr.c b/lib/dns/keymgr.c +index 965782b1f3..b01286575f 100644 +--- a/lib/dns/keymgr.c ++++ b/lib/dns/keymgr.c +@@ -1512,6 +1512,7 @@ transition: + /* It is safe to make the transition. */ + dst_key_setstate(dkey->key, i, next_state); + dst_key_settime(dkey->key, keystatetimes[i], now); ++ INSIST(dst_key_ismodified(dkey->key)); + changed = true; + } + } +@@ -2183,9 +2184,10 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, + for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; + dkey = ISC_LIST_NEXT(dkey, link)) + { +- if (!dkey->purge) { ++ if (dst_key_ismodified(dkey->key) && !dkey->purge) { + dns_dnssec_get_hints(dkey, now); + RETERR(dst_key_tofile(dkey->key, options, directory)); ++ dst_key_setmodified(dkey->key, false); + } + } + +@@ -2205,6 +2207,13 @@ failure: + } + } + ++ if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) { ++ char namebuf[DNS_NAME_FORMATSIZE]; ++ dns_name_format(origin, namebuf, sizeof(namebuf)); ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, ++ DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3), ++ "keymgr: %s done", namebuf); ++ } + return (result); + } + +@@ -2282,6 +2291,9 @@ keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring, + + dns_dnssec_get_hints(ksk_key, now); + result = dst_key_tofile(ksk_key->key, options, directory); ++ if (result == ISC_R_SUCCESS) { ++ dst_key_setmodified(ksk_key->key, false); ++ } + isc_dir_close(&dir); + + return (result); +@@ -2582,6 +2594,9 @@ dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring, + + dns_dnssec_get_hints(key, now); + result = dst_key_tofile(key->key, options, directory); ++ if (result == ISC_R_SUCCESS) { ++ dst_key_setmodified(key->key, false); ++ } + isc_dir_close(&dir); + + return (result); +-- +2.27.0 + diff --git a/backport-0037-Don-t-process-DNSSEC-related-and-ZONEMD-records-in-c.patch b/backport-0037-Don-t-process-DNSSEC-related-and-ZONEMD-records-in-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..27cb106a15358afacd43530d61b3cf500e84c83b --- /dev/null +++ b/backport-0037-Don-t-process-DNSSEC-related-and-ZONEMD-records-in-c.patch @@ -0,0 +1,63 @@ +From 1dc7288708a2c1027405d5c2b376809a335cf252 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Wed, 1 Jun 2022 08:51:55 +0000 +Subject: [PATCH] Don't process DNSSEC-related and ZONEMD records in catz + +When processing a catalog zone update, skip processing records with +DNSSEC-related and ZONEMD types, because we are not interested in them +in the context of a catalog zone, and processing them will fail and +produce an unnecessary warning message. + +(cherry picked from commit 73d664313703d2874c3b1a4380afdcd8ba26dc62) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/1dc7288708a2c1027405d5c2b376809a335cf252 +--- + lib/dns/catz.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/lib/dns/catz.c b/lib/dns/catz.c +index 53fbb1c2a7..a749ffa9d4 100644 +--- a/lib/dns/catz.c ++++ b/lib/dns/catz.c +@@ -1799,6 +1799,12 @@ cleanup: + return (result); + } + ++static bool ++catz_rdatatype_is_processable(const dns_rdatatype_t type) { ++ return (!dns_rdatatype_isdnssec(type) && type != dns_rdatatype_cds && ++ type != dns_rdatatype_cdnskey && type != dns_rdatatype_zonemd); ++} ++ + void + dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { + dns_catz_zone_t *oldzone = NULL, *newzone = NULL; +@@ -1908,6 +1914,17 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { + result = dns_rdatasetiter_first(rdsiter); + while (result == ISC_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, &rdataset); ++ ++ /* ++ * Skip processing DNSSEC-related and ZONEMD types, ++ * because we are not interested in them in the context ++ * of a catalog zone, and processing them will fail ++ * and produce an unnecessary warning message. ++ */ ++ if (!catz_rdatatype_is_processable(rdataset.type)) { ++ goto next; ++ } ++ + result = dns_catz_update_process(catzs, newzone, name, + &rdataset); + if (result != ISC_R_SUCCESS) { +@@ -1930,6 +1947,7 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { + cname, classbuf, typebuf, + isc_result_totext(result)); + } ++ next: + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) { + break; +-- +2.23.0 + diff --git a/backport-0037-Fix-CID-352776-Concurrent-data-access-violations.patch b/backport-0037-Fix-CID-352776-Concurrent-data-access-violations.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc17cb69e4a0d021e80e4048f24678811a5e2602 --- /dev/null +++ b/backport-0037-Fix-CID-352776-Concurrent-data-access-violations.patch @@ -0,0 +1,76 @@ +From 7c42c04f3fa1c6b936debe48b435b9ef9da464bd Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Mon, 16 May 2022 19:00:47 +0200 +Subject: [PATCH] Fix CID 352776: Concurrent data access violations + +*** CID 352776: Concurrent data access violations (MISSING_LOCK) +/lib/dns/dst_api.c: 474 in dst_key_setmodified() +468 dst_key_isexternal(dst_key_t *key) { +469 return (key->external); +470 } +471 +472 void +473 dst_key_setmodified(dst_key_t *key, bool value) { +>>> CID 352776: Concurrent data access violations (MISSING_LOCK) +>>> Accessing "key->modified" without holding lock +>>> "dst_key.mdlock". Elsewhere, "dst_key.modified" is accessed with +>>> "dst_key.mdlock" held 8 out of 11 times (8 of these accesses +>>> strongly imply that it is necessary). +474 key->modified = value; +475 } +476 +477 bool +478 dst_key_ismodified(dst_key_t *key) { +479 return (key->modified); + +(cherry picked from commit 1fa24d0afbc01d25d71446156758b3a945db5b5f) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/7c42c04f3fa1c6b936debe48b435b9ef9da464bd +--- + lib/dns/dst_api.c | 12 ++++++++++-- + lib/dns/include/dst/dst.h | 2 +- + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c +index 8873a041b8..e5a52aea37 100644 +--- a/lib/dns/dst_api.c ++++ b/lib/dns/dst_api.c +@@ -492,12 +492,20 @@ dst_key_isexternal(dst_key_t *key) { + + void + dst_key_setmodified(dst_key_t *key, bool value) { ++ isc_mutex_lock(&key->mdlock); + key->modified = value; ++ isc_mutex_unlock(&key->mdlock); + } + + bool +-dst_key_ismodified(dst_key_t *key) { +- return (key->modified); ++dst_key_ismodified(const dst_key_t *key) { ++ bool modified; ++ ++ isc_mutex_lock(&(((dst_key_t *)key)->mdlock)); ++ modified = key->modified; ++ isc_mutex_unlock(&(((dst_key_t *)key)->mdlock)); ++ ++ return (modified); + } + + isc_result_t +diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h +index eab5501029..3185e9f91b 100644 +--- a/lib/dns/include/dst/dst.h ++++ b/lib/dns/include/dst/dst.h +@@ -1119,7 +1119,7 @@ dst_key_setmodified(dst_key_t *key, bool value); + */ + + bool +-dst_key_ismodified(dst_key_t *key); ++dst_key_ismodified(const dst_key_t *key); + /*%< + * Check if the key file has been modified. + * +-- +2.27.0 + diff --git a/backport-0037-Require-valid-key-for-dst_key-functions.patch b/backport-0037-Require-valid-key-for-dst_key-functions.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab19afbe86b1b9a25d16d5b490cd5b984c419f72 --- /dev/null +++ b/backport-0037-Require-valid-key-for-dst_key-functions.patch @@ -0,0 +1,70 @@ +From d3147417c55cb1277cac42034198a3011c8f5cfb Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Tue, 17 May 2022 12:02:43 +0200 +Subject: [PATCH] Require valid key for dst_key functions + +Make sure that the key structure is valid when calling the following +functions: +- dst_key_setexternal +- dst_key_isexternal +- dst_key_setmodified +- dst_key_ismodified + +This commit is adapted because 9.16 has a different approach +of deconsting the variable. + +(cherry picked from commit 888ec4e0d407a9333017d6997a2be81a69658e1f) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/d3147417c55cb1277cac42034198a3011c8f5cfb +--- + lib/dns/dst_api.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c +index e5a52aea37..f5741a1af4 100644 +--- a/lib/dns/dst_api.c ++++ b/lib/dns/dst_api.c +@@ -482,16 +482,22 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory) { + + void + dst_key_setexternal(dst_key_t *key, bool value) { ++ REQUIRE(VALID_KEY(key)); ++ + key->external = value; + } + + bool + dst_key_isexternal(dst_key_t *key) { ++ REQUIRE(VALID_KEY(key)); ++ + return (key->external); + } + + void + dst_key_setmodified(dst_key_t *key, bool value) { ++ REQUIRE(VALID_KEY(key)); ++ + isc_mutex_lock(&key->mdlock); + key->modified = value; + isc_mutex_unlock(&key->mdlock); +@@ -500,10 +506,15 @@ dst_key_setmodified(dst_key_t *key, bool value) { + bool + dst_key_ismodified(const dst_key_t *key) { + bool modified; ++ dst_key_t *k; + +- isc_mutex_lock(&(((dst_key_t *)key)->mdlock)); ++ REQUIRE(VALID_KEY(key)); ++ ++ DE_CONST(key, k); ++ ++ isc_mutex_lock(&k->mdlock); + modified = key->modified; +- isc_mutex_unlock(&(((dst_key_t *)key)->mdlock)); ++ isc_mutex_unlock(&k->mdlock); + + return (modified); + } +-- +2.27.0 + diff --git a/backport-0038-Do-not-cancel-processing-record-datasets-in-catalog-.patch b/backport-0038-Do-not-cancel-processing-record-datasets-in-catalog-.patch new file mode 100644 index 0000000000000000000000000000000000000000..8c797862ab4c42aa7c5fabfc0dcff3b3f8af102e --- /dev/null +++ b/backport-0038-Do-not-cancel-processing-record-datasets-in-catalog-.patch @@ -0,0 +1,45 @@ +From 87b3ced5fefffae9627ec23f7f509be6d79c39e7 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Thu, 24 Mar 2022 21:38:08 +0000 +Subject: [PATCH] Do not cancel processing record datasets in catalog zone + after an error + +When there are multiple record datasets in a database node of a catalog +zone, and BIND encounters a soft error during processing of a dataset, +it breaks from the loop and doesn't process the other datasets in the +node. + +There are cases when this is not desired. For example, the catalog zones +draft version 5 states that there must be a TXT RRset named +`version.$CATZ` with exactly one RR, but it doesn't set a limitation +on possible non-TXT RRsets named `version.$CATZ` existing alongside +with the TXT one. In case when one exists, we will get a processing +error and will not continue the loop to process the TXT RRset coming +next. + +Remove the "break" statement to continue processing all record datasets. + +(cherry picked from commit 0b2d5490cd8b17a01852fcd9e0a0e0c4b9c93ab6) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/87b3ced5fefffae9627ec23f7f509be6d79c39e7 +--- + lib/dns/catz.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/lib/dns/catz.c b/lib/dns/catz.c +index a749ffa9d4..e46549be5e 100644 +--- a/lib/dns/catz.c ++++ b/lib/dns/catz.c +@@ -1949,9 +1949,6 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { + } + next: + dns_rdataset_disassociate(&rdataset); +- if (result != ISC_R_SUCCESS) { +- break; +- } + result = dns_rdatasetiter_next(rdsiter); + } + +-- +2.23.0 + diff --git a/backport-0039-corrected-the-opcode-param-to-opcode_totext.patch b/backport-0039-corrected-the-opcode-param-to-opcode_totext.patch new file mode 100644 index 0000000000000000000000000000000000000000..c1d8f84c93a61f3834fca48a7d0328ee2378573d --- /dev/null +++ b/backport-0039-corrected-the-opcode-param-to-opcode_totext.patch @@ -0,0 +1,28 @@ +From 66cfaf0fb057eebb51a37d55c2e85679725bc740 Mon Sep 17 00:00:00 2001 +From: JINMEI Tatuya +Date: Mon, 13 Jun 2022 16:25:40 -0700 +Subject: [PATCH] corrected the opcode param to opcode_totext + +(cherry picked from commit 2b81a696593bdc406f0cadf2ec930118a86bf92c) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/66cfaf0fb057eebb51a37d55c2e85679725bc740 +--- + lib/dns/zone.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index b7b02ae5f9..ded4bb5f23 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -13144,7 +13144,7 @@ stub_glue_response_cb(isc_task_t *task, isc_event_t *event) { + isc_buffer_t rb; + + isc_buffer_init(&rb, opcode, sizeof(opcode)); +- (void)dns_opcode_totext(msg->rcode, &rb); ++ (void)dns_opcode_totext(msg->opcode, &rb); + + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: " +-- +2.23.0 + diff --git a/backport-0040-make-the-fix-more-complete.patch b/backport-0040-make-the-fix-more-complete.patch new file mode 100644 index 0000000000000000000000000000000000000000..85e88ff1a01c5d702e238d014c1dd7402f740786 --- /dev/null +++ b/backport-0040-make-the-fix-more-complete.patch @@ -0,0 +1,46 @@ +From 673211492ceff3b80c0307726f2956c7fbd4c9dd Mon Sep 17 00:00:00 2001 +From: JINMEI Tatuya +Date: Mon, 13 Jun 2022 16:30:00 -0700 +Subject: [PATCH] make the fix more complete + +(cherry picked from commit a58647df6a0afa188ed90c410d79ccfaeacfbf8b) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/673211492ceff3b80c0307726f2956c7fbd4c9dd +--- + lib/dns/zone.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index ded4bb5f23..cd4db58eaf 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -13573,7 +13573,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { + isc_buffer_t rb; + + isc_buffer_init(&rb, opcode, sizeof(opcode)); +- (void)dns_opcode_totext(msg->rcode, &rb); ++ (void)dns_opcode_totext(msg->opcode, &rb); + + dns_zone_log(zone, ISC_LOG_INFO, + "refreshing stub: " +@@ -13979,7 +13979,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { + isc_buffer_t rb; + + isc_buffer_init(&rb, opcode, sizeof(opcode)); +- (void)dns_opcode_totext(msg->rcode, &rb); ++ (void)dns_opcode_totext(msg->opcode, &rb); + + dns_zone_log(zone, ISC_LOG_INFO, + "refresh: " +@@ -18171,7 +18171,7 @@ forward_callback(isc_task_t *task, isc_event_t *event) { + isc_buffer_t rb; + + isc_buffer_init(&rb, opcode, sizeof(opcode)); +- (void)dns_opcode_totext(msg->rcode, &rb); ++ (void)dns_opcode_totext(msg->opcode, &rb); + + dns_zone_log(zone, ISC_LOG_INFO, + "forwarding dynamic update: " +-- +2.23.0 + diff --git a/backport-0041-Gracefully-handle-uv_read_start-failures.patch b/backport-0041-Gracefully-handle-uv_read_start-failures.patch new file mode 100644 index 0000000000000000000000000000000000000000..c2e3ab7d72ad5ce7d8049d79bafe046ebcc5442e --- /dev/null +++ b/backport-0041-Gracefully-handle-uv_read_start-failures.patch @@ -0,0 +1,261 @@ +From 6cfab7e4f737803e0fc686ea7b7be0d9215489c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Tue, 14 Jun 2022 09:17:08 +0200 +Subject: [PATCH] Gracefully handle uv_read_start() failures + +Under specific rare timing circumstances the uv_read_start() could +fail with UV_EINVAL when the connection is reset between the connect (or +accept) and the uv_read_start() call on the nmworker loop. Handle such +situation gracefully by propagating the errors from uv_read_start() into +upper layers, so the socket can be internally closed(). + +(cherry picked from commit b432d5d3bcccf199141564b6a87d2cdac296ed7e) +Conflict: adapt isc__nm_start_reading modify +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/6cfab7e4f737803e0fc686ea7b7be0d9215489c2 +--- + lib/isc/netmgr/netmgr-int.h | 4 ++-- + lib/isc/netmgr/netmgr.c | 32 +++++++++++++++++++++----------- + lib/isc/netmgr/tcp.c | 10 ++++++++-- + lib/isc/netmgr/tcpdns.c | 25 +++++++++++++++++++------ + lib/isc/netmgr/udp.c | 10 ++++++++-- + 5 files changed, 58 insertions(+), 23 deletions(-) + +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index e43bc9f..326535c 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -1560,11 +1560,11 @@ isc__nm_tcp_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); + void + isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); + +-void ++isc_result_t + isc__nm_start_reading(isc_nmsocket_t *sock); + void + isc__nm_stop_reading(isc_nmsocket_t *sock); +-void ++isc_result_t + isc__nm_process_sock_buffer(isc_nmsocket_t *sock); + void + isc__nm_resume_processing(void *arg); +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index 701f9a9..71c6d62 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -2162,12 +2162,13 @@ isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) { + worker->recvbuf_inuse = true; + } + +-void ++isc_result_t + isc__nm_start_reading(isc_nmsocket_t *sock) { ++ isc_result_t result = ISC_R_SUCCESS; + int r; + + if (sock->reading) { +- return; ++ return (ISC_R_SUCCESS); + } + + switch (sock->type) { +@@ -2187,8 +2188,14 @@ isc__nm_start_reading(isc_nmsocket_t *sock) { + INSIST(0); + ISC_UNREACHABLE(); + } +- RUNTIME_CHECK(r == 0); +- sock->reading = true; ++ ++ if (r != 0) { ++ result = isc__nm_uverr2result(r); ++ } else { ++ sock->reading = true; ++ } ++ ++ return (result); + } + + void +@@ -2250,7 +2257,7 @@ processbuffer(isc_nmsocket_t *sock) { + * limit. In this case we'll be called again by resume_processing() + * later. + */ +-void ++isc_result_t + isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { + for (;;) { + int_fast32_t ah = atomic_load(&sock->ah); +@@ -2261,7 +2268,10 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { + * Don't reset the timer until we have a + * full DNS message. + */ +- isc__nm_start_reading(sock); ++ result = isc__nm_start_reading(sock); ++ if (result != ISC_R_SUCCESS) { ++ return (result); ++ } + /* + * Start the timer only if there are no externally used + * active handles, there's always one active handle +@@ -2271,11 +2281,11 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { + if (ah == 1) { + isc__nmsocket_timer_start(sock); + } +- return; ++ goto done; + case ISC_R_CANCELED: + isc__nmsocket_timer_stop(sock); + isc__nm_stop_reading(sock); +- return; ++ goto done; + case ISC_R_SUCCESS: + /* + * Stop the timer on the successful message read, this +@@ -2289,13 +2299,15 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { + ah >= STREAM_CLIENTS_PER_CONN) + { + isc__nm_stop_reading(sock); +- return; ++ goto done; + } + break; + default: + INSIST(0); + } + } ++done: ++ return (ISC_R_SUCCESS); + } + + void +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index 009e431..735b29d 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -743,18 +743,24 @@ isc__nm_async_tcpstartread(isc__networker_t *worker, isc__netievent_t *ev0) { + isc__netievent_tcpstartread_t *ievent = + (isc__netievent_tcpstartread_t *)ev0; + isc_nmsocket_t *sock = ievent->sock; ++ isc_result_t result; + + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); + UNUSED(worker); + + if (isc__nmsocket_closing(sock)) { ++ result = ISC_R_CANCELED; ++ } else { ++ result = isc__nm_start_reading(sock); ++ } ++ ++ if (result != ISC_R_SUCCESS) { + sock->reading = true; +- isc__nm_tcp_failed_read_cb(sock, ISC_R_CANCELED); ++ isc__nm_tcp_failed_read_cb(sock, result); + return; + } + +- isc__nm_start_reading(sock); + isc__nmsocket_timer_start(sock); + } + +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index 4689f56..3bc8e05 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -709,6 +709,7 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0) { + isc__netievent_tcpdnsread_t *ievent = + (isc__netievent_tcpdnsread_t *)ev0; + isc_nmsocket_t *sock = ievent->sock; ++ isc_result_t result; + + UNUSED(worker); + +@@ -716,12 +717,15 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0) { + REQUIRE(sock->tid == isc_nm_tid()); + + if (isc__nmsocket_closing(sock)) { +- sock->reading = true; +- isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false); +- return; ++ result = ISC_R_CANCELED; ++ } else { ++ result = isc__nm_process_sock_buffer(sock); + } + +- isc__nm_process_sock_buffer(sock); ++ if (result != ISC_R_SUCCESS) { ++ sock->reading = true; ++ isc__nm_failed_read_cb(sock, result, false); ++ } + } + + /* +@@ -813,6 +817,7 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, + isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)stream); + uint8_t *base = NULL; + size_t len; ++ isc_result_t result; + + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->tid == isc_nm_tid()); +@@ -856,7 +861,10 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, + sock->read_timeout = atomic_load(&sock->mgr->idle); + } + +- isc__nm_process_sock_buffer(sock); ++ result = isc__nm_process_sock_buffer(sock); ++ if (result != ISC_R_SUCCESS) { ++ isc__nm_failed_read_cb(sock, result, true); ++ } + free: + isc__nm_free_uvbuf(sock, buf); + } +@@ -999,7 +1007,12 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { + * prep_destroy()->tcpdns_close_direct(). + */ + isc_nmhandle_attach(handle, &csock->recv_handle); +- isc__nm_process_sock_buffer(csock); ++ result = isc__nm_process_sock_buffer(csock); ++ if (result != ISC_R_SUCCESS) { ++ isc_nmhandle_detach(&csock->recv_handle); ++ isc_nmhandle_detach(&handle); ++ goto failure; ++ } + + /* + * The initial timer has been set, update the read timeout for the next +diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c +index 305ac29..1af63af 100644 +--- a/lib/isc/netmgr/udp.c ++++ b/lib/isc/netmgr/udp.c +@@ -879,6 +879,7 @@ void + isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) { + isc__netievent_udpread_t *ievent = (isc__netievent_udpread_t *)ev0; + isc_nmsocket_t *sock = ievent->sock; ++ isc_result_t result; + + UNUSED(worker); + +@@ -886,12 +887,17 @@ isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) { + REQUIRE(sock->tid == isc_nm_tid()); + + if (isc__nmsocket_closing(sock)) { ++ result = ISC_R_CANCELED; ++ } else { ++ result = isc__nm_start_reading(sock); ++ } ++ ++ if (result != ISC_R_SUCCESS) { + sock->reading = true; +- isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false); ++ isc__nm_failed_read_cb(sock, result, false); + return; + } + +- isc__nm_start_reading(sock); + isc__nmsocket_timer_start(sock); + } + +-- +2.27.0 + diff --git a/backport-0042-Fix-a-race-between-resolver-query-timeout-and-valida.patch b/backport-0042-Fix-a-race-between-resolver-query-timeout-and-valida.patch new file mode 100644 index 0000000000000000000000000000000000000000..53390c39542a0a749001fd07d5e4d4944dc4bd45 --- /dev/null +++ b/backport-0042-Fix-a-race-between-resolver-query-timeout-and-valida.patch @@ -0,0 +1,174 @@ +From 058a2e7d4437f383c5cda3a44921e49ad272f9fb Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Fri, 10 Jun 2022 14:44:52 +0000 +Subject: [PATCH] Fix a race between resolver query timeout and validation + +The `resolver.c:validated()` function unlinks the current validator from +the fetch's validators list, which can leave it empty, then unlocks +the bucket lock. If, by a chance, the fetch was timed out just before +the `validated()` call, the final timeout callback running in parallel +with `validated()` can find the fetch context with no active fetches +and with an empty validators list and destroy it, which is unexpected +for the `validated()` function and can lead to a crash. + +Increase the fetch context's reference count in the beginning of +`validated()` and decrease it when it finishes its work to avoid the +unexpected destruction of the fetch context. +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/058a2e7d4437f383c5cda3a44921e49ad272f9fb +--- + lib/dns/resolver.c | 63 +++++++++++++++++++++------------------------- + 1 file changed, 28 insertions(+), 35 deletions(-) + +diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c +index f34b9e318e..e8899d2457 100644 +--- a/lib/dns/resolver.c ++++ b/lib/dns/resolver.c +@@ -5746,12 +5746,13 @@ validated(isc_task_t *task, isc_event_t *event) { + dns_rdataset_t *rdataset; + dns_rdataset_t *sigrdataset; + dns_resolver_t *res; +- dns_valarg_t *valarg; ++ dns_valarg_t *valarg = event->ev_arg; + dns_validatorevent_t *vevent; + fetchctx_t *fctx; + bool chaining; + bool negative; + bool sentresponse; ++ bool bucket_empty; + isc_result_t eresult = ISC_R_SUCCESS; + isc_result_t result = ISC_R_SUCCESS; + isc_stdtime_t now; +@@ -5765,14 +5766,15 @@ validated(isc_task_t *task, isc_event_t *event) { + UNUSED(task); /* for now */ + + REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE); +- valarg = event->ev_arg; ++ REQUIRE(VALID_FCTX(valarg->fctx)); ++ REQUIRE(!ISC_LIST_EMPTY(valarg->fctx->validators)); ++ + fctx = valarg->fctx; ++ fctx_increference(fctx); + dns_message_attach(valarg->message, &message); + +- REQUIRE(VALID_FCTX(fctx)); + res = fctx->res; + addrinfo = valarg->addrinfo; +- REQUIRE(!ISC_LIST_EMPTY(fctx->validators)); + + vevent = (dns_validatorevent_t *)event; + fctx->vresult = vevent->result; +@@ -5810,12 +5812,8 @@ validated(isc_task_t *task, isc_event_t *event) { + * so, destroy the fctx. + */ + if (SHUTTINGDOWN(fctx) && !sentresponse) { +- bool bucket_empty; +- bucket_empty = maybe_destroy(fctx, true); ++ maybe_destroy(fctx, true); + UNLOCK(&res->buckets[bucketnum].lock); +- if (bucket_empty) { +- empty_bucket(res); +- } + goto cleanup_event; + } + +@@ -5877,18 +5875,15 @@ validated(isc_task_t *task, isc_event_t *event) { + (void)dns_db_deleterdataset(fctx->cache, node, + NULL, vevent->type, + 0); +- } +- if (result == ISC_R_SUCCESS && +- vevent->sigrdataset != NULL) { +- (void)dns_db_deleterdataset( +- fctx->cache, node, NULL, +- dns_rdatatype_rrsig, vevent->type); +- } +- if (result == ISC_R_SUCCESS) { ++ if (vevent->sigrdataset != NULL) { ++ (void)dns_db_deleterdataset( ++ fctx->cache, node, NULL, ++ dns_rdatatype_rrsig, ++ vevent->type); ++ } + dns_db_detachnode(fctx->cache, &node); + } +- } +- if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) { ++ } else if (!negative) { + /* + * Cache the data as pending for later validation. + */ +@@ -5901,20 +5896,16 @@ validated(isc_task_t *task, isc_event_t *event) { + (void)dns_db_addrdataset( + fctx->cache, node, NULL, now, + vevent->rdataset, 0, NULL); +- } +- if (result == ISC_R_SUCCESS && +- vevent->sigrdataset != NULL) { +- (void)dns_db_addrdataset( +- fctx->cache, node, NULL, now, +- vevent->sigrdataset, 0, NULL); +- } +- if (result == ISC_R_SUCCESS) { ++ if (vevent->sigrdataset != NULL) { ++ (void)dns_db_addrdataset( ++ fctx->cache, node, NULL, now, ++ vevent->sigrdataset, 0, NULL); ++ } + dns_db_detachnode(fctx->cache, &node); + } + } + result = fctx->vresult; + add_bad(fctx, message, addrinfo, result, badns_validation); +- isc_event_free(&event); + UNLOCK(&res->buckets[bucketnum].lock); + INSIST(fctx->validator == NULL); + fctx->validator = ISC_LIST_HEAD(fctx->validators); +@@ -5942,8 +5933,7 @@ validated(isc_task_t *task, isc_event_t *event) { + fctx_try(fctx, true, true); /* Locks bucket. */ + } + +- dns_message_detach(&message); +- return; ++ goto cleanup_event; + } + + if (negative) { +@@ -6057,19 +6047,15 @@ validated(isc_task_t *task, isc_event_t *event) { + } + + if (sentresponse) { +- bool bucket_empty = false; + /* + * If we only deferred the destroy because we wanted to cache + * the data, destroy now. + */ + dns_db_detachnode(fctx->cache, &node); + if (SHUTTINGDOWN(fctx)) { +- bucket_empty = maybe_destroy(fctx, true); ++ maybe_destroy(fctx, true); + } + UNLOCK(&res->buckets[bucketnum].lock); +- if (bucket_empty) { +- empty_bucket(res); +- } + goto cleanup_event; + } + +@@ -6210,6 +6196,13 @@ cleanup_event: + INSIST(node == NULL); + dns_message_detach(&message); + isc_event_free(&event); ++ ++ LOCK(&res->buckets[fctx->bucketnum].lock); ++ bucket_empty = fctx_decreference(fctx); ++ UNLOCK(&res->buckets[fctx->bucketnum].lock); ++ if (bucket_empty) { ++ empty_bucket(res); ++ } + } + + static void +-- +2.23.0 + diff --git a/backport-0042-Remove-resolver.c-maybe_destroy.patch b/backport-0042-Remove-resolver.c-maybe_destroy.patch new file mode 100644 index 0000000000000000000000000000000000000000..51269c96b79717afe2fb1296057151fe52925bf6 --- /dev/null +++ b/backport-0042-Remove-resolver.c-maybe_destroy.patch @@ -0,0 +1,150 @@ +From 61d77affdd39a352de5f386dc08818174fbaa781 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Wed, 15 Jun 2022 10:27:41 +0000 +Subject: [PATCH] Remove resolver.c:maybe_destroy() + +After refactoring of `validated()`, the `maybe_destroy()` function is +no longer expected to actually destroy the fetch context when it is +being called, so effectively it only ensures that the validators are +canceled when the context has no more queries and pending events, but +that is redundant, because `maybe_destroy()` `REQUIRE`s that the context +should be in the shutting down state, and the function which sets that +state is already canceling the validators in its own turn. + +As a failsafe, to make sure that no validators will be created after +`fctx_doshutdown()` is called, add an early return from `valcreate()` if +the context is in the shutting down state. +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/61d77affdd39a352de5f386dc08818174fbaa781 +--- + lib/dns/resolver.c | 73 +++++----------------------------------------- + 1 file changed, 7 insertions(+), 66 deletions(-) + +diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c +index e8899d2457..15297024c0 100644 +--- a/lib/dns/resolver.c ++++ b/lib/dns/resolver.c +@@ -641,8 +641,6 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, + dns_rdataset_t *ardataset, isc_result_t *eresultp); + static void + validated(isc_task_t *task, isc_event_t *event); +-static bool +-maybe_destroy(fetchctx_t *fctx, bool locked); + static void + add_bad(fetchctx_t *fctx, dns_message_t *rmessage, dns_adbaddrinfo_t *addrinfo, + isc_result_t reason, badnstype_t badtype); +@@ -902,14 +900,16 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo, + dns_rdataset_t *sigrdataset, unsigned int valoptions, + isc_task_t *task) { + dns_validator_t *validator = NULL; +- dns_valarg_t *valarg; ++ dns_valarg_t *valarg = NULL; + isc_result_t result; + ++ if (SHUTTINGDOWN(fctx)) { ++ return (ISC_R_SHUTTINGDOWN); ++ } ++ + valarg = isc_mem_get(fctx->mctx, sizeof(*valarg)); ++ *valarg = (dns_valarg_t){ .fctx = fctx, .addrinfo = addrinfo }; + +- valarg->fctx = fctx; +- valarg->addrinfo = addrinfo; +- valarg->message = NULL; + dns_message_attach(message, &valarg->message); + + if (!ISC_LIST_EMPTY(fctx->validators)) { +@@ -4434,7 +4434,6 @@ resume_qmin(isc_task_t *task, isc_event_t *event) { + + LOCK(&res->buckets[bucketnum].lock); + if (SHUTTINGDOWN(fctx)) { +- maybe_destroy(fctx, true); + UNLOCK(&res->buckets[bucketnum].lock); + goto cleanup; + } +@@ -5679,58 +5678,6 @@ clone_results(fetchctx_t *fctx) { + #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0) + #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0) + +-/* +- * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has +- * no references and is no longer waiting for any events). +- * +- * Requires: +- * '*fctx' is shutting down. +- * +- * Returns: +- * true if the resolver is exiting and this is the last fctx in the bucket. +- */ +-static bool +-maybe_destroy(fetchctx_t *fctx, bool locked) { +- unsigned int bucketnum; +- bool bucket_empty = false; +- dns_resolver_t *res = fctx->res; +- dns_validator_t *validator, *next_validator; +- bool dodestroy = false; +- +- bucketnum = fctx->bucketnum; +- if (!locked) { +- LOCK(&res->buckets[bucketnum].lock); +- } +- +- REQUIRE(SHUTTINGDOWN(fctx)); +- +- if (fctx->pending != 0 || fctx->nqueries != 0) { +- goto unlock; +- } +- +- for (validator = ISC_LIST_HEAD(fctx->validators); validator != NULL; +- validator = next_validator) +- { +- next_validator = ISC_LIST_NEXT(validator, link); +- dns_validator_cancel(validator); +- } +- +- if (isc_refcount_current(&fctx->references) == 0 && +- ISC_LIST_EMPTY(fctx->validators)) +- { +- bucket_empty = fctx_unlink(fctx); +- dodestroy = true; +- } +-unlock: +- if (!locked) { +- UNLOCK(&res->buckets[bucketnum].lock); +- } +- if (dodestroy) { +- fctx_destroy(fctx); +- } +- return (bucket_empty); +-} +- + /* + * The validator has finished. + */ +@@ -5807,12 +5754,9 @@ validated(isc_task_t *task, isc_event_t *event) { + sentresponse = ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0); + + /* +- * If shutting down, ignore the results. Check to see if we're +- * done waiting for validator completions and ADB pending events; if +- * so, destroy the fctx. ++ * If shutting down, ignore the results. + */ + if (SHUTTINGDOWN(fctx) && !sentresponse) { +- maybe_destroy(fctx, true); + UNLOCK(&res->buckets[bucketnum].lock); + goto cleanup_event; + } +@@ -6052,9 +5996,6 @@ validated(isc_task_t *task, isc_event_t *event) { + * the data, destroy now. + */ + dns_db_detachnode(fctx->cache, &node); +- if (SHUTTINGDOWN(fctx)) { +- maybe_destroy(fctx, true); +- } + UNLOCK(&res->buckets[bucketnum].lock); + goto cleanup_event; + } +-- +2.23.0 + diff --git a/backport-0043-Check-for-overflow-in-GENERATE-computations.patch b/backport-0043-Check-for-overflow-in-GENERATE-computations.patch new file mode 100644 index 0000000000000000000000000000000000000000..95b4592b10b9f9f760a912548a1e09d18fd95c22 --- /dev/null +++ b/backport-0043-Check-for-overflow-in-GENERATE-computations.patch @@ -0,0 +1,64 @@ +From 16ac79a8f720a917b0f787178905a8df56d4d557 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Fri, 1 Jul 2022 11:40:37 +1000 +Subject: [PATCH] Check for overflow in $GENERATE computations + +$GENERATE uses 'int' for its computations and some constructions +can overflow values that can be represented by an 'int' resulting +in undefined behaviour. Detect these conditions and return a +range error. + +(cherry picked from commit 5327b9708fd0e5d0d6c95183cca9eafb4a1cfe05) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/16ac79a8f720a917b0f787178905a8df56d4d557 +--- + .../checkzone/zones/bad-generate-range.db | 18 ++++++++++++++++++ + lib/dns/master.c | 7 +++++++ + 2 files changed, 25 insertions(+) + create mode 100644 bin/tests/system/checkzone/zones/bad-generate-range.db + +diff --git a/bin/tests/system/checkzone/zones/bad-generate-range.db b/bin/tests/system/checkzone/zones/bad-generate-range.db +new file mode 100644 +index 0000000000..62a9e15684 +--- /dev/null ++++ b/bin/tests/system/checkzone/zones/bad-generate-range.db +@@ -0,0 +1,18 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 600 ++@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 ++ NS ns ++ns A 192.0.2.1 ++ ++; 2147483647 + 1 overflows what can be represented in an 'int' ++$GENERATE 1-1 host$ TXT foo${2147483647} +diff --git a/lib/dns/master.c b/lib/dns/master.c +index e1ba723104..e938b15a0e 100644 +--- a/lib/dns/master.c ++++ b/lib/dns/master.c +@@ -735,6 +735,13 @@ genname(char *name, int it, char *buffer, size_t length) { + continue; + } + } ++ /* ++ * 'it' is >= 0 so we don't need to check for ++ * underflow. ++ */ ++ if ((it > 0 && delta > INT_MAX - it)) { ++ return (ISC_R_RANGE); ++ } + if (nibblemode) { + n = nibbles(numbuf, sizeof(numbuf), width, + mode[0], it + delta); +-- +2.23.0 + diff --git a/backport-0043-Tighten-GENERATE-directive-parsing.patch b/backport-0043-Tighten-GENERATE-directive-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..335ff2aa84bf4e33c8e41e9af70d2edddb7b2585 --- /dev/null +++ b/backport-0043-Tighten-GENERATE-directive-parsing.patch @@ -0,0 +1,161 @@ +From d10e20da0dbd6d6438d55a5e9c6e22cee70aec20 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Fri, 1 Jul 2022 11:13:51 +1000 +Subject: [PATCH] Tighten $GENERATE directive parsing + +The original sscanf processing allowed for a number of syntax errors +to be accepted. This included missing the closing brace in +${modifiers} + +Look for both comma and right brace as intermediate seperators as +well as consuming the final right brace in the sscanf processing +for ${modifiers}. Check when we got right brace to determine if +the sscanf consumed more input than expected and if so behave as +if it had stopped at the first right brace. + +(cherry picked from commit 7be64c0e94c967c0014a0b960a495c4fb05f1fc2) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/d10e20da0dbd6d6438d55a5e9c6e22cee70aec20 +--- + .../checkzone/zones/bad-generate-garbage.db | 17 ++++++++++ + .../zones/bad-generate-missing-brace.db | 17 ++++++++++ + .../checkzone/zones/good-generate-modifier.db | 20 +++++++++++ + lib/dns/master.c | 33 ++++++++++++------- + 4 files changed, 76 insertions(+), 11 deletions(-) + create mode 100644 bin/tests/system/checkzone/zones/bad-generate-garbage.db + create mode 100644 bin/tests/system/checkzone/zones/bad-generate-missing-brace.db + create mode 100644 bin/tests/system/checkzone/zones/good-generate-modifier.db + +diff --git a/bin/tests/system/checkzone/zones/bad-generate-garbage.db b/bin/tests/system/checkzone/zones/bad-generate-garbage.db +new file mode 100644 +index 0000000000..0d66e753b6 +--- /dev/null ++++ b/bin/tests/system/checkzone/zones/bad-generate-garbage.db +@@ -0,0 +1,17 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 600 ++@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 ++ NS ns ++ns A 192.0.2.1 ++ ++$GENERATE 0-7 host$ A 1.2.3.${1,0,dgarbagegarbage} +diff --git a/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db b/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db +new file mode 100644 +index 0000000000..314583e71a +--- /dev/null ++++ b/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db +@@ -0,0 +1,17 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 600 ++@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 ++ NS ns ++ns A 192.0.2.1 ++ ++$GENERATE 0-7 host$ A 1.2.3.${1000 +diff --git a/bin/tests/system/checkzone/zones/good-generate-modifier.db b/bin/tests/system/checkzone/zones/good-generate-modifier.db +new file mode 100644 +index 0000000000..3c811d60e0 +--- /dev/null ++++ b/bin/tests/system/checkzone/zones/good-generate-modifier.db +@@ -0,0 +1,20 @@ ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") ++; ++; SPDX-License-Identifier: MPL-2.0 ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. ++; ++; See the COPYRIGHT file distributed with this work for additional ++; information regarding copyright ownership. ++ ++$TTL 600 ++@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 ++ NS ns ++ns A 192.0.2.1 ++ ++$GENERATE 0-7 host$ A 1.2.3.${1,0,d} ++$GENERATE 8-9 host$ A 1.2.3.${1,0} ++$GENERATE 10-11 host$ A 1.2.3.${1} ++$GENERATE 1024-1026 ${0,3,n} AAAA 2001:db8::${0,4,x} +diff --git a/lib/dns/master.c b/lib/dns/master.c +index e938b15a0e..1ad658b7f4 100644 +--- a/lib/dns/master.c ++++ b/lib/dns/master.c +@@ -683,7 +683,10 @@ genname(char *name, int it, char *buffer, size_t length) { + char fmt[sizeof("%04000000000d")]; + char numbuf[128]; + char *cp; +- char mode[2]; ++ char mode[2] = { 0 }; ++ char brace[2] = { 0 }; ++ char comma1[2] = { 0 }; ++ char comma2[2] = { 0 }; + int delta = 0; + isc_textregion_t r; + unsigned int n; +@@ -708,23 +711,31 @@ genname(char *name, int it, char *buffer, size_t length) { + strlcpy(fmt, "%d", sizeof(fmt)); + /* Get format specifier. */ + if (*name == '{') { +- n = sscanf(name, "{%d,%u,%1[doxXnN]}", &delta, +- &width, mode); +- switch (n) { +- case 1: +- break; +- case 2: ++ n = sscanf(name, ++ "{%d%1[,}]%u%1[,}]%1[doxXnN]%1[}]", ++ &delta, comma1, &width, comma2, mode, ++ brace); ++ if (n < 2 || n > 6) { ++ return (DNS_R_SYNTAX); ++ } ++ if (comma1[0] == '}') { ++ /* %{delta} */ ++ } else if (comma1[0] == ',' && comma2[0] == '}') ++ { ++ /* %{delta,width} */ + n = snprintf(fmt, sizeof(fmt), "%%0%ud", + width); +- break; +- case 3: ++ } else if (comma1[0] == ',' && ++ comma2[0] == ',' && mode[0] != 0 && ++ brace[0] == '}') ++ { ++ /* %{delta,width,format} */ + if (mode[0] == 'n' || mode[0] == 'N') { + nibblemode = true; + } + n = snprintf(fmt, sizeof(fmt), + "%%0%u%c", width, mode[0]); +- break; +- default: ++ } else { + return (DNS_R_SYNTAX); + } + if (n >= sizeof(fmt)) { +-- +2.23.0 + diff --git a/backport-0044-Add-UV_RUNTIME_CHECK-macro-to-print-uv_strerror.patch b/backport-0044-Add-UV_RUNTIME_CHECK-macro-to-print-uv_strerror.patch new file mode 100644 index 0000000000000000000000000000000000000000..5f101b8e6ad850a8585c01dca51f7f441ee4cfb2 --- /dev/null +++ b/backport-0044-Add-UV_RUNTIME_CHECK-macro-to-print-uv_strerror.patch @@ -0,0 +1,39 @@ +From 88751da1145e1bbc4ed32fd100184f3f0d7e2ad1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Tue, 15 Feb 2022 14:44:29 +0100 +Subject: [PATCH] Add UV_RUNTIME_CHECK() macro to print uv_strerror() + +When libuv functions fail, they return correct return value that could +be useful for more detailed debugging. Currently, we usually just check +whether the return value is 0 and invoke assertion error if it doesn't +throwing away the details why the call has failed. Unfortunately, this +often happen on more exotic platforms. + +Add a UV_RUNTIME_CHECK() macro that can be used to print more detailed +error message (via uv_strerror() before ending the execution of the +program abruptly with the assertion. + +(cherry picked from commit 62e15bb06db5e7d209e8c20d7bdb1501df7dfba8) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/88751da1145e1bbc4ed32fd100184f3f0d7e2ad1 +--- + lib/isc/netmgr/netmgr-int.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index 326535c..23bc2a2 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -1607,3 +1607,9 @@ isc__nmsocket_writetimeout_cb(void *data, isc_result_t eresult); + * changed in the future. + */ + #define STREAM_CLIENTS_PER_CONN 23 ++ ++#define UV_RUNTIME_CHECK(func, ret) \ ++ if (ret != 0) { \ ++ isc_error_fatal(__FILE__, __LINE__, "%s failed: %s\n", #func, \ ++ uv_strerror(ret)); \ ++ } +-- +2.27.0 + diff --git a/backport-0045-Move-setting-the-sock-write_timeout-to-the-async_-se.patch b/backport-0045-Move-setting-the-sock-write_timeout-to-the-async_-se.patch new file mode 100644 index 0000000000000000000000000000000000000000..9e528c6c018382489a36d604c7e8a93ebe695fa8 --- /dev/null +++ b/backport-0045-Move-setting-the-sock-write_timeout-to-the-async_-se.patch @@ -0,0 +1,88 @@ +From ed4eda5ebc77c08b7ef1e6c94bea373c00c903c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Tue, 17 May 2022 21:31:37 +0200 +Subject: [PATCH] Move setting the sock->write_timeout to the async_*send + +Setting the sock->write_timeout from the TCP, TCPDNS, and TLSDNS send +functions could lead to (harmless) data race when setting the value for +the first time when the isc_nm_send() function would be called from +thread not-matching the socket we are sending to. Move the setting the +sock->write_timeout to the matching async function which is always +called from the matching thread. + +(cherry picked from commit 61117840c18778e69e3073cc01dbea579271a014) +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/ed4eda5ebc77c08b7ef1e6c94bea373c00c903c8 +--- + lib/isc/netmgr/tcp.c | 14 +++++++------- + lib/isc/netmgr/tcpdns.c | 15 ++++++++------- + 2 files changed, 15 insertions(+), 14 deletions(-) + +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index a8d1dba6d4..eaad8da7c6 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -1083,13 +1083,6 @@ isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region, + uvreq->cb.send = cb; + uvreq->cbarg = cbarg; + +- if (sock->write_timeout == 0) { +- sock->write_timeout = +- (atomic_load(&sock->keepalive) +- ? atomic_load(&sock->mgr->keepalive) +- : atomic_load(&sock->mgr->idle)); +- } +- + ievent = isc__nm_get_netievent_tcpsend(sock->mgr, sock, uvreq); + isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid], + (isc__netievent_t *)ievent); +@@ -1134,6 +1127,13 @@ isc__nm_async_tcpsend(isc__networker_t *worker, isc__netievent_t *ev0) { + REQUIRE(sock->tid == isc_nm_tid()); + UNUSED(worker); + ++ if (sock->write_timeout == 0) { ++ sock->write_timeout = ++ (atomic_load(&sock->keepalive) ++ ? atomic_load(&sock->mgr->keepalive) ++ : atomic_load(&sock->mgr->idle)); ++ } ++ + result = tcp_send_direct(sock, uvreq); + if (result != ISC_R_SUCCESS) { + isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]); +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index e287f0a282..6f513b49ce 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -1088,13 +1088,6 @@ isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region, + uvreq->cb.send = cb; + uvreq->cbarg = cbarg; + +- if (sock->write_timeout == 0) { +- sock->write_timeout = +- (atomic_load(&sock->keepalive) +- ? atomic_load(&sock->mgr->keepalive) +- : atomic_load(&sock->mgr->idle)); +- } +- + ievent = isc__nm_get_netievent_tcpdnssend(sock->mgr, sock, uvreq); + isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid], + (isc__netievent_t *)ievent); +@@ -1141,6 +1134,14 @@ isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) { + isc_result_t result; + isc_nmsocket_t *sock = ievent->sock; + isc__nm_uvreq_t *uvreq = ievent->req; ++ ++ if (sock->write_timeout == 0) { ++ sock->write_timeout = ++ (atomic_load(&sock->keepalive) ++ ? atomic_load(&sock->mgr->keepalive) ++ : atomic_load(&sock->mgr->idle)); ++ } ++ + uv_buf_t bufs[2] = { { .base = uvreq->tcplen, .len = 2 }, + { .base = uvreq->uvbuf.base, + .len = uvreq->uvbuf.len } }; +-- +2.23.0 + diff --git a/backport-Accept-in-NULL-with-inlen-0-in-isc_-half-siphash24.patch b/backport-Accept-in-NULL-with-inlen-0-in-isc_-half-siphash24.patch new file mode 100644 index 0000000000000000000000000000000000000000..575ce6d668e7b81f3d6b8fafbe37ed8eb1ea6fdb --- /dev/null +++ b/backport-Accept-in-NULL-with-inlen-0-in-isc_-half-siphash24.patch @@ -0,0 +1,60 @@ +From f1c08fe93ba35343534d893f3efcfa6f5d97fdf0 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Tue, 10 Jan 2023 13:51:49 +1100 +Subject: [PATCH] Accept 'in=NULL' with 'inlen=0' in isc_{half}siphash24 + +Arthimetic on NULL pointers is undefined. Avoid arithmetic operations +when 'in' is NULL and require 'in' to be non-NULL if 'inlen' is not zero. + +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/f1c08fe93ba35343534d893f3efcfa6f5d97fdf0 + +(cherry picked from commit 349c23dbb7a4f3ffe29f3c9deff418aab6266fd0) +--- + lib/isc/siphash.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/lib/isc/siphash.c b/lib/isc/siphash.c +index 1a863ff8e1..a6e60cf02f 100644 +--- a/lib/isc/siphash.c ++++ b/lib/isc/siphash.c +@@ -91,6 +91,7 @@ isc_siphash24(const uint8_t *k, const uint8_t *in, const size_t inlen, + uint8_t *out) { + REQUIRE(k != NULL); + REQUIRE(out != NULL); ++ REQUIRE(inlen == 0 || in != NULL); + + uint64_t k0 = U8TO64_LE(k); + uint64_t k1 = U8TO64_LE(k + 8); +@@ -102,7 +103,9 @@ isc_siphash24(const uint8_t *k, const uint8_t *in, const size_t inlen, + + uint64_t b = ((uint64_t)inlen) << 56; + +- const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t)); ++ const uint8_t *end = (in == NULL) ++ ? NULL ++ : in + inlen - (inlen % sizeof(uint64_t)); + const size_t left = inlen & 7; + + for (; in != end; in += 8) { +@@ -169,6 +172,7 @@ isc_halfsiphash24(const uint8_t *k, const uint8_t *in, const size_t inlen, + uint8_t *out) { + REQUIRE(k != NULL); + REQUIRE(out != NULL); ++ REQUIRE(inlen == 0 || in != NULL); + + uint32_t k0 = U8TO32_LE(k); + uint32_t k1 = U8TO32_LE(k + 4); +@@ -180,7 +184,9 @@ isc_halfsiphash24(const uint8_t *k, const uint8_t *in, const size_t inlen, + + uint32_t b = ((uint32_t)inlen) << 24; + +- const uint8_t *end = in + inlen - (inlen % sizeof(uint32_t)); ++ const uint8_t *end = (in == NULL) ++ ? NULL ++ : in + inlen - (inlen % sizeof(uint32_t)); + const int left = inlen & 3; + + for (; in != end; in += 4) { +-- +2.23.0 diff --git a/backport-Add-mctx-attach-detach-when-creating-destroying-a-memory-pool.patch b/backport-Add-mctx-attach-detach-when-creating-destroying-a-memory-pool.patch new file mode 100644 index 0000000000000000000000000000000000000000..03dbc11fc92f3e383c6821cedefae3a89f831577 --- /dev/null +++ b/backport-Add-mctx-attach-detach-when-creating-destroying-a-memory-pool.patch @@ -0,0 +1,41 @@ +yum 32779aba8a0a5f852c611f44ecbeab5aab633e34 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Wed, 31 Aug 2022 12:30:38 +0000 +Subject: [PATCH] Add mctx attach/detach when creating/destroying a memory pool + +This should make sure that the memory context is not destroyed +before the memory pool, which is using the context. +Conflict: Context adaptation in the original patch:+ mpctx->lock = NULL; +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/32779aba8a0a5f852c611f44ecbeab5aab633e34 +(cherry picked from commit e97c3eea954e055634b72c21325d2611e960ee94) +--- + lib/isc/mem.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/lib/isc/mem.c b/lib/isc/mem.c +index f84d300..33ece7a 100644 +--- a/lib/isc/mem.c ++++ b/lib/isc/mem.c +@@ -1656,7 +1656,8 @@ isc_mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) { + mpctx->common.impmagic = MEMPOOL_MAGIC; + mpctx->common.magic = ISCAPI_MPOOL_MAGIC; + mpctx->lock = NULL; +- mpctx->mctx = mctx; ++ mpctx->mctx = NULL; ++ isc_mem_attach((isc_mem_t *)mctx, (isc_mem_t **)&mpctx->mctx); + /* + * Mempools are stored as a linked list of element. + */ +@@ -1765,7 +1766,8 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) { + mpctx->common.impmagic = 0; + mpctx->common.magic = 0; + +- isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t)); ++ isc_mem_putanddetach((isc_mem_t **)&mpctx->mctx, mpctx, ++ sizeof(isc__mempool_t)); + + if (lock != NULL) { + UNLOCK(lock); +-- +2.33.0 + diff --git a/backport-Add-missing-DbC-magic-checks.patch b/backport-Add-missing-DbC-magic-checks.patch new file mode 100644 index 0000000000000000000000000000000000000000..5a3c341d3fcc638bc0d9d98fd2d2c23fe5f7cbbb --- /dev/null +++ b/backport-Add-missing-DbC-magic-checks.patch @@ -0,0 +1,64 @@ +From f9845df6d61e7491508a7f54b1d3caab7641652e Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 1 Dec 2022 12:51:30 +1100 +Subject: [PATCH] Add missing DbC magic checks + +Checking for value != NULL is not sufficient to detect use after +free errors. + +(cherry picked from commit b1086a5561c8024fc39b5250063fc901c27eef06) +--- + lib/dns/catz.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/lib/dns/catz.c b/lib/dns/catz.c +index 332f9877360..68927e84bbf 100644 +--- a/lib/dns/catz.c ++++ b/lib/dns/catz.c +@@ -638,7 +638,7 @@ cleanup_ht: + void + dns_catz_catzs_set_view(dns_catz_zones_t *catzs, dns_view_t *view) { + REQUIRE(DNS_CATZ_ZONES_VALID(catzs)); +- REQUIRE(view != NULL); ++ REQUIRE(DNS_VIEW_VALID(view)); + /* Either it's a new one or it's being reconfigured. */ + REQUIRE(catzs->view == NULL || !strcmp(catzs->view->name, view->name)); + +@@ -834,7 +834,7 @@ void + dns_catz_catzs_detach(dns_catz_zones_t **catzsp) { + dns_catz_zones_t *catzs; + +- REQUIRE(catzsp != NULL && *catzsp != NULL); ++ REQUIRE(catzsp != NULL && DNS_CATZ_ZONES_VALID(*catzsp)); + + catzs = *catzsp; + *catzsp = NULL; +@@ -1515,7 +1515,7 @@ dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry, + bool special = false; + + REQUIRE(DNS_CATZ_ZONE_VALID(zone)); +- REQUIRE(entry != NULL); ++ REQUIRE(DNS_CATZ_ENTRY_VALID(entry)); + REQUIRE(buffer != NULL && *buffer != NULL); + + isc_buffer_allocate(zone->catzs->mctx, &tbuf, +@@ -1613,7 +1613,7 @@ dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry, + char zname[DNS_NAME_FORMATSIZE]; + + REQUIRE(DNS_CATZ_ZONE_VALID(zone)); +- REQUIRE(entry != NULL); ++ REQUIRE(DNS_CATZ_ENTRY_VALID(entry)); + REQUIRE(buf != NULL && *buf == NULL); + + /* +@@ -1745,7 +1745,7 @@ dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg) { + isc_region_t r; + + REQUIRE(DNS_DB_VALID(db)); +- REQUIRE(fn_arg != NULL); ++ REQUIRE(DNS_CATZ_ZONES_VALID(fn_arg)); + catzs = (dns_catz_zones_t *)fn_arg; + + dns_name_toregion(&db->origin, &r); +-- +2.23.0 \ No newline at end of file diff --git a/backport-CVE-2021-25214.patch b/backport-CVE-2021-25214.patch deleted file mode 100644 index 00eccf8d03fdf0f9de3b8bb330f61962897cae67..0000000000000000000000000000000000000000 --- a/backport-CVE-2021-25214.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 813a1d0f943f7b4ecf43c449a08762a8d8557a45 Mon Sep 17 00:00:00 2001 -From: UNKNOWN <> -Date: Tue, 27 Apr 2021 12:02:53 +0800 -Subject: [PATCH v2 1/2] Fix CVE-2021-25214 - -Conflict:NA -Reference:https://downloads.isc.org/isc/bind9/private/40732ca6e4fcc9d0/patches/CVE-2021-25214.patch - - -diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c -index 558f40c..bae6d41 100644 ---- a/lib/dns/xfrin.c -+++ b/lib/dns/xfrin.c -@@ -474,6 +474,20 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl, - dns_rdatatype_ismeta(rdata->type)) - FAIL(DNS_R_FORMERR); - -+ /* -+ * Immediately reject the entire transfer if the RR that is currently -+ * being processed is an SOA record that is not placed at the zone -+ * apex. -+ */ -+ if (rdata->type == dns_rdatatype_soa && -+ !dns_name_equal(&xfr->name, name)) { -+ char namebuf[DNS_NAME_FORMATSIZE]; -+ dns_name_format(name, namebuf, sizeof(namebuf)); -+ xfrin_log(xfr, ISC_LOG_DEBUG(3), "SOA name mismatch: '%s'", -+ namebuf); -+ FAIL(DNS_R_NOTZONETOP); -+ } -+ - redo: - switch (xfr->state) { - case XFRST_SOAQUERY: --- -1.8.3.1 diff --git a/backport-CVE-2021-25215.patch b/backport-CVE-2021-25215.patch deleted file mode 100644 index bbd3c4acb2714fb508af8c0f7b154096a245e7e1..0000000000000000000000000000000000000000 --- a/backport-CVE-2021-25215.patch +++ /dev/null @@ -1,36 +0,0 @@ -From c42cc79ef9a23d8273b273bb86a1c8c9995b28a0 Mon Sep 17 00:00:00 2001 -From: UNKNOWN <> -Date: Tue, 27 Apr 2021 12:12:24 +0800 -Subject: [PATCH v2 2/2] Fix CVE-2021-25215 - -Conflict:NA -Reference:https://downloads.isc.org/isc/bind9/private/40732ca6e4fcc9d0/patches/CVE-2021-25215.patch - - -diff --git a/bin/named/query.c b/bin/named/query.c -index 6e988f5..2e7700a 100644 ---- a/bin/named/query.c -+++ b/bin/named/query.c -@@ -9092,10 +9092,17 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - if (noqname != NULL) - query_addnoqnameproof(client, noqname); - /* -- * We shouldn't ever fail to add 'rdataset' -- * because it's already in the answer. -+ * 'rdataset' will only be non-NULL here if the ANSWER section -+ * of the message to be sent to the client already contains an -+ * RRset with the same owner name and the same type as -+ * 'rdataset'. This should never happen, with one exception: -+ * when chasing DNAME records, one of the DNAME records placed -+ * in the ANSWER section may turn out to be the final answer to -+ * the client's query, but we have no way of knowing that until -+ * now. In such a case, 'rdataset' will be freed later, so we -+ * do not need to free it here. - */ -- INSIST(rdataset == NULL); -+ INSIST(rdataset == NULL || qtype == dns_rdatatype_dname); - } - - addauth: --- -1.8.3.1 diff --git a/backport-CVE-2021-25220.patch b/backport-CVE-2021-25220.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb4dd26e1052c2dea48f8f1084db1a0e0a6b3c27 --- /dev/null +++ b/backport-CVE-2021-25220.patch @@ -0,0 +1,208 @@ +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/f1bc36f19362f9f2173bf9511e85781058f19c64 +diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c +index dd82f273a4d5a2d34edd1cbcba8c9daf78a71b34..677384b1081d060ccc0acc92e476eb7664577806 100644 +--- a/lib/dns/resolver.c ++++ b/lib/dns/resolver.c +@@ -65,6 +65,8 @@ + #include + #include + #include ++#include ++ + #ifdef WANT_QUERYTRACE + #define RTRACE(m) \ + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, \ +@@ -339,6 +341,8 @@ struct fetchctx { + dns_fetch_t *qminfetch; + dns_rdataset_t qminrrset; + dns_name_t qmindcname; ++ dns_fixedname_t fwdfname; ++ dns_name_t *fwdname; + + /*% + * The number of events we're waiting for. +@@ -3766,6 +3770,7 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) { + if (result == ISC_R_SUCCESS) { + fwd = ISC_LIST_HEAD(forwarders->fwdrs); + fctx->fwdpolicy = forwarders->fwdpolicy; ++ dns_name_copynf(domain, fctx->fwdname); + if (fctx->fwdpolicy == dns_fwdpolicy_only && + isstrictsubdomain(domain, &fctx->domain)) + { +@@ -5155,6 +5160,9 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, + fctx->restarts = 0; + fctx->querysent = 0; + fctx->referrals = 0; ++ ++ fctx->fwdname = dns_fixedname_initname(&fctx->fwdfname); ++ + TIME_NOW(&fctx->start); + fctx->timeouts = 0; + fctx->lamecount = 0; +@@ -5217,6 +5225,7 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, + fname, &forwarders); + if (result == ISC_R_SUCCESS) { + fctx->fwdpolicy = forwarders->fwdpolicy; ++ dns_name_copynf(fname, fctx->fwdname); + } + + if (fctx->fwdpolicy != dns_fwdpolicy_only) { +@@ -7120,6 +7129,107 @@ mark_related(dns_name_t *name, dns_rdataset_t *rdataset, bool external, + } + } + ++/* ++ * Returns true if 'name' is external to the namespace for which ++ * the server being queried can answer, either because it's not a ++ * subdomain or because it's below a forward declaration or a ++ * locally served zone. ++ */ ++static inline bool ++name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) { ++ isc_result_t result; ++ dns_forwarders_t *forwarders = NULL; ++ dns_fixedname_t fixed, zfixed; ++ dns_name_t *fname = dns_fixedname_initname(&fixed); ++ dns_name_t *zfname = dns_fixedname_initname(&zfixed); ++ dns_name_t *apex = NULL; ++ dns_name_t suffix; ++ dns_zone_t *zone = NULL; ++ unsigned int labels; ++ dns_namereln_t rel; ++ ++ apex = ISFORWARDER(fctx->addrinfo) ? fctx->fwdname : &fctx->domain; ++ ++ /* ++ * The name is outside the queried namespace. ++ */ ++ rel = dns_name_fullcompare(name, apex, &(int){ 0 }, ++ &(unsigned int){ 0U }); ++ if (rel != dns_namereln_subdomain && rel != dns_namereln_equal) { ++ return (true); ++ } ++ ++ /* ++ * If the record lives in the parent zone, adjust the name so we ++ * look for the correct zone or forward clause. ++ */ ++ labels = dns_name_countlabels(name); ++ if (dns_rdatatype_atparent(type) && labels > 1U) { ++ dns_name_init(&suffix, NULL); ++ dns_name_getlabelsequence(name, 1, labels - 1, &suffix); ++ name = &suffix; ++ } else if (rel == dns_namereln_equal) { ++ /* If 'name' is 'apex', no further checking is needed. */ ++ return (false); ++ } ++ ++ /* ++ * If there is a locally served zone between 'apex' and 'name' ++ * then don't cache. ++ */ ++ LOCK(&fctx->res->view->lock); ++ if (fctx->res->view->zonetable != NULL) { ++ unsigned int options = DNS_ZTFIND_NOEXACT | DNS_ZTFIND_MIRROR; ++ result = dns_zt_find(fctx->res->view->zonetable, name, options, ++ zfname, &zone); ++ if (zone != NULL) { ++ dns_zone_detach(&zone); ++ } ++ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { ++ if (dns_name_fullcompare(zfname, apex, &(int){ 0 }, ++ &(unsigned int){ 0U }) == ++ dns_namereln_subdomain) ++ { ++ UNLOCK(&fctx->res->view->lock); ++ return (true); ++ } ++ } ++ } ++ UNLOCK(&fctx->res->view->lock); ++ ++ /* ++ * Look for a forward declaration below 'name'. ++ */ ++ result = dns_fwdtable_find(fctx->res->view->fwdtable, name, fname, ++ &forwarders); ++ ++ if (ISFORWARDER(fctx->addrinfo)) { ++ /* ++ * See if the forwarder declaration is better. ++ */ ++ if (result == ISC_R_SUCCESS) { ++ return (!dns_name_equal(fname, fctx->fwdname)); ++ } ++ ++ /* ++ * If the lookup failed, the configuration must have ++ * changed: play it safe and don't cache. ++ */ ++ return (true); ++ } else if (result == ISC_R_SUCCESS && ++ forwarders->fwdpolicy == dns_fwdpolicy_only && ++ !ISC_LIST_EMPTY(forwarders->fwdrs)) ++ { ++ /* ++ * If 'name' is covered by a 'forward only' clause then we ++ * can't cache this repsonse. ++ */ ++ return (true); ++ } ++ ++ return (false); ++} ++ + static isc_result_t + check_section(void *arg, const dns_name_t *addname, dns_rdatatype_t type, + dns_section_t section) { +@@ -7146,7 +7256,7 @@ check_section(void *arg, const dns_name_t *addname, dns_rdatatype_t type, + result = dns_message_findname(rctx->query->rmessage, section, addname, + dns_rdatatype_any, 0, &name, NULL); + if (result == ISC_R_SUCCESS) { +- external = !dns_name_issubdomain(name, &fctx->domain); ++ external = name_external(name, type, fctx); + if (type == dns_rdatatype_a) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; +@@ -8770,6 +8880,13 @@ rctx_answer_scan(respctx_t *rctx) { + break; + + case dns_namereln_subdomain: ++ /* ++ * Don't accept DNAME from parent namespace. ++ */ ++ if (name_external(name, dns_rdatatype_dname, fctx)) { ++ continue; ++ } ++ + /* + * In-scope DNAME records must have at least + * as many labels as the domain being queried. +@@ -9083,13 +9200,11 @@ rctx_authority_positive(respctx_t *rctx) { + DNS_SECTION_AUTHORITY); + while (!done && result == ISC_R_SUCCESS) { + dns_name_t *name = NULL; +- bool external; + + dns_message_currentname(rctx->query->rmessage, + DNS_SECTION_AUTHORITY, &name); +- external = !dns_name_issubdomain(name, &fctx->domain); + +- if (!external) { ++ if (!name_external(name, dns_rdatatype_ns, fctx)) { + dns_rdataset_t *rdataset = NULL; + + /* +@@ -9476,7 +9591,10 @@ rctx_authority_dnssec(respctx_t *rctx) { + } + + if (!dns_name_issubdomain(name, &fctx->domain)) { +- /* Invalid name found; preserve it for logging later */ ++ /* ++ * Invalid name found; preserve it for logging ++ * later. ++ */ + rctx->found_name = name; + rctx->found_type = ISC_LIST_HEAD(name->list)->type; + continue; diff --git a/backport-CVE-2022-0396.patch b/backport-CVE-2022-0396.patch new file mode 100644 index 0000000000000000000000000000000000000000..e66735d55b9a51844ab15b939b90cbe4de40fcc7 --- /dev/null +++ b/backport-CVE-2022-0396.patch @@ -0,0 +1,79 @@ +From bfa4b9c1418ca1ae504f3474e8ffe6fddb6d3e98 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Tue, 8 Feb 2022 12:42:34 +0100 +Subject: [PATCH] Run .closehandle_cb asynchrounosly in nmhandle_detach_cb() + +When sock->closehandle_cb is set, we need to run nmhandle_detach_cb() +asynchronously to ensure correct order of multiple packets processing in +the isc__nm_process_sock_buffer(). When not run asynchronously, it +would cause: + + a) out-of-order processing of the return codes from processbuffer(); + + b) stack growth because the next TCP DNS message read callback will + be called from within the current TCP DNS message read callback. + +The sock->closehandle_cb is set to isc__nm_resume_processing() for TCP +sockets which calls isc__nm_process_sock_buffer(). If the read callback +(called from isc__nm_process_sock_buffer()->processbuffer()) doesn't +attach to the nmhandle (f.e. because it wants to drop the processing or +we send the response directly via uv_try_write()), the +isc__nm_resume_processing() (via .closehandle_cb) would call +isc__nm_process_sock_buffer() recursively. + +The below shortened code path shows how the stack can grow: + + 1: ns__client_request(handle, ...); + 2: isc_nm_tcpdns_sequential(handle); + 3: ns_query_start(client, handle); + 4: query_lookup(qctx); + 5: query_send(qctcx->client); + 6: isc__nmhandle_detach(&client->reqhandle); + 7: nmhandle_detach_cb(&handle); + 8: sock->closehandle_cb(sock); // isc__nm_resume_processing + 9: isc__nm_process_sock_buffer(sock); +10: processbuffer(sock); // isc__nm_tcpdns_processbuffer +11: isc_nmhandle_attach(req->handle, &handle); +12: isc__nm_readcb(sock, req, ISC_R_SUCCESS); +13: isc__nm_async_readcb(NULL, ...); +14: uvreq->cb.recv(...); // ns__client_request + +Instead, if 'sock->closehandle_cb' is set, we need to run detach the +handle asynchroniously in 'isc__nmhandle_detach', so that on line 8 in +the code flow above does not start this recursion. This ensures the +correct order when processing multiple packets in the function +'isc__nm_process_sock_buffer()' and prevents the stack growth. + +When not run asynchronously, the out-of-order processing leaves the +first TCP socket open until all requests on the stream have been +processed. + +If the pipelining is disabled on the TCP via `keep-response-order` +configuration option, named would keep the first socket in lingering +CLOSE_WAIT state when the client sends an incomplete packet and then +closes the connection from the client side. +--- + lib/isc/netmgr/netmgr.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index cabe9d5..c405a9b 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -1731,8 +1731,12 @@ isc__nmhandle_detach(isc_nmhandle_t **handlep FLARG) { + handle = *handlep; + *handlep = NULL; + ++ /* ++ * If the closehandle_cb is set, it needs to run asynchronously to ++ * ensure correct ordering of the isc__nm_process_sock_buffer(). ++ */ + sock = handle->sock; +- if (sock->tid == isc_nm_tid()) { ++ if (sock->tid == isc_nm_tid() && sock->closehandle_cb == NULL) { + nmhandle_detach_cb(&handle FLARG_PASS); + } else { + isc__netievent_detach_t *event = +-- +1.8.3.1 + diff --git a/backport-CVE-2022-2795.patch b/backport-CVE-2022-2795.patch new file mode 100644 index 0000000000000000000000000000000000000000..c978c7390ea8165399373eb95a71f1c51aab057c --- /dev/null +++ b/backport-CVE-2022-2795.patch @@ -0,0 +1,60 @@ +From bf2ea6d8525bfd96a84dad221ba9e004adb710a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= +Date: Thu, 8 Sep 2022 11:11:30 +0200 +Subject: [PATCH] Bound the amount of work performed for delegations + +Limit the amount of database lookups that can be triggered in +fctx_getaddresses() (i.e. when determining the name server addresses to +query next) by setting a hard limit on the number of NS RRs processed +for any delegation encountered. Without any limit in place, named can +be forced to perform large amounts of database lookups per each query +received, which severely impacts resolver performance. + +The limit used (20) is an arbitrary value that is considered to be big +enough for any sane DNS delegation. + +(cherry picked from commit 3a44097fd6c6c260765b628cd1d2c9cb7efb0b2a) +--- + lib/dns/resolver.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c +index d2cf14bbc8b..73a0ee9f779 100644 +--- a/lib/dns/resolver.c ++++ b/lib/dns/resolver.c +@@ -195,6 +195,12 @@ + */ + #define NS_FAIL_LIMIT 4 + #define NS_RR_LIMIT 5 ++/* ++ * IP address lookups are performed for at most NS_PROCESSING_LIMIT NS RRs in ++ * any NS RRset encountered, to avoid excessive resource use while processing ++ * large delegations. ++ */ ++#define NS_PROCESSING_LIMIT 20 + + /* Number of hash buckets for zone counters */ + #ifndef RES_DOMAIN_BUCKETS +@@ -3711,6 +3717,7 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) { + bool need_alternate = false; + bool all_spilled = true; + unsigned int no_addresses = 0; ++ unsigned int ns_processed = 0; + + FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth); + +@@ -3902,6 +3909,11 @@ normal_nses: + + dns_rdata_reset(&rdata); + dns_rdata_freestruct(&ns); ++ ++ if (++ns_processed >= NS_PROCESSING_LIMIT) { ++ result = ISC_R_NOMORE; ++ break; ++ } + } + if (result != ISC_R_NOMORE) { + return (result); +-- +GitLab + diff --git a/backport-CVE-2022-2881.patch b/backport-CVE-2022-2881.patch new file mode 100644 index 0000000000000000000000000000000000000000..45bb83f5ff0abdeb14485d210cdc2f8ae507729a --- /dev/null +++ b/backport-CVE-2022-2881.patch @@ -0,0 +1,42 @@ +From 13333db69f9b9710a98c86f44276e01e95420fa0 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Tue, 16 Aug 2022 16:26:02 -0700 +Subject: [PATCH] compression buffer was not reused correctly + +when the compression buffer was reused for multiple statistics +requests, responses could grow beyond the correct size. this was +because the buffer was not cleared before reuse; compressed data +was still written to the beginning of the buffer, but then the size +of used region was increased by the amount written, rather than set +to the amount written. this caused responses to grow larger and +larger, potentially reading past the end of the allocated buffer. + +(cherry picked from commit 47e9fa981e56a7a232f3219fe8a40525c79d748b) +--- + lib/isc/httpd.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c +index 776455a..e55330b 100644 +--- a/lib/isc/httpd.c ++++ b/lib/isc/httpd.c +@@ -246,6 +246,8 @@ free_buffer(isc_mem_t *mctx, isc_buffer_t *buffer) { + if (r.length > 0) { + isc_mem_put(mctx, r.base, r.length); + } ++ ++ isc_buffer_initnull(buffer); + } + + static void +@@ -910,6 +912,7 @@ isc_httpd_compress(isc_httpd_t *httpd) { + if (result != ISC_R_SUCCESS) { + return (result); + } ++ isc_buffer_clear(&httpd->compbuffer); + isc_buffer_region(&httpd->compbuffer, &r); + + /* +-- +2.23.0 + diff --git a/backport-CVE-2022-2906.patch b/backport-CVE-2022-2906.patch new file mode 100644 index 0000000000000000000000000000000000000000..704cc528a9711e9151a32f2d67a477536e42af93 --- /dev/null +++ b/backport-CVE-2022-2906.patch @@ -0,0 +1,135 @@ +From 73df5c80538970ee1fbc4fe3348109bdc281e197 Mon Sep 17 00:00:00 2001 +From: Aram Sargsyan +Date: Thu, 18 Aug 2022 08:59:09 +0000 +Subject: [PATCH] Fix memory leaks in DH code + +When used with OpenSSL v3.0.0+, the `openssldh_compare()`, +`openssldh_paramcompare()`, and `openssldh_todns()` functions +fail to cleanup the used memory on some error paths. + +Use `DST_RET` instead of `return`, when there is memory to be +released before returning from the functions. + +(cherry picked from commit 73d6bbff4e1df583810126fe58eac39bb52bc0d9) +--- + lib/dns/openssldh_link.c | 45 +++++++++++++++++++++++----------------- + 1 file changed, 26 insertions(+), 19 deletions(-) + +diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c +index 72b8209..ece97ea 100644 +--- a/lib/dns/openssldh_link.c ++++ b/lib/dns/openssldh_link.c +@@ -68,6 +68,12 @@ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" + ++#define DST_RET(a) \ ++ { \ ++ ret = a; \ ++ goto err; \ ++ } ++ + static BIGNUM *bn2 = NULL, *bn768 = NULL, *bn1024 = NULL, *bn1536 = NULL; + + #if !HAVE_DH_GET0_KEY +@@ -180,7 +186,8 @@ openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv, + + static bool + openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) { +- DH *dh1, *dh2; ++ bool ret = true; ++ DH *dh1, *dh2; + const BIGNUM *pub_key1 = NULL, *pub_key2 = NULL; + const BIGNUM *priv_key1 = NULL, *priv_key2 = NULL; + const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL; +@@ -202,23 +209,24 @@ openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) { + if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0 || + BN_cmp(pub_key1, pub_key2) != 0) + { +- return (false); ++ DST_RET(false); + } + + if (priv_key1 != NULL || priv_key2 != NULL) { +- if (priv_key1 == NULL || priv_key2 == NULL) { +- return (false); +- } +- if (BN_cmp(priv_key1, priv_key2) != 0) { +- return (false); ++ if (priv_key1 == NULL || priv_key2 == NULL || ++ BN_cmp(priv_key1, priv_key2) != 0) { ++ DST_RET(false); + } + } +- return (true); ++ ++err: ++ return (ret); + } + + static bool + openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { +- DH *dh1, *dh2; ++ bool ret = true; ++ DH *dh1, *dh2; + const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL; + + dh1 = key1->keydata.dh; +@@ -234,9 +242,11 @@ openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { + DH_get0_pqg(dh2, &p2, NULL, &g2); + + if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0) { +- return (false); ++ DST_RET(false); + } +- return (true); ++ ++err: ++ return (ret); + } + + static int +@@ -386,7 +396,8 @@ uint16_fromregion(isc_region_t *region) { + + static isc_result_t + openssldh_todns(const dst_key_t *key, isc_buffer_t *data) { +- DH *dh; ++ isc_result_t ret = ISC_R_SUCCESS; ++ DH *dh; + const BIGNUM *pub_key = NULL, *p = NULL, *g = NULL; + isc_region_t r; + uint16_t dnslen, plen, glen, publen; +@@ -412,7 +423,7 @@ openssldh_todns(const dst_key_t *key, isc_buffer_t *data) { + publen = BN_num_bytes(pub_key); + dnslen = plen + glen + publen + 6; + if (r.length < (unsigned int)dnslen) { +- return (ISC_R_NOSPACE); ++ DST_RET(ISC_R_NOSPACE); + } + + uint16_toregion(plen, &r); +@@ -441,7 +452,8 @@ openssldh_todns(const dst_key_t *key, isc_buffer_t *data) { + + isc_buffer_add(data, dnslen); + +- return (ISC_R_SUCCESS); ++err: ++ return (ret); + } + + static isc_result_t +@@ -659,11 +671,6 @@ openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { + DH *dh = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL; + isc_mem_t *mctx; +-#define DST_RET(a) \ +- { \ +- ret = a; \ +- goto err; \ +- } + + UNUSED(pub); + mctx = key->mctx; +-- +2.23.0 + diff --git a/backport-CVE-2022-3080.patch b/backport-CVE-2022-3080.patch new file mode 100644 index 0000000000000000000000000000000000000000..b5bfb5669d1f4212411eeabb54ac655bf62cdf9d --- /dev/null +++ b/backport-CVE-2022-3080.patch @@ -0,0 +1,146 @@ +From 3f68e2ad838b3c12a725ccb1082a54b0e8b69562 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Fri, 2 Sep 2022 16:50:39 +0200 +Subject: [PATCH] Only refresh RRset once + +Don't attempt to resolve DNS responses for intermediate results. This +may create multiple refreshes and can cause a crash. + +One scenario is where for the query there is a CNAME and canonical +answer in cache that are both stale. This will trigger a refresh of +the RRsets because we encountered stale data and we prioritized it over +the lookup. It will trigger a refresh of both RRsets. When we start +recursing, it will detect a recursion loop because the recursion +parameters will eventually be the same. In 'dns_resolver_destroyfetch' +the sanity check fails, one of the callers did not get its event back +before trying to destroy the fetch. + +Move the call to 'query_refresh_rrset' to 'ns_query_done', so that it +is only called once per client request. + +Another scenario is where for the query there is a stale CNAME in the +cache that points to a record that is also in cache but not stale. This +will trigger a refresh of the RRset (because we encountered stale data +and we prioritized it over the lookup). + +We mark RRsets that we add to the message with +DNS_RDATASETATTR_STALE_ADDED to prevent adding a duplicate RRset when +a stale lookup and a normal lookup conflict with each other. However, +the other non-stale RRset when following a CNAME chain will be added to +the message without setting that attribute, because it is not stale. + +This is a variant of the bug in #2594. The fix covered the same crash +but for stale-answer-client-timeout > 0. + +Fix this by clearing all RRsets from the message before refreshing. +This requires the refresh to happen after the query is send back to +the client. + +(cherry picked from commit d939d2ecde5639d11acd6eac33a997b3e3c78b02) +--- + lib/ns/include/ns/query.h | 1 + + lib/ns/query.c | 42 ++++++++++++++++++++++++--------------- + 2 files changed, 27 insertions(+), 16 deletions(-) + +diff --git a/lib/ns/include/ns/query.h b/lib/ns/include/ns/query.h +index 142ef8c6c1d..be0dadd5099 100644 +--- a/lib/ns/include/ns/query.h ++++ b/lib/ns/include/ns/query.h +@@ -147,6 +147,7 @@ struct query_ctx { + bool authoritative; /* authoritative query? */ + bool want_restart; /* CNAME chain or other + * restart needed */ ++ bool refresh_rrset; /* stale RRset refresh needed */ + bool need_wildcardproof; /* wildcard proof needed */ + bool nxrewrite; /* negative answer from RPZ */ + bool findcoveringnsec; /* lookup covering NSEC */ +diff --git a/lib/ns/query.c b/lib/ns/query.c +index 5c2701eb718..98cfffe8c36 100644 +--- a/lib/ns/query.c ++++ b/lib/ns/query.c +@@ -5737,7 +5737,6 @@ query_lookup(query_ctx_t *qctx) { + bool dbfind_stale = false; + bool stale_timeout = false; + bool stale_found = false; +- bool refresh_rrset = false; + bool stale_refresh_window = false; + + CCTRACE(ISC_LOG_DEBUG(3), "query_lookup"); +@@ -5921,8 +5920,7 @@ query_lookup(query_ctx_t *qctx) { + "%s stale answer used, an attempt to " + "refresh the RRset will still be made", + namebuf); +- refresh_rrset = STALE(qctx->rdataset); +- qctx->client->nodetach = refresh_rrset; ++ qctx->refresh_rrset = STALE(qctx->rdataset); + } + } else { + /* +@@ -5960,17 +5958,6 @@ query_lookup(query_ctx_t *qctx) { + + result = query_gotanswer(qctx, result); + +- if (refresh_rrset) { +- /* +- * If we reached this point then it means that we have found a +- * stale RRset entry in cache and BIND is configured to allow +- * queries to be answered with stale data if no active RRset +- * is available, i.e. "stale-anwer-client-timeout 0". But, we +- * still need to refresh the RRset. +- */ +- query_refresh_rrset(qctx); +- } +- + cleanup: + return (result); + } +@@ -7760,11 +7747,14 @@ query_addanswer(query_ctx_t *qctx) { + + /* + * On normal lookups, clear any rdatasets that were added on a +- * lookup due to stale-answer-client-timeout. ++ * lookup due to stale-answer-client-timeout. Do not clear if we ++ * are going to refresh the RRset, because the stale contents are ++ * prioritized. + */ + if (QUERY_STALEOK(&qctx->client->query) && +- !QUERY_STALETIMEOUT(&qctx->client->query)) ++ !QUERY_STALETIMEOUT(&qctx->client->query) && !qctx->refresh_rrset) + { ++ CCTRACE(ISC_LOG_DEBUG(3), "query_clear_stale"); + query_clear_stale(qctx->client); + /* + * We can clear the attribute to prevent redundant clearing +@@ -11478,9 +11468,29 @@ ns_query_done(query_ctx_t *qctx) { + /* + * Client may have been detached after query_send(), so + * we test and store the flag state here, for safety. ++ * If we are refreshing the RRSet, we must not detach from the client ++ * in the query_send(), so we need to override the flag. + */ ++ if (qctx->refresh_rrset) { ++ qctx->client->nodetach = true; ++ } + nodetach = qctx->client->nodetach; + query_send(qctx->client); ++ ++ if (qctx->refresh_rrset) { ++ /* ++ * If we reached this point then it means that we have found a ++ * stale RRset entry in cache and BIND is configured to allow ++ * queries to be answered with stale data if no active RRset ++ * is available, i.e. "stale-anwer-client-timeout 0". But, we ++ * still need to refresh the RRset. To prevent adding duplicate ++ * RRsets, clear the RRsets from the message before doing the ++ * refresh. ++ */ ++ message_clearrdataset(qctx->client->message, 0); ++ query_refresh_rrset(qctx); ++ } ++ + if (!nodetach) { + qctx->detach_client = true; + } +-- +GitLab + diff --git a/backport-CVE-2022-3094-add-a-configuration-option-for-the-update-quota.patch b/backport-CVE-2022-3094-add-a-configuration-option-for-the-update-quota.patch new file mode 100644 index 0000000000000000000000000000000000000000..af9fa3521e5784ad2edc645303f4edf8ce1d9486 --- /dev/null +++ b/backport-CVE-2022-3094-add-a-configuration-option-for-the-update-quota.patch @@ -0,0 +1,267 @@ +From 7fe2204a2e8952bf892e4a70fea2ef5167e1f509 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Thu, 1 Sep 2022 16:22:46 -0700 +Subject: [PATCH] add a configuration option for the update quota + +add an "update-quota" option to configure the update quota. + +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/82185f4f80d2fa39a4569f6740cb360ffff8f5c4 +(cherry picked from commit f57758a7303ad0034ff2ff08eaaf2ef899630f19) +--- + bin/named/config.c | 1 + + bin/named/named.conf.rst | 9 +++++---- + bin/named/server.c | 1 + + bin/tests/system/checkconf/good.conf | 1 + + doc/arm/reference.rst | 7 ++++++- + doc/man/named.conf.5in | 9 +++++---- + doc/misc/master.zoneopt.rst | 2 +- + doc/misc/options | 1 + + doc/misc/options.active | 1 + + doc/misc/options.grammar.rst | 3 ++- + doc/misc/slave.zoneopt.rst | 2 +- + lib/isccfg/namedconf.c | 1 + + 12 files changed, 26 insertions(+), 12 deletions(-) + +diff --git a/bin/named/config.c b/bin/named/config.c +index 5fedee84d99..494147015ff 100644 +--- a/bin/named/config.c ++++ b/bin/named/config.c +@@ -130,6 +130,7 @@ options {\n\ + transfers-out 10;\n\ + transfers-per-ns 2;\n\ + trust-anchor-telemetry yes;\n\ ++ update-quota 100;\n\ + \n\ + /* view */\n\ + allow-new-zones no;\n\ +diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst +index 27eed5ca3e4..4c9f9a73704 100644 +--- a/bin/named/named.conf.rst ++++ b/bin/named/named.conf.rst +@@ -179,7 +179,7 @@ OPTIONS + answer-cookie boolean; + attach-cache string; + auth-nxdomain boolean; // default changed +- auto-dnssec ( allow | maintain | off ); ++ auto-dnssec ( allow | maintain | off );// deprecated + automatic-interface-scan boolean; + avoid-v4-udp-ports { portrange; ... }; + avoid-v6-udp-ports { portrange; ... }; +@@ -446,6 +446,7 @@ OPTIONS + trust-anchor-telemetry boolean; // experimental + try-tcp-refresh boolean; + update-check-ksk boolean; ++ update-quota integer; + use-alt-transfer-source boolean; + use-v4-udp-ports { portrange; ... }; + use-v6-udp-ports { portrange; ... }; +@@ -584,7 +585,7 @@ VIEW + * ) ] [ dscp integer ]; + attach-cache string; + auth-nxdomain boolean; // default changed +- auto-dnssec ( allow | maintain | off ); ++ auto-dnssec ( allow | maintain | off );// deprecated + cache-file quoted_string;// deprecated + catalog-zones { zone string [ default-masters [ port integer ] + [ dscp integer ] { ( remote-servers | ipv4_address [ port +@@ -859,7 +860,7 @@ VIEW + integer | * ) ] [ dscp integer ]; + alt-transfer-source-v6 ( ipv6_address | * ) [ port ( + integer | * ) ] [ dscp integer ]; +- auto-dnssec ( allow | maintain | off ); ++ auto-dnssec ( allow | maintain | off );// deprecated + check-dup-records ( fail | warn | ignore ); + check-integrity boolean; + check-mx ( fail | warn | ignore ); +@@ -977,7 +978,7 @@ ZONE + ] [ dscp integer ]; + alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer | + * ) ] [ dscp integer ]; +- auto-dnssec ( allow | maintain | off ); ++ auto-dnssec ( allow | maintain | off );// deprecated + check-dup-records ( fail | warn | ignore ); + check-integrity boolean; + check-mx ( fail | warn | ignore ); +diff --git a/bin/named/server.c b/bin/named/server.c +index 20443ff8a94..78a21d62a20 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -8542,6 +8542,7 @@ load_configuration(const char *filename, named_server_t *server, + configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota); + configure_server_quota(maps, "recursive-clients", + &server->sctx->recursionquota); ++ configure_server_quota(maps, "update-quota", &server->sctx->updquota); + + max = isc_quota_getmax(&server->sctx->recursionquota); + if (max > 1000) { +diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf +index b1f7059acf8..0ecdb68e95a 100644 +--- a/bin/tests/system/checkconf/good.conf ++++ b/bin/tests/system/checkconf/good.conf +@@ -75,6 +75,7 @@ options { + recursive-clients 3000; + serial-query-rate 100; + server-id none; ++ update-quota 200; + check-names primary warn; + check-names secondary ignore; + max-cache-size 20000000000000; +diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst +index 2603d602518..703663d0ba6 100644 +--- a/doc/arm/reference.rst ++++ b/doc/arm/reference.rst +@@ -3151,6 +3151,11 @@ system. + value as ``tcp-keepalive-timeout``. This value can be updated at + runtime by using ``rndc tcp-timeouts``. + ++``update-quota`` ++ This is the maximum number of simultaneous DNS UPDATE messages that ++ the server will accept for updating local authoritiative zones or ++ forwarding to a primary server. The default is ``100``. ++ + .. _intervals: + + Periodic Task Intervals +@@ -6840,7 +6845,7 @@ Name Server Statistics Counters + ``UpdateQuota`` + This indicates the number of times a dynamic update or update + forwarding request was rejected because the number of pending +- requests exceeded the update quota. ++ requests exceeded ``update-quota``. + + ``RateDropped`` + This indicates the number of responses dropped due to rate limits. +diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in +index 4c46f475929..c87afa28813 100644 +--- a/doc/man/named.conf.5in ++++ b/doc/man/named.conf.5in +@@ -231,7 +231,7 @@ options { + answer\-cookie boolean; + attach\-cache string; + auth\-nxdomain boolean; // default changed +- auto\-dnssec ( allow | maintain | off ); ++ auto\-dnssec ( allow | maintain | off );// deprecated + automatic\-interface\-scan boolean; + avoid\-v4\-udp\-ports { portrange; ... }; + avoid\-v6\-udp\-ports { portrange; ... }; +@@ -498,6 +498,7 @@ options { + trust\-anchor\-telemetry boolean; // experimental + try\-tcp\-refresh boolean; + update\-check\-ksk boolean; ++ update\-quota integer; + use\-alt\-transfer\-source boolean; + use\-v4\-udp\-ports { portrange; ... }; + use\-v6\-udp\-ports { portrange; ... }; +@@ -668,7 +669,7 @@ view string [ class ] { + * ) ] [ dscp integer ]; + attach\-cache string; + auth\-nxdomain boolean; // default changed +- auto\-dnssec ( allow | maintain | off ); ++ auto\-dnssec ( allow | maintain | off );// deprecated + cache\-file quoted_string;// deprecated + catalog\-zones { zone string [ default\-masters [ port integer ] + [ dscp integer ] { ( remote\-servers | ipv4_address [ port +@@ -943,7 +944,7 @@ view string [ class ] { + integer | * ) ] [ dscp integer ]; + alt\-transfer\-source\-v6 ( ipv6_address | * ) [ port ( + integer | * ) ] [ dscp integer ]; +- auto\-dnssec ( allow | maintain | off ); ++ auto\-dnssec ( allow | maintain | off );// deprecated + check\-dup\-records ( fail | warn | ignore ); + check\-integrity boolean; + check\-mx ( fail | warn | ignore ); +@@ -1065,7 +1066,7 @@ zone string [ class ] { + ] [ dscp integer ]; + alt\-transfer\-source\-v6 ( ipv6_address | * ) [ port ( integer | + * ) ] [ dscp integer ]; +- auto\-dnssec ( allow | maintain | off ); ++ auto\-dnssec ( allow | maintain | off );// deprecated + check\-dup\-records ( fail | warn | ignore ); + check\-integrity boolean; + check\-mx ( fail | warn | ignore ); +diff --git a/doc/misc/master.zoneopt.rst b/doc/misc/master.zoneopt.rst +index 8fc7e1b4f0d..346d59813ee 100644 +--- a/doc/misc/master.zoneopt.rst ++++ b/doc/misc/master.zoneopt.rst +@@ -20,7 +20,7 @@ + also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ]; ... }; + alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; + alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; +- auto-dnssec ( allow | maintain | off ); ++ auto-dnssec ( allow | maintain | off ); // deprecated + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); +diff --git a/doc/misc/options b/doc/misc/options +index f57399499a5..0dbcf101e1c 100644 +--- a/doc/misc/options ++++ b/doc/misc/options +@@ -404,6 +404,7 @@ options { + trust-anchor-telemetry ; // experimental + try-tcp-refresh ; + update-check-ksk ; ++ update-quota ; + use-alt-transfer-source ; + use-id-pool ; // ancient + use-ixfr ; // obsolete +diff --git a/doc/misc/options.active b/doc/misc/options.active +index 5fc1ab29f42..eb75a86eae9 100644 +--- a/doc/misc/options.active ++++ b/doc/misc/options.active +@@ -363,6 +363,7 @@ options { + trust-anchor-telemetry ; // experimental + try-tcp-refresh ; + update-check-ksk ; ++ update-quota ; + use-alt-transfer-source ; + use-v4-udp-ports { ; ... }; + use-v6-udp-ports { ; ... }; +diff --git a/doc/misc/options.grammar.rst b/doc/misc/options.grammar.rst +index 438072c95c4..beef35341a1 100644 +--- a/doc/misc/options.grammar.rst ++++ b/doc/misc/options.grammar.rst +@@ -33,7 +33,7 @@ + answer-cookie ; + attach-cache ; + auth-nxdomain ; // default changed +- auto-dnssec ( allow | maintain | off ); ++ auto-dnssec ( allow | maintain | off ); // deprecated + automatic-interface-scan ; + avoid-v4-udp-ports { ; ... }; + avoid-v6-udp-ports { ; ... }; +@@ -300,6 +300,7 @@ + trust-anchor-telemetry ; // experimental + try-tcp-refresh ; + update-check-ksk ; ++ update-quota ; + use-alt-transfer-source ; + use-v4-udp-ports { ; ... }; + use-v6-udp-ports { ; ... }; +diff --git a/doc/misc/slave.zoneopt.rst b/doc/misc/slave.zoneopt.rst +index cc72dcbf677..468a7f4d9a3 100644 +--- a/doc/misc/slave.zoneopt.rst ++++ b/doc/misc/slave.zoneopt.rst +@@ -21,7 +21,7 @@ + also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ]; ... }; + alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; + alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; +- auto-dnssec ( allow | maintain | off ); ++ auto-dnssec ( allow | maintain | off ); // deprecated + check-names ( fail | warn | ignore ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); +diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c +index 45de0196bf4..6e63d86816e 100644 +--- a/lib/isccfg/namedconf.c ++++ b/lib/isccfg/namedconf.c +@@ -1267,6 +1267,7 @@ static cfg_clausedef_t options_clauses[] = { + { "transfers-out", &cfg_type_uint32, 0 }, + { "transfers-per-ns", &cfg_type_uint32, 0 }, + { "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT }, ++ { "update-quota", &cfg_type_uint32, 0 }, + { "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT }, + { "use-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, + { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, +-- +GitLab diff --git a/backport-CVE-2022-3094-add-an-update-quota.patch b/backport-CVE-2022-3094-add-an-update-quota.patch new file mode 100644 index 0000000000000000000000000000000000000000..f004366a010fac7e983b845d38263c3e3618da4e --- /dev/null +++ b/backport-CVE-2022-3094-add-an-update-quota.patch @@ -0,0 +1,243 @@ +From 35711a29e5002fce5fb56af163c5a3db81b33bed Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Thu, 1 Sep 2022 16:05:04 -0700 +Subject: [PATCH] add an update quota + +limit the number of simultaneous DNS UPDATE events that can be +processed by adding a quota for update and update forwarding. +this quota currently, arbitrarily, defaults to 100. + +also add a statistics counter to record when the update quota +has been exceeded. + +Conflict: NA +Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/82185f4f80d2fa39a4569f6740cb360ffff8f5c4 +(cherry picked from commit 7c47254a140c3e9cf383cda73c7b6a55c4782826) +--- + bin/named/bind9.xsl | 4 +++- + bin/named/bind9.xsl.h | 6 +++++- + bin/named/statschannel.c | 5 +++-- + doc/arm/reference.rst | 5 +++++ + lib/ns/include/ns/server.h | 1 + + lib/ns/include/ns/stats.h | 4 +++- + lib/ns/server.c | 2 ++ + lib/ns/update.c | 38 +++++++++++++++++++++++++++++++++++++- + 8 files changed, 59 insertions(+), 6 deletions(-) + +diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl +index 5078115..194625b 100644 +--- a/bin/named/bind9.xsl ++++ b/bin/named/bind9.xsl +@@ -12,7 +12,9 @@ + + + +- ++ ++ ++ + + + +diff --git a/bin/named/bind9.xsl.h b/bin/named/bind9.xsl.h +index e30f7f5..b182742 100644 +--- a/bin/named/bind9.xsl.h ++++ b/bin/named/bind9.xsl.h +@@ -20,7 +20,11 @@ static char xslmsg[] = + "\n" + " \n" +- " \n" ++ " \n" ++ " \n" ++ " \n" + " \n" + " \n" + "