diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-12-21 00:44:00 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-12-21 19:09:32 +0100 |
commit | 87447ae4598d8de5aad557ec746e27e8271a60a7 (patch) | |
tree | 508503e69ff4c6ee5b9fc2d188548c3479181c82 /src/nspawn | |
parent | 8ccf7e9e96ac89f02424c065e39043b5165f8bca (diff) |
nspawn: tweaks to /etc/resolv.conf management
Handle properly if /etc is a symlink (i.e. make sure we don't follow the
symlink outside the image). Also follow /etc/resolv.conf if it is a
symlink, and use the resolved path when creating a mount point and
mounting (as both of these operations follow symlinks and rally
shouldn't).
Handle more types of read-only errors as debug-level issues.
Diffstat (limited to 'src/nspawn')
-rw-r--r-- | src/nspawn/nspawn.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 5df00df6ed..6246c6d6fa 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1311,31 +1311,43 @@ static int setup_timezone(const char *dest) { } static int setup_resolv_conf(const char *dest) { - const char *where = NULL; - int r; + _cleanup_free_ char *resolved = NULL, *etc = NULL; + const char *where; + int r, found; assert(dest); if (arg_private_network) return 0; - /* Fix resolv.conf, if possible */ - where = prefix_roota(dest, "/etc/resolv.conf"); + r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc); + if (r < 0) { + log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); + return 0; + } + + where = strjoina(etc, "/resolv.conf"); + found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved); + if (found < 0) { + log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m"); + return 0; + } if (access("/run/systemd/resolve/resolv.conf", F_OK) >= 0 && - access("/usr/lib/systemd/resolv.conf", F_OK) >= 0) { + access("/usr/lib/systemd/resolv.conf", F_OK) >= 0) { + /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the * container, so that the container can use the host's resolver. Given that network namespacing is * disabled it's only natural of the container also uses the host's resolver. It also has the big * advantage that the container will be able to follow the host's DNS server configuration changes * transparently. */ - (void) touch(where); + if (found == 0) /* missing? */ + (void) touch(resolved); - r = mount_verbose(LOG_WARNING, "/usr/lib/systemd/resolv.conf", where, NULL, MS_BIND, NULL); + r = mount_verbose(LOG_DEBUG, "/usr/lib/systemd/resolv.conf", resolved, NULL, MS_BIND, NULL); if (r >= 0) - return mount_verbose(LOG_ERR, NULL, where, NULL, - MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); + 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 */ @@ -1346,7 +1358,7 @@ static int setup_resolv_conf(const char *dest) { * * If the disk image is read-only, there's also no point in complaining. */ - log_full_errno(IN_SET(r, -ELOOP, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + log_full_errno(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; } |