]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/cache pkt_renew(): don't keep parts of packet header docs-pkt-renew-306vyc/deployments/7216
authorVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 13 Jun 2025 13:27:10 +0000 (15:27 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 17 Jul 2025 06:14:13 +0000 (08:14 +0200)
No idea why it's been done in this weird way since forever.

NEWS
lib/cache/knot_pkt.c
lib/layer/iterate.c

diff --git a/NEWS b/NEWS
index a89970f1f6c20fbe6b41dd8d0040f8adde1a73d5..4ed34f9a555bfea735501a7a2663272765e21f3b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,12 @@
 Knot Resolver 6.0.15 (2025-06-dd)
 =================================
 
+Security
+--------
+- DoS: fix a rare segfault in `resolve` function (!1717)
+  Someone controlling the DNS traffic might be able
+  to trigger this crash intentionally and too often.
+
 Bugfixes
 --------
 - manager: prometheus metrics update (!1703, #917, !1712)
index 4b28891e979acc8ad55188a6fe4b0f4d3fa1e47c..7fe975cc258fa2130db59f8499cdd394034dffc3 100644 (file)
 
 int pkt_renew(knot_pkt_t *pkt, const knot_dname_t *name, uint16_t type)
 {
-       /* Clear the packet if needed. */
-       if (pkt->rrset_count != 0 || !knot_dname_is_equal(knot_pkt_qname(pkt), name)
-           || knot_pkt_qtype(pkt) != type || knot_pkt_qclass(pkt) != KNOT_CLASS_IN) {
-               int ret = kr_pkt_recycle(pkt);
-               if (ret) return kr_error(ret);
-               ret = knot_pkt_put_question(pkt, name, KNOT_CLASS_IN, type);
-               if (ret) return kr_error(ret);
-       }
+       knot_pkt_clear(pkt);
+       int ret = knot_pkt_put_question(pkt, name, KNOT_CLASS_IN, type);
+       if (ret) return kr_error(ret);
 
        pkt->parsed = pkt->size = KR_PKT_SIZE_NOWIRE;
        knot_wire_set_qr(pkt->wire);
index 3cc641cd8e657ef8b39b889baa7e2d68d9b5ec87..9a9a41a771c84f8f10ea037553e8b33b707212a3 100644 (file)
@@ -1060,6 +1060,8 @@ static int resolve(kr_layer_t *ctx, knot_pkt_t *pkt)
        if (!query) {
                return ctx->state;
        }
+       if (pkt->size == KR_PKT_SIZE_NOWIRE)
+               goto skip_checks; // answers from cache are sane, surely
        query->flags.PKT_IS_SANE = false;
 
        WITH_VERBOSE(query) {
@@ -1111,7 +1113,7 @@ static int resolve(kr_layer_t *ctx, knot_pkt_t *pkt)
                }
                return KR_STATE_CONSUME;
        }
-
+skip_checks:
        /* If exiting above here, there's no sense to put it into packet cache.
         * Having "extra bytes" at the end of DNS message is considered SANE here.
         * The most important part is to check for spoofing: is_paired_to_query() */