From: dongshengyuan <545258830@qq.com> Date: Thu, 9 Jul 2026 00:35:03 +0000 (+0800) Subject: dns-rr: invalidate wire format after changing ttl X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ccae5c7a4f269bcd7fac39baf93c1cee2c1536a8;p=thirdparty%2Fsystemd.git 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 --- diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 67cf991e705..575f100809d 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -554,7 +554,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 2ded6b0ab96..516c9011b42 100644 --- a/src/resolve/test-dns-rr.c +++ b/src/resolve/test-dns-rr.c @@ -2443,18 +2443,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 eb91910e835..9ba7429a6c3 100644 --- a/src/shared/dns-rr.c +++ b/src/shared/dns-rr.c @@ -1466,6 +1466,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; @@ -1977,6 +1986,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 d747083aa8a..a3cde2f3d1e 100644 --- a/src/shared/dns-rr.h +++ b/src/shared/dns-rr.h @@ -392,6 +392,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);