resolve: get the current DNS server before passing the server lists

manager_get_dns_server() may re-read /etc/resolv.conf and replace
m->dns_servers and m->search_domains, but it was passed as an argument
to dns_configuration_json_append() together with those lists, and the
order of evaluation of the arguments is unspecified. gcc with LTO reads
the list heads first, so after a foreign /etc/resolv.conf has changed
the freed lists are walked. Typically the serialization then fails with
EUCLEAN, which makes the SubscribeDNSConfiguration method of
io.systemd.Resolve.Monitor and in turn systemd-networkd-wait-online
--dns fail.

Call manager_get_dns_server() first and store the result in a local
variable.

(cherry picked from commit 04567a3b5e2e29a2252e89be8a3c625c692103d3)
This commit is contained in:
Egor Ignatov
2026-10-16 17:24:50 +01:00
committed by Luca Boccassi
parent c3e01464e7
commit 7476fff8f2
+5 -1
View File
@@ -2173,12 +2173,16 @@ static int global_dns_configuration_json_append(Manager *m, sd_json_variant **co
if (r < 0)
return r;
/* This may re-read /etc/resolv.conf and replace m->dns_servers and m->search_domains, hence call it
* before they are passed below, as the order of evaluation of the arguments is unspecified. */
DnsServer *current_dns_server = manager_get_dns_server(m);
return dns_configuration_json_append(
/* ifname= */ NULL,
/* ifindex= */ 0,
/* delegate= */ NULL,
/* default_route= */ -1,
manager_get_dns_server(m),
current_dns_server,
m->dns_servers,
m->fallback_dns_servers,
m->search_domains,