aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo <thinkabit.ukim@gmail.com>2020-05-21 02:28:49 -0300
committerLeo <thinkabit.ukim@gmail.com>2020-05-21 02:28:49 -0300
commit36e8c099cca7330e59a5debe18132371200d1a3c (patch)
treebf95c2575ea8a32fdff0e3ba4071012db83abcd6
parent0736c451214b8c97e150c0af44ac70695a552b0f (diff)
downloadaports-36e8c099cca7330e59a5debe18132371200d1a3c.tar.gz
aports-36e8c099cca7330e59a5debe18132371200d1a3c.tar.bz2
aports-36e8c099cca7330e59a5debe18132371200d1a3c.tar.xz
community/knot-resolver: fix CVE-2020-12667
See #11565
-rw-r--r--community/knot-resolver/APKBUILD4
-rw-r--r--community/knot-resolver/CVE-2020-12667.patch119
2 files changed, 122 insertions, 1 deletions
diff --git a/community/knot-resolver/APKBUILD b/community/knot-resolver/APKBUILD
index 0e113fdcdd..7b7d14ed16 100644
--- a/community/knot-resolver/APKBUILD
+++ b/community/knot-resolver/APKBUILD
@@ -3,7 +3,7 @@
# Maintainer: Jakub Jirutka <jakub@jirutka.cz>
pkgname=knot-resolver
pkgver=4.3.0
-pkgrel=2
+pkgrel=3
pkgdesc="Minimalistic caching DNS resolver implementation"
url="https://www.knot-resolver.cz/"
arch="all !s390x" # limited by luajit
@@ -38,6 +38,8 @@ source="https://secure.nic.cz/files/$pkgname/$pkgname-$pkgver.tar.xz
builddir="$srcdir/$pkgname-$pkgver"
# secfixes:
+# 4.3.0-r3:
+# - CVE-2020-12667
# 4.3.0-r0:
# - CVE-2019-19331
# 4.1.0-r0:
diff --git a/community/knot-resolver/CVE-2020-12667.patch b/community/knot-resolver/CVE-2020-12667.patch
new file mode 100644
index 0000000000..045740e5f8
--- /dev/null
+++ b/community/knot-resolver/CVE-2020-12667.patch
@@ -0,0 +1,119 @@
+diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua
+index c68ece0..1d783f6 100644
+--- a/daemon/lua/kres-gen.lua
++++ b/daemon/lua/kres-gen.lua
+@@ -189,6 +189,8 @@ struct kr_request {
+ int vars_ref;
+ knot_mm_t pool;
+ unsigned int uid;
++ unsigned int count_no_nsaddr;
++ unsigned int count_fail_row;
+ };
+ enum kr_rank {KR_RANK_INITIAL, KR_RANK_OMIT, KR_RANK_TRY, KR_RANK_INDET = 4, KR_RANK_BOGUS, KR_RANK_MISMATCH, KR_RANK_MISSING, KR_RANK_INSECURE, KR_RANK_AUTH = 16, KR_RANK_SECURE = 32};
+ struct kr_cdb_stats {
+diff --git a/lib/defines.h b/lib/defines.h
+index f49e974..296d0e2 100644
+--- a/lib/defines.h
++++ b/lib/defines.h
+@@ -64,6 +64,8 @@ static inline int KR_COLD kr_error(int x) {
+ #define KR_CNAME_CHAIN_LIMIT 13 /* Built-in maximum CNAME chain length */
+ #define KR_TIMEOUT_LIMIT 4 /* Maximum number of retries after timeout. */
+ #define KR_QUERY_NSRETRY_LIMIT 4 /* Maximum number of retries per query. */
++#define KR_COUNT_NO_NSADDR_LIMIT 5
++#define KR_CONSUME_FAIL_ROW_LIMIT 3 /* Maximum number of KR_STATE_FAIL in a row. */
+
+ /*
+ * Defines.
+diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c
+index bc3412e..93f6b20 100644
+--- a/lib/layer/iterate.c
++++ b/lib/layer/iterate.c
+@@ -860,7 +860,8 @@ static int process_stub(knot_pkt_t *pkt, struct kr_request *req)
+ }
+
+
+-/** Error handling, RFC1034 5.3.3, 4d. */
++/** Error handling, RFC1034 5.3.3, 4d.
++ * NOTE: returing this does not prevent further queries (by itself). */
+ static int resolve_error(knot_pkt_t *pkt, struct kr_request *req)
+ {
+ return KR_STATE_FAIL;
+diff --git a/lib/resolve.c b/lib/resolve.c
+index 8e365d7..96ee02b 100644
+--- a/lib/resolve.c
++++ b/lib/resolve.c
+@@ -311,10 +311,10 @@ static int ns_fetch_cut(struct kr_query *qry, const knot_dname_t *requested_name
+ return KR_STATE_PRODUCE;
+ }
+
+-static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param)
++static int ns_resolve_addr(struct kr_query *qry, struct kr_request *req)
+ {
+- struct kr_rplan *rplan = &param->rplan;
+- struct kr_context *ctx = param->ctx;
++ struct kr_rplan *rplan = &req->rplan;
++ struct kr_context *ctx = req->ctx;
+
+
+ /* Start NS queries from root, to avoid certain cases
+@@ -345,7 +345,9 @@ static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param)
+ return kr_error(EAGAIN);
+ }
+ /* No IPv4 nor IPv6, flag server as unusable. */
+- VERBOSE_MSG(qry, "=> unresolvable NS address, bailing out\n");
++ ++req->count_no_nsaddr;
++ VERBOSE_MSG(qry, "=> unresolvable NS address, bailing out (counter: %u)\n",
++ req->count_no_nsaddr);
+ qry->ns.reputation |= KR_NS_NOIP4 | KR_NS_NOIP6;
+ kr_nsrep_update_rep(&qry->ns, qry->ns.reputation, ctx->cache_rep);
+ invalidate_ns(rplan, qry);
+@@ -948,6 +950,23 @@ int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, k
+ qry->flags.RESOLVED = false;
+ }
+
++ /* For multiple errors in a row; invalidate_ns() is not enough. */
++ if (!qry->flags.CACHED) {
++ if (request->state & KR_STATE_FAIL) {
++ if (++request->count_fail_row > KR_CONSUME_FAIL_ROW_LIMIT) {
++ if (VERBOSE_STATUS || kr_log_rtrace_enabled(request)) {
++ kr_log_req(request, 0, 2, "resl",
++ "=> too many failures in a row, "
++ "bail out (mitigation for NXNSAttack "
++ "CVE-2020-12667)");
++ }
++ return KR_STATE_FAIL;
++ }
++ } else {
++ request->count_fail_row = 0;
++ }
++ }
++
+ /* Pop query if resolved. */
+ if (request->state == KR_STATE_YIELD) {
+ return KR_STATE_PRODUCE; /* Requery */
+@@ -1407,6 +1426,11 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
+
+ ns_election:
+
++ if (unlikely(request->count_no_nsaddr >= KR_COUNT_NO_NSADDR_LIMIT)) {
++ VERBOSE_MSG(qry, "=> too many unresolvable NSs, bail out "
++ "(mitigation for NXNSAttack CVE-2020-12667)\n");
++ return KR_STATE_FAIL;
++ }
+ /* If the query has already selected a NS and is waiting for IPv4/IPv6 record,
+ * elect best address only, otherwise elect a completely new NS.
+ */
+diff --git a/lib/resolve.h b/lib/resolve.h
+index b49aa8d..e36c944 100644
+--- a/lib/resolve.h
++++ b/lib/resolve.h
+@@ -234,6 +234,8 @@ struct kr_request {
+ int vars_ref; /**< Reference to per-request variable table. LUA_NOREF if not set. */
+ knot_mm_t pool;
+ unsigned int uid; /** for logging purposes only */
++ unsigned int count_no_nsaddr;
++ unsigned int count_fail_row;
+ };
+
+ /** Initializer for an array of *_selected. */
+