From 253b34d8ac08e9443d5ab19c5528ee85118ddd5a Mon Sep 17 00:00:00 2001 From: dongshengyuan <545258830@qq.com> Date: Thu, 13 Aug 2026 10:54:02 +0800 Subject: [PATCH] resolvconf: reject malformed stdin without changing link state The resolvconf compatibility parser ignored errors from nameserver, domain, and search lines. If one of those lines was malformed, resolvectl could still send the partially parsed configuration to resolved and overwrite the previous link state. Reproducer: IF=enp1s0 TMP="$(mktemp -d)" ln -s "$(command -v resolvectl)" "$TMP/resolvconf" sudo resolvectl dns "$IF" 1.1.1.1 sudo resolvectl domain "$IF" keep.example resolvectl domain "$IF" printf 'nameserver 1.1.1.1\nsearch "unterminated\n' | sudo "$TMP/resolvconf" -a "$IF" || true resolvectl domain "$IF" Before: The malformed search line was ignored and the previous domain was cleared: Link 2 (enp1s0): keep.example Link 2 (enp1s0): After: The malformed input fails before updating resolved, so keep.example remains configured. Follow-up for: 097f130731513bd934ed74975ac34070197614af --- NEWS | 3 +++ man/resolvectl.xml | 3 ++- src/resolve/resolvconf-compat.c | 8 ++++++-- test/units/TEST-75-RESOLVED.sh | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index ccadaa256d..c5686b929f 100644 --- a/NEWS +++ b/NEWS @@ -454,6 +454,9 @@ CHANGES WITH 261: Changes in systemd-resolved: + * The resolvconf compatibility mode now rejects malformed stdin input + and leaves the existing per-link DNS configuration unchanged. + * systemd-resolved will now read additional DNS resource record definitions to resolve locally from JSON drop-in files in {/etc,/run,/usr/local/lib,/usr/lib}/systemd/resolve/static.d/. This diff --git a/man/resolvectl.xml b/man/resolvectl.xml index e908345d48..fabd64e81e 100644 --- a/man/resolvectl.xml +++ b/man/resolvectl.xml @@ -564,7 +564,8 @@ DNS configuration data from its standard input. Relevant fields are nameserver and domain/search. This command is mostly identical to invoking resolvectl with a combination of and - commands. + commands. If a relevant input line has invalid syntax, the command fails and leaves the existing + per-interface configuration unchanged. diff --git a/src/resolve/resolvconf-compat.c b/src/resolve/resolvconf-compat.c index d3ddec755a..dcac5c130e 100644 --- a/src/resolve/resolvconf-compat.c +++ b/src/resolve/resolvconf-compat.c @@ -116,7 +116,9 @@ static int parse_stdin(LookupType lookup_type) { a = first_word(line, "nameserver"); if (a) { - (void) parse_nameserver(a); + r = parse_nameserver(a); + if (r < 0) + return log_error_errno(r, "Failed to parse resolv.conf nameserver line: %m"); continue; } @@ -124,7 +126,9 @@ static int parse_stdin(LookupType lookup_type) { if (!a) a = first_word(line, "search"); if (a) { - (void) parse_search_domain(a); + r = parse_search_domain(a); + if (r < 0) + return log_error_errno(r, "Failed to parse resolv.conf domain/search line: %m"); continue; } diff --git a/test/units/TEST-75-RESOLVED.sh b/test/units/TEST-75-RESOLVED.sh index 707a6f3011..e3055616cb 100755 --- a/test/units/TEST-75-RESOLVED.sh +++ b/test/units/TEST-75-RESOLVED.sh @@ -273,6 +273,9 @@ manual_testcase_01_resolvectl() { assert_in 'test-domain1.example.com' "$(resolvectl domain hoge)" assert_in 'test-domain2.example.com' "$(resolvectl domain hoge)" assert_in 'test-search-domain.example.com' "$(resolvectl domain hoge)" + resolvectl domain hoge keep.example + (! echo -e "nameserver 10.0.2.1\nsearch \"unterminated" | SYSTEMD_INVOKED_AS=resolvconf resolvectl -a hoge) + assert_in 'keep.example' "$(resolvectl domain hoge)" # Tests for 'resolvconf -x' echo nameserver 10.0.2.1 | SYSTEMD_INVOKED_AS=resolvconf resolvectl -x -a hoge