Skip to content

nvx-rs: give a layered root's workloads the DNS server that their network policy allows #860

Open

Description

Parent: #816. Needs: nothing for PR 1; #822's PR 10 for PR 2. Unblocks: #817's resolver; #845, in the snapshot/restore workstream (#833).

Goal.

  • Workloads in a layered root resolve names through the DNS server that their network policy allows, as a blockless guest's workloads do.
  • Cold boots and clones bind the same resolver file.
  • A root's teardown never trips over the runtime's binds.

Today (dev d04d9fb):

  • OpenVMM names the gateway as the guest's DNS server, with virtnet_dns=, when the egress policy allows DNS to it (vm/devices/net/net_backend_resources/src/egress.rs:971-990, in NVX's OpenVMM pin).

  • NVX's /init writes the initramfs's /etc/resolv.conf from that token (guest/common/init:235-246).

  • The layered root gets no resolver. No component handles one:

    • nvx-init-agent;
    • nvx-container-launch and nvx-container-enter;
    • the managed agent;
    • nvx::guest::entry.

    A root's workloads see the image's own /etc/resolv.conf, which NVX's Ubuntu image ships empty (scripts/nvx_tools/ubuntu.py:719-722), so they resolve no names. The proxy-only scenario doesn't notice: its proxy resolves names.

  • Shares and mappings may target /etc/resolv.conf: only /etc itself and /etc/machine-id are reserved (nvx-rs/src/protocol/share.rs:12-23).

  • Runtime binds:

    • Entry::bind_runtime binds a generated machine ID and the time status in the caller's mount namespace (nvx-rs/src/guest/entry.rs:715).
    • Root::teardown detaches no busy mount (nvx-rs/src/guest/root.rs:620-629).
    • So a caller that binds in the namespace where it later tears the root down can't remove the binds first, and the overlay's unmount fails. NVX's managed agent and the test adapter's entries helper avoid it: each binds in a mount namespace of its own, which ends before the teardown (nvx-rs/src/guest/managed_agent/seam.rs:99-102, :193-203; tests/runtime-adapter/src/worker/entries.rs:164-180). The test adapter's worker, which spawns and reaps every execution itself and tears the root down, has no such process.

Stacked PRs. PR 2 builds on PR 1; each lands with its own tests.

PR 1 of 2: the resolver bind, and removable runtime binds, in nvx::guest. Needs nothing.

  • The resolver: Entry::resolver(path) names a resolver file. Entry::bind_runtime binds it read-only, nosuid and nodev over the root's /etc/resolv.conf, as it binds a generated machine ID: a symbolic link there is replaced with an empty file first. Without one, the image's own file stays.
  • Removable binds: bind_runtime returns the binds that it made. A caller that tears the root down in the same mount namespace removes them first, in reverse order.
  • DNS servers: a strict reader of virtnet_dns=, in nvx::protocol::cmdline: at most one token, with one IPv4 or IPv6 address, as OpenVMM renders it. A writer of a resolver file that names it.
  • Reserved target: /etc/resolv.conf joins the container root's reserved targets (protocol::share::RESERVED_MOUNT_TARGETS), for the host's planner and the guest's mapper. A share there, allowed today, is refused.
  • Tests:
    • the bind's flags, and the link's replacement;
    • binds removed before a teardown, which then succeeds;
    • the reader's vectors;
    • the reserved target, on the host and in the guest.

PR 2 of 2: DNS in the test adapter. Needs PR 1, and #822's PR 10.

  • The worker binds the resolver that /init wrote, when the command line names a DNS server, and removes the binds before the root's teardown.
  • Tests, in VMs on KVM, MSHV and WHP:
    • with DNS allowed, a workload in the root finds the gateway in /etc/resolv.conf, and a query through it gets an answer;
    • with DNS denied, the root keeps the image's file;
    • a share at /etc/resolv.conf, refused before launch.

Elsewhere:

Done when: both PRs are merged, and the VM tests pass on the three backends.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions