Skip to content

Commit

Permalink
Fix DNS queries in images with systemd-resolved on hosts without it
Browse files Browse the repository at this point in the history
On some Toolbx images with systemd-resolved(8), like the fedora-toolbox
images for Fedora 39 onwards, /etc/resolv.conf can end up being a
symbolic link inside the container that expects the host operating
system to also use systemd-resolved(8):
  $ ls -l /etc/resolv.conf
  lrwxrwxrwx. 1 root root 39 Nov 28 08:50 /etc/resolv.conf ->
    ../run/systemd/resolve/stub-resolv.conf

This happens because systemd-resolved(8) already makes /etc/resolv.conf
a symbolic link inside the image, and, hence, the container's entry
point doesn't change it to point at the host's copy of the file at
/run/host/etc/resolv.conf.  Instead, it's left pointing at the host's
copy of the files maintained by systemd-resolved(8) under
/run/systemd/resolve, which happen to be also available inside the
container [1].

If the host OS doesn't use systemd-resolved(8), like Red Hat Enterprise
Linux 9, then this leads to a dangling symbolic link and breaks DNS
queries.

Note that the presence of systemd-resolved(8) in the recent
fedora-toolbox images is a regression caused by the ToolbxReleaseBlocker
Change [2] for Fedora 39 where the image was rewritten in terms of
fedora-kickstarts and pungi-fedora instead of a Container/Dockerfile.
By mistake, systemd crept in as an RPM needed by the image [3], which
in turn pulled in the systemd-resolved RPM as a weak dependency [4].

Hopefully, that will get fixed.  However, it's also not practical to
keep track of all the Toolbx images out there in the wild, so it's
wise to make toolbox(1) more resilient to such things.

This will have the downside of overwriting some custom user-made
modifications to the container's /etc/resolv.conf.  While that's
unfortunate, it's more important to have Toolbx images produce working
containers on a wide range of host OSes.  It will be better to come up
with a more explicit way to support custom user-made modifications to
the container's configuration.  Perhaps with a persistent stamp file.

[1] Commit af602c7
    af602c7d227617d2
    #707

[2] https://fedoraproject.org/wiki/Changes/ToolbxReleaseBlocker

[3] fedora-kickstarts commit 48e2c3b5598de32f
    https://pagure.io/fedora-kickstarts/c/48e2c3b5598de32f

[4] fedora-kickstarts commit 49306cb6eada8777
    https://pagure.io/fedora-kickstarts/c/49306cb6eada8777

#1410
  • Loading branch information
debarshiray committed Dec 18, 2023
1 parent 5784754 commit 9289c2d
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/cmd/initContainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ func initContainer(cmd *cobra.Command, args []string) error {
return err
}

if _, err := os.Readlink("/etc/resolv.conf"); err != nil {
if resolvConfTarget, err := os.Readlink("/etc/resolv.conf"); err != nil ||
resolvConfTarget != "/run/host/etc/resolv.conf" {
if err := redirectPath("/etc/resolv.conf",
"/run/host/etc/resolv.conf",
false); err != nil {
Expand Down
126 changes: 126 additions & 0 deletions test/system/203-network.bats
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,132 @@ teardown() {
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: /etc/resolv.conf inside the default container" {
create_default_container

run --keep-empty-lines --separate-stderr "$TOOLBOX" run readlink /etc/resolv.conf

assert_success
assert_line --index 0 "/run/host/etc/resolv.conf"

if check_bats_version 1.10.0; then
assert [ ${#lines[@]} -eq 1 ]
else
assert [ ${#lines[@]} -eq 2 ]
fi

# shellcheck disable=SC2154
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: /etc/resolv.conf inside Arch Linux" {
create_distro_container arch latest arch-toolbox-latest

run --keep-empty-lines --separate-stderr "$TOOLBOX" run --distro arch readlink /etc/resolv.conf

assert_success
assert_line --index 0 "/run/host/etc/resolv.conf"

if check_bats_version 1.10.0; then
assert [ ${#lines[@]} -eq 1 ]
else
assert [ ${#lines[@]} -eq 2 ]
fi

# shellcheck disable=SC2154
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: /etc/resolv.conf inside Fedora 34" {
create_distro_container fedora 34 fedora-toolbox-34

run --keep-empty-lines --separate-stderr "$TOOLBOX" run --distro fedora --release 34 readlink /etc/resolv.conf

assert_success
assert_line --index 0 "/run/host/etc/resolv.conf"

if check_bats_version 1.10.0; then
assert [ ${#lines[@]} -eq 1 ]
else
assert [ ${#lines[@]} -eq 2 ]
fi

# shellcheck disable=SC2154
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: /etc/resolv.conf inside RHEL 8.7" {
create_distro_container rhel 8.7 rhel-toolbox-8.7

run --keep-empty-lines --separate-stderr "$TOOLBOX" run --distro rhel --release 8.7 readlink /etc/resolv.conf

assert_success
assert_line --index 0 "/run/host/etc/resolv.conf"

if check_bats_version 1.10.0; then
assert [ ${#lines[@]} -eq 1 ]
else
assert [ ${#lines[@]} -eq 2 ]
fi

# shellcheck disable=SC2154
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: /etc/resolv.conf inside Ubuntu 16.04" {
create_distro_container ubuntu 16.04 ubuntu-toolbox-16.04

run --keep-empty-lines --separate-stderr "$TOOLBOX" run --distro ubuntu --release 16.04 readlink /etc/resolv.conf

assert_success
assert_line --index 0 "/run/host/etc/resolv.conf"

if check_bats_version 1.10.0; then
assert [ ${#lines[@]} -eq 1 ]
else
assert [ ${#lines[@]} -eq 2 ]
fi

# shellcheck disable=SC2154
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: /etc/resolv.conf inside Ubuntu 18.04" {
create_distro_container ubuntu 18.04 ubuntu-toolbox-18.04

run --keep-empty-lines --separate-stderr "$TOOLBOX" run --distro ubuntu --release 18.04 readlink /etc/resolv.conf

assert_success
assert_line --index 0 "/run/host/etc/resolv.conf"

if check_bats_version 1.10.0; then
assert [ ${#lines[@]} -eq 1 ]
else
assert [ ${#lines[@]} -eq 2 ]
fi

# shellcheck disable=SC2154
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: /etc/resolv.conf inside Ubuntu 20.04" {
create_distro_container ubuntu 20.04 ubuntu-toolbox-20.04

run --keep-empty-lines --separate-stderr "$TOOLBOX" run --distro ubuntu --release 20.04 readlink /etc/resolv.conf

assert_success
assert_line --index 0 "/run/host/etc/resolv.conf"

if check_bats_version 1.10.0; then
assert [ ${#lines[@]} -eq 1 ]
else
assert [ ${#lines[@]} -eq 2 ]
fi

# shellcheck disable=SC2154
assert [ ${#stderr_lines[@]} -eq 0 ]
}

@test "network: DNS inside the default container" {
local ipv4_skip=false
local ipv4_addr
Expand Down

0 comments on commit 9289c2d

Please sign in to comment.