feat(supervisor): set up sandbox netns via rtnetlink instead of ip/nsenter - #3285
Open
akram wants to merge 1 commit into
Open
feat(supervisor): set up sandbox netns via rtnetlink instead of ip/nsenter#3285akram wants to merge 1 commit into
akram wants to merge 1 commit into
Conversation
…enter
Replace the privileged supervisor's `ip` (32 call sites) and the
`ip`-in-namespace `nsenter` usage with in-process route netlink
(rtnetlink) plus unshare/setns/mount syscalls, so proxy-mode sandboxes no
longer need iproute2/nsenter from the workload image and a bare Alpine
image works.
- New netns/netlink.rs programs the veth pair, addresses, routes, and
teardown over rtnetlink. The namespace is created with
unshare(CLONE_NEWNET) and bind-mounted onto netns_path via mount(2)
(not `ip netns add`), so it stays reachable for the still-nsenter-based
nft path, which is converted separately.
- rtnetlink is async; it is driven from the synchronous create() via a
local current-thread runtime on a dedicated OS thread. create() runs
inside a tokio runtime on the podman driver, so building the runtime on
the caller thread would panic ("runtime within a runtime");
namespace-scoped operations run on a setns thread.
- Remove run_ip/run_ip_netns/run_ip_netns_output and IP_SEARCH_PATHS, and
drop the iproute2 hint from the proxy-mode error. nsenter and the nft
helpers are unchanged (the nft path is a separate follow-up).
Refs NVIDIA#3281
Signed-off-by: Akram <akram.benaissi@gmail.com>
akram
marked this pull request as ready for review
September 11, 2026 15:04
akram
requested review from
a team,
derekwaynecarr,
mrunalp and
sjenning
as code owners
September 11, 2026 15:04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The privileged supervisor builds the sandbox network namespace by shelling out to
ip(32 call sites) and, for in-namespace operations,nsenter— both resolved from the workload image. A baredocker.io/library/alpine:3.22image ships only busyboxip(nonetnssubcommand), so proxy-mode setup fails withNetwork namespace creation failed … iproute2 is installed.This change programs the namespace entirely through kernel interfaces, so the supervisor needs no network tooling from the workload image:
rtnetlink).unshare(CLONE_NEWNET)on a short-lived thread and bind-mounted ontonetns_pathviamount(2)(notip netns add), so it persists and stays reachable for the still-nsenter-based nft path.setns()into the namespace, instead of spawningnsenter.rtnetlinkis async; it is confined to the newnetns/netlink.rsmodule and driven from the synchronouscreate()via a localcurrent_threadruntime on a dedicated OS thread —create()runs inside a tokio runtime on the Podman driver, so building the runtime on the caller thread would panic (“Cannot start a runtime from within a runtime”).Scope is the
ip/nsenternamespace-setup path only. Thenftbypass-rule path (stillnsenter-based) anddmesg→NFLOG are separate follow-ups, sonsenterand the nft helpers are intentionally left in place.Related Issue
Refs #3281 — networking (
ip/nsenter) subset of #2750 (make the privileged supervisor independent of workload-image tooling). Unblocks the bare-Alpine default in #3116.Changes
crates/openshell-supervisor-process/src/netns/netlink.rs: FD-owned namespace creation, host-side veth setup, setns-thread in-namespace configuration, veth/namespace teardown, and route replace/dump — all overrtnetlink+unshare/setns/mount.NetworkNamespace::create(),Drop,install_transparent_tcp_rules, andvalidate_synthetic_pool_routesonto the new module;first_route_overlapnow operates on parsed route prefixes.run_ip/run_ip_netns/run_ip_netns_outputhelpers andIP_SEARCH_PATHS; drop theiproute2hint from the proxy-mode error message.rtnetlink,netlink-packet-route, andfutures-utilunder the crate’scfg(target_os = "linux")dependencies.Testing
x86_64-unknown-linux-musl) with the new dependencies.docker.io/library/alpine:3.22sandbox starts in proxy mode with the network namespace, veth pair, addresses, and default route established via netlink and noip/nsenterprocess spawned; the FD-owned namespace bind mount is present, and teardown removes the veth and namespace. The sandbox reachesReady/healthy.#[ignore]; requireCAP_NET_ADMIN).iproute2/nftables.Checklist
nft/dmesgpaths left for follow-upsiproute2/nftables