summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-04-21 18:33:23 +0200
committerLennart Poettering <lennart@poettering.net>2020-04-22 19:38:04 +0200
commit86775e3524dcc1d719aa2c5ec39997f243e0a1e0 (patch)
treeab11e4b5701465c782f35664f597eb8be2d089ed
parent082814743f6d118e73dc4d38adc4c19f3b2a57ec (diff)
downloadsystemd-86775e3524dcc1d719aa2c5ec39997f243e0a1e0.tar.gz
nspawn: beef up --resolve-conf= modes
Let's add flavours for copying stub/uplink resolv.conf versions. Let's add a more brutal "replace" mode, where we'll replace any existing destination file. Let's also change what "auto" means: instead of copying the static file, let's use the stub file, so that DNS search info is copied over. Fixes: #15340
-rw-r--r--src/nspawn/nspawn-settings.c8
-rw-r--r--src/nspawn/nspawn-settings.h12
-rw-r--r--src/nspawn/nspawn.c33
3 files changed, 37 insertions, 16 deletions
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c
index 5fb5b49bbc..4b1115b6e8 100644
--- a/src/nspawn/nspawn-settings.c
+++ b/src/nspawn/nspawn-settings.c
@@ -821,8 +821,16 @@ static const char *const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = {
[RESOLV_CONF_OFF] = "off",
[RESOLV_CONF_COPY_HOST] = "copy-host",
[RESOLV_CONF_COPY_STATIC] = "copy-static",
+ [RESOLV_CONF_COPY_UPLINK] = "copy-uplink",
+ [RESOLV_CONF_COPY_STUB] = "copy-stub",
+ [RESOLV_CONF_REPLACE_HOST] = "replace-host",
+ [RESOLV_CONF_REPLACE_STATIC] = "replace-static",
+ [RESOLV_CONF_REPLACE_UPLINK] = "replace-uplink",
+ [RESOLV_CONF_REPLACE_STUB] = "replace-stub",
[RESOLV_CONF_BIND_HOST] = "bind-host",
[RESOLV_CONF_BIND_STATIC] = "bind-static",
+ [RESOLV_CONF_BIND_UPLINK] = "bind-uplink",
+ [RESOLV_CONF_BIND_STUB] = "bind-stub",
[RESOLV_CONF_DELETE] = "delete",
[RESOLV_CONF_AUTO] = "auto",
};
diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h
index f1a1a75466..6f2c1141e6 100644
--- a/src/nspawn/nspawn-settings.h
+++ b/src/nspawn/nspawn-settings.h
@@ -38,10 +38,18 @@ typedef enum UserNamespaceMode {
typedef enum ResolvConfMode {
RESOLV_CONF_OFF,
- RESOLV_CONF_COPY_HOST,
- RESOLV_CONF_COPY_STATIC,
+ RESOLV_CONF_COPY_HOST, /* /etc/resolv.conf */
+ RESOLV_CONF_COPY_STATIC, /* /usr/lib/systemd/resolv.conf */
+ RESOLV_CONF_COPY_UPLINK, /* /run/systemd/resolve/resolv.conf */
+ RESOLV_CONF_COPY_STUB, /* /run/systemd/resolve/stub-resolv.conf */
+ RESOLV_CONF_REPLACE_HOST,
+ RESOLV_CONF_REPLACE_STATIC,
+ RESOLV_CONF_REPLACE_UPLINK,
+ RESOLV_CONF_REPLACE_STUB,
RESOLV_CONF_BIND_HOST,
RESOLV_CONF_BIND_STATIC,
+ RESOLV_CONF_BIND_UPLINK,
+ RESOLV_CONF_BIND_STUB,
RESOLV_CONF_DELETE,
RESOLV_CONF_AUTO,
_RESOLV_CONF_MODE_MAX,
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 1d7136cee5..9888c9e294 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -79,6 +79,7 @@
#include "ptyfwd.h"
#include "random-util.h"
#include "raw-clone.h"
+#include "resolve-util.h"
#include "rlimit-util.h"
#include "rm-rf.h"
#if HAVE_SECCOMP
@@ -100,12 +101,6 @@
#include "user-util.h"
#include "util.h"
-#if HAVE_SPLIT_USR
-#define STATIC_RESOLV_CONF "/lib/systemd/resolv.conf"
-#else
-#define STATIC_RESOLV_CONF "/usr/lib/systemd/resolv.conf"
-#endif
-
/* nspawn is listening on the socket at the path in the constant nspawn_notify_socket_path
* nspawn_notify_socket_path is relative to the container
* the init process in the container pid can send messages to nspawn following the sd_notify(3) protocol */
@@ -1850,12 +1845,13 @@ static int setup_resolv_conf(const char *dest) {
if (arg_resolv_conf == RESOLV_CONF_AUTO) {
if (arg_private_network)
m = RESOLV_CONF_OFF;
- else if (have_resolv_conf(STATIC_RESOLV_CONF) > 0 && resolved_listening() > 0)
- m = etc_writable() ? RESOLV_CONF_COPY_STATIC : RESOLV_CONF_BIND_STATIC;
+ else if (have_resolv_conf(PRIVATE_STUB_RESOLV_CONF) > 0 && resolved_listening() > 0)
+ m = etc_writable() ? RESOLV_CONF_COPY_STUB : RESOLV_CONF_BIND_STUB;
else if (have_resolv_conf("/etc/resolv.conf") > 0)
m = etc_writable() ? RESOLV_CONF_COPY_HOST : RESOLV_CONF_BIND_HOST;
else
m = etc_writable() ? RESOLV_CONF_DELETE : RESOLV_CONF_OFF;
+
} else
m = arg_resolv_conf;
@@ -1877,12 +1873,16 @@ static int setup_resolv_conf(const char *dest) {
return 0;
}
- if (IN_SET(m, RESOLV_CONF_BIND_STATIC, RESOLV_CONF_COPY_STATIC))
- what = STATIC_RESOLV_CONF;
+ if (IN_SET(m, RESOLV_CONF_BIND_STATIC, RESOLV_CONF_REPLACE_STATIC, RESOLV_CONF_COPY_STATIC))
+ what = PRIVATE_STATIC_RESOLV_CONF;
+ else if (IN_SET(m, RESOLV_CONF_BIND_UPLINK, RESOLV_CONF_REPLACE_UPLINK, RESOLV_CONF_COPY_UPLINK))
+ what = PRIVATE_UPLINK_RESOLV_CONF;
+ else if (IN_SET(m, RESOLV_CONF_BIND_STUB, RESOLV_CONF_REPLACE_STUB, RESOLV_CONF_COPY_STUB))
+ what = PRIVATE_STUB_RESOLV_CONF;
else
what = "/etc/resolv.conf";
- if (IN_SET(m, RESOLV_CONF_BIND_HOST, RESOLV_CONF_BIND_STATIC)) {
+ if (IN_SET(m, RESOLV_CONF_BIND_HOST, RESOLV_CONF_BIND_STATIC, RESOLV_CONF_BIND_UPLINK, RESOLV_CONF_BIND_STUB)) {
_cleanup_free_ char *resolved = NULL;
int found;
@@ -1898,17 +1898,22 @@ static int setup_resolv_conf(const char *dest) {
r = mount_verbose(LOG_WARNING, what, resolved, NULL, MS_BIND, NULL);
if (r >= 0)
return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
+
+ /* If that didn't work, let's copy the file */
}
- /* If that didn't work, let's copy the file */
- r = copy_file(what, where, O_TRUNC|O_NOFOLLOW, 0644, 0, 0, COPY_REFLINK);
+ if (IN_SET(m, RESOLV_CONF_REPLACE_HOST, RESOLV_CONF_REPLACE_STATIC, RESOLV_CONF_REPLACE_UPLINK, RESOLV_CONF_REPLACE_STUB))
+ r = copy_file_atomic(what, where, 0644, 0, 0, COPY_REFLINK|COPY_REPLACE);
+ else
+ r = copy_file(what, where, O_TRUNC|O_NOFOLLOW, 0644, 0, 0, COPY_REFLINK);
if (r < 0) {
/* If the file already exists as symlink, let's suppress the warning, under the assumption that
* resolved or something similar runs inside and the symlink points there.
*
* If the disk image is read-only, there's also no point in complaining.
*/
- log_full_errno(!IN_SET(RESOLV_CONF_COPY_HOST, RESOLV_CONF_COPY_STATIC) && IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(!IN_SET(RESOLV_CONF_COPY_HOST, RESOLV_CONF_COPY_STATIC, RESOLV_CONF_COPY_UPLINK, RESOLV_CONF_COPY_STUB) &&
+ IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to copy /etc/resolv.conf to %s, ignoring: %m", where);
return 0;
}