summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-06-01 10:08:07 +0200
committerThomas Haller <thaller@redhat.com>2018-06-05 16:09:32 +0200
commit2401e7c74bbc8eb2e0a6cc930624e2cdc49d9a33 (patch)
tree76b2d2cbf728252257588d3fdf3081a54fa51110
parent92ebd16cee2a7a306abae7fd3cba3f1366471f14 (diff)
downloadNetworkManager-th/dns-rc-manager-file-always-follow.tar.gz
dns: change main.rc-manager=file behavior to always follow symlinkth/dns-rc-manager-file-always-follow
With "main.rc-manager=file", if /etc/resolv.conf is a symlink, NetworkManager would follow the symlink and update the file instead. However, note that realpath() only returns a target, if the file actually exists. That means, if /etc/resolv.conf is a dangling symlink, NetworkManager would replace the symlink with a file. This was the only case in which NetworkManager would every change a symlink resolv.conf to a file. I think this is undesired behavior. This is a change in long established behavior. Although note that there were several changes regarding rc-manager settings in the past. See for example commit [1] and [2]. Now, first still try using realpath() as before. Only if that fails, try to resolve /etc/resolv.conf as a symlink with readlink(). Following the dangling symlink is likely not a problem for the user, it probably is even desired. The part that most likely can cause problems is if the destination file is not writable. That happens for example, if the destination's parent directories are missing. In this case, NetworkManager will now fail to write resolv.conf and log a warning. This has the potential of breaking existing setups, but it really is a mis-configuration from the user's side. This fixes for example the problem, if the user configures /etc/resolv.conf as symlink to /tmp/my-resolv.conf. At boot, the file would not exist, and NetworkManager would previously always replace the link with a plain file. Instead, it should follow the symlink and create the file. [1] 718fd2243690b8c72dd1cb32f67114f304542082 [2] 15177a34be297654086005f2d796e6a4c6a1b918
-rw-r--r--NEWS2
-rw-r--r--man/NetworkManager.conf.xml6
-rw-r--r--src/dns/nm-dns-manager.c19
3 files changed, 20 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 533b46a189..62f6be58e4 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,8 @@ Notable changes included in this snapshot so far include:
documentation. This represents a change in behavior since previous
versions where the first character of the string was used as
type. The internal client is not affected by the change.
+* DNS setting rc-manager=file now always follows dangling symlinks
+ instead of replacing /etc/resolv.conf with a plain file.
The following features were backported to 1.10.x releases from 1.10.0 to
1.10.8 are also present in NetworkManager-1.12:
diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml
index 6f333acd6f..8a1b04bc09 100644
--- a/man/NetworkManager.conf.xml
+++ b/man/NetworkManager.conf.xml
@@ -367,8 +367,10 @@ no-auto-default=*
<para><literal>file</literal>: NetworkManager will write
<filename>/etc/resolv.conf</filename> as file. If it finds
a symlink to an existing target, it will follow the symlink and
- update the target instead. If the symlink's target does not exist,
- the symlink will be replaced by a file.</para>
+ update the target instead. In no case will an existing symlink
+ be replaced by a file. Note that older versions of NetworkManager
+ behaved differently and would replace dangling symlinks with a
+ plain file.</para>
<para><literal>resolvconf</literal>: NetworkManager will run
resolvconf to update the DNS configuration.</para>
<para><literal>netconfig</literal>: NetworkManager will run
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c
index 354520b3a7..a29fd81f4e 100644
--- a/src/dns/nm-dns-manager.c
+++ b/src/dns/nm-dns-manager.c
@@ -792,18 +792,27 @@ update_resolv_conf (NMDnsManager *self,
if ( rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE
|| ( rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK
&& !_read_link_cached (_PATH_RESCONF, &resconf_link_cached, &resconf_link))) {
+ gs_free char *rc_path_syml = NULL;
nm_auto_free char *rc_path_real = NULL;
const char *rc_path = _PATH_RESCONF;
GError *local = NULL;
if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) {
- /* Note that if /etc/resolv.conf is a dangling symlink, realpath()
- * will return %NULL, and thus below we will replace the symlink
- * with a file. This is the only case, in which NetworkManager
- * replaces an existing symlink with a file.*/
- rc_path_real = realpath (rc_path, NULL);
+ rc_path_real = realpath (_PATH_RESCONF, NULL);
if (rc_path_real)
rc_path = rc_path_real;
+ else {
+ /* realpath did not resolve a path-name. That either means,
+ * _PATH_RESCONF:
+ * - does not exist
+ * - is a plain file
+ * - is a dangling symlink
+ *
+ * Handle the case, where it is a dangling symlink... */
+ rc_path_syml = nm_utils_read_link_absolute (_PATH_RESCONF, NULL);
+ if (rc_path_syml)
+ rc_path = rc_path_syml;
+ }
}
/* we first write to /etc/resolv.conf directly. If that fails,