You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MXC will not run privileged LXC containers. After startup and before applying network rules, MXC reads the container's live UID mappings from the host. MXC stops the container if it cannot verify that container root maps to a nonroot host user. lxc-ls can incorrectly report an unprivileged container when lxc.namespace.keep = user retains the host user namespace.
build_lxc_capability_helper.rs builds a static helper embedded in MXC for network-filtered workloads. Entering the container can restore capabilities dropped on the host. The helper removes CAP_NET_ADMIN and CAP_NET_RAW after entry and before the workload starts. It restricts the requested command without changing the container's configuration or depending on container-provided libraries.
One consequence of this change is the minimum Linux version went up to 3.12. Version 3.12 is the minimum supported version to unprivileged containers.
Gudge (@MGudgin) for FYI on the minimum Linux kernel version change.
Remove the helper-specific tests instead of keeping a helper solely for testing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ee956a7c-701c-4e30-ba23-88ed75d298fc
Configured status can report an unprivileged container even when it retains the host user namespace.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ee956a7c-701c-4e30-ba23-88ed75d298fc
Use complete command output instead of the bounded helper; inspection now waits for lxc-attach to finish.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ee956a7c-701c-4e30-ba23-88ed75d298fc
A readable shifted-root range is sufficient; unreadable or nonmatching rows do not veto admission.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ee956a7c-701c-4e30-ba23-88ed75d298fc
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The LXC admission check trusts forgeable guest output, exposes host environment variables, and breaks existing SDK and CI flows without the required unprivileged provisioning and migration support.
This PR adds an unprivileged-container admission check to MXC’s LXC backend, intended to reject privileged containers before executing the requested workload.
Changes:
Inspect the live UID mapping after startup and stop containers that fail validation.
Add a regression scenario for misleading LXC privilege metadata and include it in the LXC suite.
Document unprivileged-container requirements and raise the minimum Linux kernel version to 3.12.
File
Description
tests/scripts/run_lxc_unprivileged_test.sh
Tests rejection, workload prevention, and cleanup for an identity-mapped container.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The admission check trusts guest-controlled output and can expose host credentials, while the V1 compatibility break lacks the required security-servicing documentation and migration guidance.
Configure shifted UID/GID mappings in all CI hosts
.github/workflows/lxc-e2e.yml:51
[P1] Scheduled LXC validation (scripts/ci/prepare-linux-host.sh) and Azure SDK integration (.azure-pipelines/templates/SDK.Integration.Test.Job.yml) still install LXC without configuring shifted mappings or root subordinate UID/GID ranges. On clean hosts with default LXC configuration, the new admission check rejects their normal success-path scenarios. Provision the mappings and required mapping tools in those entry points too, preferably through shared host setup with appropriate cleanup.
The streaming and PTY cases need no host files; sharing /tmp can prevent mapped-container startup on hosts with nested mounts.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ee956a7c-701c-4e30-ba23-88ed75d298fc
Namespace entry restored capabilities dropped on the host, allowing raw-socket traffic through the ICMP allowance. Reading UID mappings on the host avoids trusting guest code during admission.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ee956a7c-701c-4e30-ba23-88ed75d298fc
The reason will be displayed to describe this comment to others. Learn more.
This only requires one uid_map line that shifts root, so it admits g 0 0 65536 (host GID 0) and u 1 0 1 (container UID 1 = host root); on LXC 5.0.3 both let the workload read host root-only files.
Do we need to check gid_map, and refuse any range in either map that covers host ID 0 or any line that doesn't parse?
The reason will be displayed to describe this comment to others. Learn more.
The check runs after lxc-start, so a privileged container's init has already run as host root when it's refused; also, on a nested host, a container sharing MXC's user namespace passes because its map reads like a shifted one.
Shall we refuse a config without lxc.idmap or with lxc.namespace.keep = user before starting and refuse when /proc/<pid>/ns/user equals /proc/self/ns/user?
The reason will be displayed to describe this comment to others. Learn more.
This contradicts "Running without root" (line 57), and this PR also dropped its chmod o+x ~ step, which is still needed on 0750 Ubuntu homes (run_lxc_rootless_no_network_test.sh:31-32 still does it).
Please say root is needed to configure LXC and filter network traffic and restore the chmod o+x ~ step?
The reason will be displayed to describe this comment to others. Learn more.
Every root-run host with a stock /etc/lxc/default.conf hits this after upgrading, and nothing tells them to add root ranges to /etc/subuid//etc/subgid, add lxc.idmap, and recreate existing containers.
Please name those steps in the error or link the doc section that lists them?
The reason will be displayed to describe this comment to others. Learn more.
Every helper failure exits 126, and MXC returns that as the workload's normal exit code with no error, so "MXC couldn't confine the workload" looks the same as a script that exited 126; before this commit a failed drop was an MXC error.
The reason will be displayed to describe this comment to others. Learn more.
Nothing runs this helper directly: its failure exits are untested, and the aarch64 syscall path never executes in CI either?
Please add a Linux test that runs the embedded helper in a user namespace (caps dropped on success, exit 126 on bad args or a failed exec); it would also run natively on the arm64 build job.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Unresolved issues include a V1 networking compatibility break, a cross-container reply isolation bypass, and cleanup that can leave active workloads running without network restrictions.
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
Needs-Author-FeedbackWaiting for additional information or action from the issue or pull-request author.
3 participants
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.
📖 Description
MXC will not run privileged LXC containers. After startup and before applying network rules, MXC reads the container's live UID mappings from the host. MXC stops the container if it cannot verify that container root maps to a nonroot host user.
lxc-lscan incorrectly report an unprivileged container whenlxc.namespace.keep = userretains the host user namespace.build_lxc_capability_helper.rsbuilds a static helper embedded in MXC for network-filtered workloads. Entering the container can restore capabilities dropped on the host. The helper removesCAP_NET_ADMINandCAP_NET_RAWafter entry and before the workload starts. It restricts the requested command without changing the container's configuration or depending on container-provided libraries.One consequence of this change is the minimum Linux version went up to 3.12. Version 3.12 is the minimum supported version to unprivileged containers.
Gudge (@MGudgin) for FYI on the minimum Linux kernel version change.
🔗 References
N/A
🔍 Validation
Ran the full LXC E2E suite
✅ Checklist
feature-acceptedCargo.lock, thedependency-feed-checkcheck passes (see pull request builds)📋 Issue Type
Microsoft Reviewers: Open in CodeFlow