From 1d410b0dc920d54597f93f5bc98dddada3d623eb Mon Sep 17 00:00:00 2001 From: dongshengyuan <545258830@qq.com> Date: Thu, 9 Jul 2026 08:35:03 +0800 Subject: [PATCH] dns-rr: invalidate wire format after changing ttl dns_resource_record_clamp_ttl() may patch the TTL in place when the record has a single reference. dnssec_fix_rrset_ttl() also updates TTLs after canonical wire-format data may have been cached. If a record already has cached wire-format data, that cache still contains the old TTL and dns_resource_record_to_wire_format() will keep reusing it. Add a small helper to clear the cached wire-format state, and use it whenever the TTL changes. This makes subsequent serialization match the record fields. Signed-off-by: dongshengyuan (cherry picked from commit ccae5c7a4f269bcd7fac39baf93c1cee2c1536a8) (cherry picked from commit b82a9f9f53c226cda1452023290bb8cae659905e) (cherry picked from commit 03e94e2650891636767ae171e13f81633172dee2) --- src/resolve/resolved-dns-dnssec.c | 7 ++++++- src/resolve/test-dns-rr.c | 11 +++++++++++ src/shared/dns-rr.c | 10 ++++++++++ src/shared/dns-rr.h | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 9748f329201..4e51794faf9 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -551,7 +551,12 @@ static void dnssec_fix_rrset_ttl( /* Pick the TTL as the minimum of the RR's TTL, the * RR's original TTL according to the RRSIG and the * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */ - rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl); + uint32_t ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl); + if (ttl != rr->ttl) { + rr->ttl = ttl; + dns_resource_record_clear_wire_format(rr); + } + rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC; /* Copy over information about the signer and wildcard source of synthesis */ diff --git a/src/resolve/test-dns-rr.c b/src/resolve/test-dns-rr.c index c4a70a81c31..d6999d3f76b 100644 --- a/src/resolve/test-dns-rr.c +++ b/src/resolve/test-dns-rr.c @@ -2449,18 +2449,29 @@ TEST(dns_resource_record_is_synthetic) { * ================================================================ */ TEST(dns_resource_record_clamp_ttl_in_place) { + _cleanup_free_ void *wire_format = NULL; DnsResourceRecord *rr = NULL, *orig = NULL; + size_t wire_format_size; rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "www.example.com"); ASSERT_NOT_NULL(rr); orig = rr; rr->ttl = 3600; + rr->a.in_addr.s_addr = htobe32(0xc0a8017f); ASSERT_FALSE(dns_resource_record_clamp_ttl(&rr, 4800)); ASSERT_EQ(rr->ttl, 3600u); + ASSERT_OK(dns_resource_record_to_wire_format(rr, false)); + ASSERT_NOT_NULL(rr->wire_format); + wire_format_size = rr->wire_format_size; + ASSERT_NOT_NULL(wire_format = memdup(rr->wire_format, wire_format_size)); + ASSERT_TRUE(dns_resource_record_clamp_ttl(&rr, 2400)); ASSERT_EQ(rr->ttl, 2400u); + ASSERT_OK(dns_resource_record_to_wire_format(rr, false)); + ASSERT_EQ(rr->wire_format_size, wire_format_size); + ASSERT_NE(memcmp(rr->wire_format, wire_format, wire_format_size), 0); ASSERT_TRUE(rr == orig); diff --git a/src/shared/dns-rr.c b/src/shared/dns-rr.c index 38ccc2843ba..435c72b115b 100644 --- a/src/shared/dns-rr.c +++ b/src/shared/dns-rr.c @@ -1467,6 +1467,15 @@ int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) { return 0; } +void dns_resource_record_clear_wire_format(DnsResourceRecord *rr) { + assert(rr); + + rr->wire_format = mfree(rr->wire_format); + rr->wire_format_size = 0; + rr->wire_format_rdata_offset = 0; + rr->wire_format_canonical = false; +} + int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) { const char *n; int r; @@ -1978,6 +1987,7 @@ int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) { if (old_rr->n_ref == 1) { /* Patch in place */ old_rr->ttl = new_ttl; + dns_resource_record_clear_wire_format(old_rr); return 1; } diff --git a/src/shared/dns-rr.h b/src/shared/dns-rr.h index 56c30cf880e..833fdbeb8af 100644 --- a/src/shared/dns-rr.h +++ b/src/shared/dns-rr.h @@ -394,6 +394,7 @@ const char* dns_resource_record_to_string(DnsResourceRecord *rr); DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref); +void dns_resource_record_clear_wire_format(DnsResourceRecord *rr); int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical); int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret);