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: d2ec6608b9
This commit is contained in:
dongshengyuan
2026-08-13 09:04:26 +08:00
parent 0cfa2d4f4c
commit a572dd2f60
2 changed files with 19 additions and 0 deletions
+4
View File
@@ -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;
+15
View File
@@ -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)"