From a572dd2f607a14d065a5c9538393cee037daca58 Mon Sep 17 00:00:00 2001 From: dongshengyuan <545258830@qq.com> Date: Wed, 12 Aug 2026 13:42:40 +0800 Subject: [PATCH] resolved: allow full replacement of link domains SetLinkDomains() marks old link domains and then builds the replacement list in place. The marked old domains still counted against LINK_SEARCH_DOMAINS_MAX, so replacing a non-empty list with exactly the maximum number of new domains failed while adding the last entry. The error path then unlinked all domains, so a failed setter call also destroyed the previous configuration. Reproducer: resolvectl domain dnsbug1 old.example busctl call org.freedesktop.resolve1 /org/freedesktop/resolve1 \ org.freedesktop.resolve1.Manager SetLinkDomains 'ia(sb)' "$ifindex" 1024 "${args[@]}" resolvectl domain dnsbug1 Before: the bus call failed with "Argument list too long" and the link's domain list became empty. Follow-up for: d2ec6608b93e3f74345c737637af24e9e75c209b --- src/resolve/resolved-link-bus.c | 4 ++++ test/units/TEST-75-RESOLVED.sh | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c index a269414ccf..0f341d740a 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -392,6 +392,10 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_ dns_search_domain_move_back_and_unmark(d); else { r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, /* delegate= */ NULL, name); + if (r == -E2BIG) { + changed = dns_search_domain_unlink_marked(l->search_domains) || changed; + r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, /* delegate= */ NULL, name); + } if (r < 0) goto clear; diff --git a/test/units/TEST-75-RESOLVED.sh b/test/units/TEST-75-RESOLVED.sh index ad4e8f8a42..44cc71ba9f 100755 --- a/test/units/TEST-75-RESOLVED.sh +++ b/test/units/TEST-75-RESOLVED.sh @@ -290,6 +290,21 @@ manual_testcase_01_resolvectl() { assert_in "DOMAINS=~route-only-change.example.com" "$(cat "$hoge_state")" assert_not_in "route-only-change.example.com" "$(cat /run/systemd/resolve/resolv.conf /run/systemd/resolve/stub-resolv.conf)" + resolvectl domain hoge "old.example.com" + local domains=() + for i in {1..1025}; do + domains+=("too-many-$i.example.com") + done + (! resolvectl domain hoge "${domains[@]}") + assert_in 'old.example.com' "$(resolvectl domain hoge)" + + domains=() + for i in {1..1024}; do + domains+=("replacement-$i.example.com") + done + resolvectl domain hoge "${domains[@]}" + assert_not_in 'old.example.com' "$(resolvectl domain hoge)" + assert_in 'replacement-1024.example.com' "$(resolvectl domain hoge)" echo -e "nameserver 10.0.2.1\ndomain test-domain.example.com" | SYSTEMD_INVOKED_AS=resolvconf resolvectl -x -a hoge assert_in 'test-domain.example.com' "$(resolvectl domain hoge)" assert_in '~.' "$(resolvectl domain hoge)"