knot-resolver: Update to 6.4.1

Message ID 20260725163957.3363172-1-matthias.fischer@ipfire.org
State Staged
Commit c0cc5337db0aeb60c62d5990058216226061233e
Headers
Series knot-resolver: Update to 6.4.1 |

Commit Message

Matthias Fischer 25 Jul 2026, 4:39 p.m. UTC
- Commented some unnecessary lines in rootfile.
- Removed no longer needed patchfile.

For details see:
https://www.knot-resolver.cz/2026-07-22-knot-resolver-6.4.1.html

"Security

    DNS-over-QUIC (DoQ) had severe issues, allowing even RCE
    Many people reported (some of) these issues to us.

    DNSSEC correctness issues, acting mainly through the
    aggressive cache: * dealing with Labels field in RRSIGs being
    smaller than the signer's * dealing with NSEC's next-name
    pointing outside of the zone

Special thanks to Qifan Zhang from Palo Alto Networks.

Improvements

    docker: upgrade to Debian 13 (!1856)
    update IANA's certificate for root trust anchor bootstrapping (!1845)

Bugfixes

    /local-data/addresses*: make multiple addresses work (#808, #954)
    views: fix protocol-based matching for DoQ"

Signed-off-by: Matthias Fischer <matthias.fischer@ipfire.org>
---
 config/rootfiles/common/knot-resolver      |  18 +-
 lfs/knot-resolver                          |   7 +-
 src/patches/knot-resolver-6.4.0-1854.patch | 251 ---------------------
 3 files changed, 12 insertions(+), 264 deletions(-)
 delete mode 100644 src/patches/knot-resolver-6.4.0-1854.patch
  

Patch

diff --git a/config/rootfiles/common/knot-resolver b/config/rootfiles/common/knot-resolver
index 9d5a83460..80d82d34b 100644
--- a/config/rootfiles/common/knot-resolver
+++ b/config/rootfiles/common/knot-resolver
@@ -43,7 +43,7 @@  usr/lib/knot-resolver/distro-preconfig.lua
 usr/lib/knot-resolver/kluautil.lua
 usr/lib/knot-resolver/kres-gen.lua
 usr/lib/knot-resolver/kres.lua
-usr/lib/knot-resolver/kres_modules
+#usr/lib/knot-resolver/kres_modules
 usr/lib/knot-resolver/kres_modules/bogus_log.so
 #usr/lib/knot-resolver/kres_modules/daf
 usr/lib/knot-resolver/kres_modules/daf.lua
@@ -109,13 +109,13 @@  usr/lib/knot-resolver/zonefile.lua
 usr/lib/libkres.so.9
 #usr/lib/pkgconfig/libkres.pc
 usr/lib/python3.10/site-packages/knot_resolver
-usr/lib/python3.10/site-packages/knot_resolver-6.4.0-py3.10.egg-info
-usr/lib/python3.10/site-packages/knot_resolver-6.4.0-py3.10.egg-info/PKG-INFO
-usr/lib/python3.10/site-packages/knot_resolver-6.4.0-py3.10.egg-info/SOURCES.txt
-usr/lib/python3.10/site-packages/knot_resolver-6.4.0-py3.10.egg-info/dependency_links.txt
-usr/lib/python3.10/site-packages/knot_resolver-6.4.0-py3.10.egg-info/entry_points.txt
-usr/lib/python3.10/site-packages/knot_resolver-6.4.0-py3.10.egg-info/requires.txt
-usr/lib/python3.10/site-packages/knot_resolver-6.4.0-py3.10.egg-info/top_level.txt
+#usr/lib/python3.10/site-packages/knot_resolver-6.4.1-py3.10.egg-info
+usr/lib/python3.10/site-packages/knot_resolver-6.4.1-py3.10.egg-info/PKG-INFO
+usr/lib/python3.10/site-packages/knot_resolver-6.4.1-py3.10.egg-info/SOURCES.txt
+usr/lib/python3.10/site-packages/knot_resolver-6.4.1-py3.10.egg-info/dependency_links.txt
+usr/lib/python3.10/site-packages/knot_resolver-6.4.1-py3.10.egg-info/entry_points.txt
+usr/lib/python3.10/site-packages/knot_resolver-6.4.1-py3.10.egg-info/requires.txt
+usr/lib/python3.10/site-packages/knot_resolver-6.4.1-py3.10.egg-info/top_level.txt
 #usr/lib/python3.10/site-packages/knot_resolver/__init__.py
 #usr/lib/python3.10/site-packages/knot_resolver/client
 #usr/lib/python3.10/site-packages/knot_resolver/client/__init__.py
@@ -269,7 +269,7 @@  usr/sbin/kresd
 #usr/share/man/man8/kresctl.8
 #usr/share/man/man8/kresd.8
 var/cache/knot-resolver
-var/lib/knot-resolver
+#var/lib/knot-resolver
 var/lib/knot-resolver/leases.db
 var/lib/knot-resolver/root.keys
 var/lib/knot-resolver/zones
diff --git a/lfs/knot-resolver b/lfs/knot-resolver
index 3d49a3bc7..daeea4159 100644
--- a/lfs/knot-resolver
+++ b/lfs/knot-resolver
@@ -1,7 +1,7 @@ 
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2007-2024  IPFire Team  <info@ipfire.org>                     #
+# Copyright (C) 2007-2026  IPFire Team  <info@ipfire.org>                     #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
@@ -24,7 +24,7 @@ 
 
 include Config
 
-VER        = 6.4.0
+VER        = 6.4.1
 
 THISAPP    = knot-resolver-$(VER)
 DL_FILE    = $(THISAPP).tar.xz
@@ -40,7 +40,7 @@  objects = $(DL_FILE)
 
 $(DL_FILE) = $(DL_FROM)/$(DL_FILE)
 
-$(DL_FILE)_BLAKE2 = dbe67ea0ad3484aba912406f960568c2c92630910863eaf33aeba9b15dce0279810a7df8844aa7d5617f1055de957445042a80c7479972f185bbfff457e96e1d
+$(DL_FILE)_BLAKE2 = cd755323a3e6decf36bacf2508f8f3cf02a4538d1909e17689d1e2d7821e8b9d8e463a1426d6ea765bbfd7cc9aa11894fe8a0ad5e8b51ad9f970c44735fb3a3e
 
 install : $(TARGET)
 
@@ -70,7 +70,6 @@  $(subst %,%_BLAKE2,$(objects)) :
 $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
 	@$(PREBUILD)
 	@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
-	cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/knot-resolver-6.4.0-1854.patch
 	cd $(DIR_APP) && meson setup \
 		--prefix=/usr \
 		-Duser=knot-resolver \
diff --git a/src/patches/knot-resolver-6.4.0-1854.patch b/src/patches/knot-resolver-6.4.0-1854.patch
deleted file mode 100644
index 94267c2a4..000000000
--- a/src/patches/knot-resolver-6.4.0-1854.patch
+++ /dev/null
@@ -1,251 +0,0 @@ 
-diff --git a/lib/cache/cdb_api.h b/lib/cache/cdb_api.h
-index 9e8a34d58..b589b564a 100644
---- a/lib/cache/cdb_api.h
-+++ b/lib/cache/cdb_api.h
-@@ -65,11 +65,15 @@ struct kr_cdb_api {
- 	 * \return error code - accepting RW transactions can fail with LMDB.
- 	 */
- 	int (*commit)(kr_cdb_pt db, struct kr_cdb_stats *stat, bool accept_rw, bool reset_ro);
-+	/** Run before a row of operations to ensure they happen in a single RW transaction,
-+	 *   at least in case of successes. */
-+	int (*txn_open_rw)(kr_cdb_pt db, struct kr_cdb_stats *stat/*unused*/);
- 
- 	/* Data access */
- 
- 	int (*read)(kr_cdb_pt db, struct kr_cdb_stats *stat,
- 			const knot_db_val_t *key, knot_db_val_t *val, int maxcount);
-+	/* TODO: the behavior of write() around transactions is a bit complex. */
- 	int (*write)(kr_cdb_pt db, struct kr_cdb_stats *stat, const knot_db_val_t *key,
- 			knot_db_val_t *val, int maxcount);
- 
-@@ -111,13 +115,19 @@ struct kr_cdb_api {
- 	int (*check_health)(kr_cdb_pt db, struct kr_cdb_stats *stat);
- 
- 
--	/** Start iterating; return the first *val with *key.
-+	/** Start iterating: get the first *val with *key + return error code.
- 	 *
--	 * This only makes sense if !is_cache.
--	 * TODO: it only works inside RO transactions for now.
-+	 * - in cache: ensures a RO transaction (and commits the RW txn if any)
-+	 * - in ruledb: transaction is preserved if exists, otherwise RO txn gets opened
- 	 */
- 	int (*it_first)(kr_cdb_pt db, struct kr_cdb_stats *stat,
- 			const knot_db_val_t *key, knot_db_val_t *val);
--	/** Advance to the next *val with the same key. */
-+	/** Advance to the next *val with the same key.  Return error code. */
- 	int (*it_next)(kr_cdb_pt db, struct kr_cdb_stats *stat, knot_db_val_t *val);
-+	/** Delete the current *val + return error code.
-+	 *
-+	 * You can it_next() to continue.
-+	 * This assumed that you got it_first() in a RW txn.
-+	 */
-+	int (*it_del)(kr_cdb_pt db, struct kr_cdb_stats *stat);
- };
-diff --git a/lib/cache/cdb_lmdb.c b/lib/cache/cdb_lmdb.c
-index 0319b5cbb..6221c9492 100644
---- a/lib/cache/cdb_lmdb.c
-+++ b/lib/cache/cdb_lmdb.c
-@@ -38,12 +38,13 @@ struct lmdb_env
- 	 *
- 	 * - only one of (ro,rw) may be active at once
- 	 * - non-NULL .ro may be active or reset
--	 * - non-NULL .rw is always active
-+	 * - ro_curs can survive an RW transaction and renewed later in an RO txn
-+	 * - non-NULL .rw is always active, non-NULL rw_curs is always active
- 	 */
- 	struct {
- 		bool ro_active, ro_curs_active;
- 		MDB_txn *ro, *rw;
--		MDB_cursor *ro_curs;
-+		MDB_cursor *ro_curs, *rw_curs;
- 	} txn;
- 
- 	bool is_cache; /**< cache vs. rules; from struct kr_cdb_opts::is_cache */
-@@ -236,6 +237,7 @@ static int cdb_commit(kr_cdb_pt db, struct kr_cdb_stats *stats, bool accept_rw,
- 			mdb_txn_abort(env->txn.rw);
- 		}
- 		env->txn.rw = NULL; /* the transaction got freed even in case of errors */
-+		env->txn.rw_curs = NULL; /* auto-closed with txn if existed */
- 	} else if (reset_ro && env->txn.ro && env->txn.ro_active) {
- 		mdb_txn_reset(env->txn.ro);
- 		env->txn.ro_active = false;
-@@ -244,21 +246,39 @@ static int cdb_commit(kr_cdb_pt db, struct kr_cdb_stats *stats, bool accept_rw,
- 	return ret;
- }
- 
--/** Obtain a read-only cursor (and a read-only transaction).
-- * TODO: allow RW transaction (for ruledb iterator) */
-+static int cdb_txn_open_rw(kr_cdb_pt db, struct kr_cdb_stats *stat/*unused*/)
-+{
-+	struct lmdb_env *env = db2env(db);
-+	MDB_txn *txn = NULL;
-+	return txn_get(env, &txn, false);
-+}
-+
-+/** Obtain a cursor (and a transaction).
-+ *
-+ * - for cache these are read only
-+ * - for policy the RW transaction gets preserved if open */
- static int txn_curs_get(struct lmdb_env *env, MDB_cursor **curs, struct kr_cdb_stats *stats)
- {
- 	if (kr_fails_assert(env && curs))
- 		return kr_error(EINVAL);
- 	if (env->txn.ro_curs_active)
--		goto success;
--	/* Only in a read-only txn; TODO: it's a bit messy/coupled
--	 * At least for rules we don't do the auto-commit feature. */
--	if (env->txn.rw) {
--		if (!env->is_cache) return kr_error(EINPROGRESS);
-+		goto success_ro;
-+	/* Only in a read-only txn if for cache; TODO: it's a bit messy/coupled */
-+	if (env->txn.rw && env->is_cache) {
- 		int ret = cdb_commit(env2db(env), stats, true, false);
- 		if (ret) return ret;
- 	}
-+	if (env->txn.rw && !env->is_cache) {
-+		if (!env->txn.rw_curs) {
-+			MDB_txn *txn = env->txn.rw;
-+			int ret = mdb_cursor_open(txn, env->dbi, &env->txn.rw_curs);
-+			if (ret) return lmdb_error(env, ret);
-+		}
-+		if (kr_fails_assert(env->txn.rw_curs))
-+			return kr_error(EINVAL);
-+		*curs = env->txn.rw_curs;
-+		return kr_ok();
-+	}
- 	MDB_txn *txn = NULL;
- 	int ret = txn_get(env, &txn, true);
- 	if (ret) return ret;
-@@ -270,7 +290,7 @@ static int txn_curs_get(struct lmdb_env *env, MDB_cursor **curs, struct kr_cdb_s
- 	}
- 	if (ret) return lmdb_error(env, ret);
- 	env->txn.ro_curs_active = true;
--success:
-+success_ro:
- 	kr_assert(env->txn.ro_curs_active && env->txn.ro && env->txn.ro_active
- 			 && !env->txn.rw);
- 	*curs = env->txn.ro_curs;
-@@ -301,6 +321,7 @@ static void txn_abort(struct lmdb_env *env)
- 	if (env->txn.rw) {
- 		mdb_txn_abort(env->txn.rw);
- 		env->txn.rw = NULL; /* the transaction got freed even in case of errors */
-+		env->txn.rw_curs = NULL; /* auto-closed with txn if existed */
- 	}
- }
- 
-@@ -940,7 +961,7 @@ static int cdb_it_next(kr_cdb_pt db, struct kr_cdb_stats *stats, knot_db_val_t *
- 	if (kr_fails_assert(db && val))
- 		return kr_error(EINVAL);
- 	struct lmdb_env *env = db2env(db);
--	if (kr_fails_assert(!env->is_cache && env->txn.ro_curs_active))
-+	if (kr_fails_assert(!env->is_cache && (env->txn.ro_curs_active || env->txn.rw_curs)))
- 		return kr_error(EINVAL);
- 
- 	MDB_cursor *curs = NULL;
-@@ -952,19 +973,35 @@ static int cdb_it_next(kr_cdb_pt db, struct kr_cdb_stats *stats, knot_db_val_t *
- 	*val = val_mdb2knot(val2_m);
- 	return kr_ok();
- }
-+static int cdb_it_del(kr_cdb_pt db, struct kr_cdb_stats *stats)
-+{
-+	if (kr_fails_assert(db))
-+		return kr_error(EINVAL);
-+	struct lmdb_env *env = db2env(db);
-+	if (kr_fails_assert(!env->is_cache && env->txn.rw_curs))
-+		return kr_error(EINVAL);
-+
-+	MDB_cursor *curs = NULL;
-+	int ret = txn_curs_get(env, &curs, stats);
-+	if (ret) return ret;
-+	ret = mdb_cursor_del(curs, 0);
-+	if (ret) return lmdb_error(env, ret);
-+	return kr_ok();
-+}
- 
- 
- const struct kr_cdb_api *kr_cdb_lmdb(void)
- {
- 	static const struct kr_cdb_api api = {
- 		"lmdb",
--		cdb_init, cdb_deinit, cdb_count, cdb_clear, cdb_commit,
-+		cdb_init, cdb_deinit, cdb_count, cdb_clear,
-+		cdb_commit, cdb_txn_open_rw,
- 		cdb_readv, cdb_writev, cdb_remove,
- 		cdb_match,
- 		cdb_read_leq, cdb_read_less,
- 		cdb_usage_percent, cdb_get_maxsize,
- 		cdb_check_health,
--		cdb_it_first, cdb_it_next,
-+		cdb_it_first, cdb_it_next, cdb_it_del,
- 	};
- 	return &api;
- }
-diff --git a/lib/rules/api.c b/lib/rules/api.c
-index d9dbfcf1f..4c213d6f5 100644
---- a/lib/rules/api.c
-+++ b/lib/rules/api.c
-@@ -663,21 +663,27 @@ int kr_rule_local_data_merge(const knot_rrset_t *rrs, const kr_rule_tags_t tags,
- 	uint8_t key_data[KEY_MAXLEN];
- 	knot_db_val_t key = local_data_key(rrs, key_data, RULESET_DEFAULT);
- 	knot_db_val_t val;
-+	int ret = ruledb_op(txn_open_rw);
-+	if (ret)
-+		return kr_error(ret);
- 	// Transaction: we assume that we're in a RW transaction already,
- 	// so that here we already "have a lock" on the last version.
--	// FIXME: iterate over multiple tags, once iterator supports RW TXN
--	int ret = ruledb_op(read, &key, &val, 1);
-+	// Multiple variants are possible, with different tags.
-+	for (ret = ruledb_op(it_first, &key, &val); ret == 0; ret = ruledb_op(it_next, &val)) {
-+		// we're looking for the same tag-set
-+		kr_rule_tags_t tags_old;
-+		if (deserialize_fails_assert(&val, &tags_old) || tags_old != tags)
-+			continue;
-+		kr_rule_opts_t opts_old;
-+		if (deserialize_fails_assert(&val, &opts_old))
-+			continue;
-+		break;
-+	}
- 	if (abs(ret) == abs(ENOENT))
- 		goto fallback;
- 	if (ret)
- 		return kr_error(ret);
--	// check tags
--	kr_rule_tags_t tags_old;
--	if (deserialize_fails_assert(&val, &tags_old) || tags_old != tags)
--		goto fallback;
--	kr_rule_opts_t opts_old;
--	if (deserialize_fails_assert(&val, &opts_old))
--		goto fallback;
-+
- 	// merge TTLs
- 	uint32_t ttl;
- 	if (deserialize_fails_assert(&val, &ttl))
-@@ -700,6 +706,10 @@ int kr_rule_local_data_merge(const knot_rrset_t *rrs, const kr_rule_tags_t tags,
- 		mm_ctx_delete(mm);
- 		return kr_error(ret);
- 	}
-+	// ATM ruledb does not overwrite, so we `remove` before `write`.
-+	ret = ruledb_op(it_del);
-+	if (ret)
-+		return kr_error(ret);
- 	// everything is ready to insert the merged RRset
- 	ret = local_data_ins(key, &rrs_new, NULL, tags, opts);
- 	mm_ctx_delete(mm);
-diff --git a/lib/rules/api.h b/lib/rules/api.h
-index feea98e09..c3af5901b 100644
---- a/lib/rules/api.h
-+++ b/lib/rules/api.h
-@@ -144,10 +144,8 @@ const uint32_t KR_RULE_TTL_DEFAULT;
- KR_EXPORT
- int kr_rule_local_data_ins(const knot_rrset_t *rrs, const knot_rdataset_t *sig_rds,
- 				kr_rule_tags_t tags, kr_rule_opts_t opts);
--/** Merge RRs into a local data rule.
-+/** Merge RRs into a local data rule with the same set of tags.
-  *
-- * - FIXME: with multiple tags variants for the same name-type pair,
-- *     you typically end up with a single RR per RRset
-  * - RRSIGs get dropped, if any were attached.
-  * - We assume that this is called with a RW transaction open already,
-  *   which is always true in normal usage (long RW txn covering whole config).