Add privileged container support for FUSE workloads - #41174
Add privileged container support for FUSE workloads#41174Xiaoyang Han (Ivanbeethoven) wants to merge 8 commits into
Conversation
Add WSLCContainerFlagsPrivileged flag end-to-end: - docker_schema.h: add Privileged field to HostConfig - WSLCShared.idl: add WSLCContainerFlagsPrivileged = 128 - wslcsdk.cpp: wire WSLC_CONTAINER_FLAG_PRIVILEGED to runtime - ContainerModel.h: add Privileged option - ArgumentDefinitions.h: add --privileged CLI flag - ContainerCreateCommand.cpp: register --privileged arg - ContainerTasks.cpp: parse --privileged arg - ContainerService.cpp: pass privileged to launcher - WSLCContainerLauncher: add SetPrivileged(bool) - WSLCContainer.cpp: set Privileged=true on Docker HostConfig This enables privileged mode containers (required for /dev/fuse, etc.) via wslc run --privileged or wslc create --privileged.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Adds privileged-container support to the WSL Containers stack (CLI → service/launcher → session/Docker request), enabling workloads that require elevated capabilities and access to /dev/fuse.
Changes:
- Introduces a
--privilegedCLI option and corresponding flags/plumbing through launcher/session layers. - Extends the Docker HostConfig schema and request generation to set
Privileged=trueandSecurityOpt=["seccomp=unconfined"], plus explicit/dev/fusedevice mapping. - Adds initial scaffolding for a
--deviceCLI option (currently not wired through to the runtime).
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/windows/wslcsession/WSLCContainer.cpp | Sets Docker HostConfig privileged/security options and adds /dev/fuse device mapping when privileged is requested. |
| src/windows/WslcSDK/wslcsdk.h | Updates public SDK container flags to include privileged. |
| src/windows/WslcSDK/wslcsdk.cpp | Extends SDK flag conversion/mask/asserts to include privileged. |
| src/windows/wslc/tasks/ContainerTasks.cpp | Parses --privileged (and --device) into container options. |
| src/windows/wslc/services/ContainerService.cpp | Wires Privileged into the container launcher; notes TODO for devices. |
| src/windows/wslc/services/ContainerModel.h | Adds Privileged and Devices fields to the CLI service model. |
| src/windows/wslc/commands/ContainerRunCommand.cpp | Exposes --privileged / --device on run. |
| src/windows/wslc/commands/ContainerCreateCommand.cpp | Exposes --privileged / --device on create. |
| src/windows/wslc/arguments/ArgumentDefinitions.h | Adds argument definitions for privileged and device. |
| src/windows/service/inc/WSLCShared.idl | Adds internal WSLCContainerFlagsPrivileged and updates valid mask. |
| src/windows/inc/docker_schema.h | Adds HostConfig Privileged/SecurityOpt fields and refactors auth response type definition. |
| src/windows/common/WSLCContainerLauncher.h | Adds launcher API/state for privileged containers. |
| src/windows/common/WSLCContainerLauncher.cpp | Sets the privileged flag into WSLCContainerOptions.Flags. |
| _(Device, "device", NO_ALIAS, Kind::Value, L"Add a host device to the container") \ | ||
| _(Privileged, "privileged", NO_ALIAS, Kind::Flag, L"Run container in privileged mode") \ | ||
| #define WSLC_ARGUMENTS(_) \ | ||
| _(All, "all", L"a", Kind::Flag, Localization::WSLCCLI_AllArgDescription()) \ |
| for (const auto& device : context.Args.GetAll<ArgType::Device>()) | ||
| { | ||
| auto parsed = validation::ParseLabel(WideToMultiByte(device)); | ||
| options.Devices.emplace_back(parsed.first, parsed.second); | ||
| } |
| if (options.Privileged) | ||
| { | ||
| containerLauncher.SetPrivileged(true); | ||
| } | ||
|
|
||
| // TODO: Wire devices through to SDK when MDL struct is added. | ||
| // for (const auto& [hostPath, containerPath] : options.Devices) { ... } | ||
|
|
| } | ||
|
|
||
| // All strings built successfully — allocate output array and transfer ownership. | ||
| // All strings built successfully �?allocate output array and transfer ownership. |
| // Docker wire type is int64. 0 means "use daemon default" �?same as omitting | ||
| // the field �?so we don't bother with std::optional here. |
| typedef enum WslcContainerFlags | ||
| { | ||
| WSLC_CONTAINER_FLAG_NONE = 0x00000000, | ||
| WSLC_CONTAINER_FLAG_AUTO_REMOVE = 0x00000001, | ||
| WSLC_CONTAINER_FLAG_ENABLE_GPU = 0x00000002, | ||
| WSLC_CONTAINER_FLAG_PRIVILEGED = 0x00000004, | ||
| WSLC_CONTAINER_FLAG_PRIVILEGED = 0x00000080, | ||
|
|
||
| } WslcContainerFlags; |
@microsoft-github-policy-service agree |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (3)
src/windows/wslc/arguments/ArgumentDefinitions.h:37
WSLC_ARGUMENTSX-macro entries for Device/Privileged are placed before the#define WSLC_ARGUMENTS(_)line, which will expand_(at file scope and break compilation depending on how this header is included.
_(Device, "device", NO_ALIAS, Kind::Value, L"Add a host device to the container") \
_(Privileged, "privileged", NO_ALIAS, Kind::Flag, L"Run container in privileged mode") \
#define WSLC_ARGUMENTS(_) \
src/windows/wslcsession/WSLCContainer.cpp:2767
- The comment text contains mojibake ("�?") which indicates a source-encoding corruption; this should be restored to a normal dash so the comment is readable.
// All strings built successfully �?allocate output array and transfer ownership.
src/windows/inc/docker_schema.h:298
- These comments contain mojibake ("�?") instead of a dash, which indicates an encoding/copy-paste issue and reduces readability.
// Docker wire type is int64. 0 means "use daemon default" �same as omitting
// the field �so we don't bother with std::optional here.
| _(Device, "device", NO_ALIAS, Kind::Value, L"Add a host device to the container") \ | ||
| _(Privileged, "privileged", NO_ALIAS, Kind::Flag, L"Run container in privileged mode") \ |
| if (context.Args.Contains(ArgType::Device)) | ||
| { | ||
| for (const auto& device : context.Args.GetAll<ArgType::Device>()) | ||
| { | ||
| auto parsed = validation::ParseLabel(WideToMultiByte(device)); | ||
| options.Devices.emplace_back(parsed.first, parsed.second); | ||
| } | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/windows/wslc/arguments/ArgumentDefinitions.h:108
- The new --privileged argument description is a user-facing string but is not localized (it uses a raw L"..." literal). Most other arguments in this list use Localization::WSLCCLI_*ArgDescription() strings, and the repo’s localization guidance expects new user-visible strings to be added to Resources.resw and surfaced via Localization helpers.
_(Privileged, "privileged", NO_ALIAS, Kind::Flag, L"Run container in privileged mode") \
| if (context.Args.Contains(ArgType::Privileged)) | ||
| { | ||
| options.Privileged = true; | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/windows/wslc/arguments/ArgumentDefinitions.h:108
- The new --privileged argument description is a hard-coded English string, while most other CLI argument descriptions in this file use Localization::WSLCCLI_*ArgDescription() for localizable/help output. This introduces a new user-facing string that won't be localized.
_(Privileged, "privileged", NO_ALIAS, Kind::Flag, L"Run container in privileged mode") \
| constexpr auto s_publicMask = WSLC_CONTAINER_FLAG_AUTO_REMOVE | WSLC_CONTAINER_FLAG_ENABLE_GPU; | ||
| auto result = static_cast<WSLCContainerFlags>(flags & s_publicMask); | ||
| if (WI_IsFlagSet(flags, WSLC_CONTAINER_FLAG_PRIVILEGED)) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/windows/wslc/arguments/ArgumentDefinitions.h:108
- The new
--privilegedargument description is a hard-coded English string. Most other arguments useLocalization::...descriptions; adding another literal here makes the CLI help non-localizable and inconsistent.
_(Privileged, "privileged", NO_ALIAS, Kind::Flag, L"Run container in privileged mode") \
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/windows/wslc/arguments/ArgumentDefinitions.h:109
- The new
--privilegedargument description is a hard-coded string literal instead of using the existingLocalization::WSLCCLI_*ArgDescription()pattern used by other CLI arguments. This introduces a new user-facing string without a localization resource entry.
_(Publish, "publish", L"p", Kind::Value, Localization::WSLCCLI_PublishArgDescription()) \
_(PublishAll, "publish-all", L"P", Kind::Flag, Localization::WSLCCLI_PublishAllArgDescription()) \
_(Privileged, "privileged", NO_ALIAS, Kind::Flag, L"Run container in privileged mode") \
/*_(Pull, "pull", NO_ALIAS, Kind::Value, Localization::WSLCCLI_PullArgDescription())*/ \
| options.StopSignal = m_stopSignal; | ||
| options.Flags = m_containerFlags; | ||
| if (m_privileged) { WI_SetFlag(options.Flags, WSLCContainerFlagsPrivileged); } | ||
| if (m_stopTimeout.has_value()) | ||
| { |
|
Unfortunately adding WSL includes support for "WSL Plugins" like MDE which are supremely valuable to enterprises to be able to monitor what happens inside of a WSL distribution (And in the future WSL Containers). Adding So for us to accept any PR on this, we'd need it to have a full E2E security story of how this would work with WSL plugins and not invalidate security promises around WSL container. Xiaoyang Han (@Ivanbeethoven) thank you for filing this - I would understand if that's a bit out of scope of what changes you'd like. I'll leave this open for now but please let me know if you're not interested or up for doing the full E2E security review for that change and I can close it. Thanks! |
Thanks for the detailed explanation. Given the broader security implications and the need for a full E2E security review, this is outside the scope of what I can take on at the moment. I’ll step back from this change, so feel free to close the PR. |
Summary
Adds first-class privileged-container support to the WSL Containers command line and SDK path, including the runtime settings needed for FUSE workloads.
Changes
--privilegedcontainer option through the command, service, SDK, and session layers.HostConfig.Privileged=trueandSecurityOpt=[seccomp=unconfined]for privileged containers.c 10:229 rwmfor privileged containers.Validation
Built the modified WSL components locally and loaded the resulting
wslcsdk.dllwith a real Windows WSL service. A privileged container reported full capabilities,Seccomp=0, and successfully opened/dev/fuseread/write. BrewFS then established a real FUSE mount backed by Redis and completed fio read/write smoke jobs.The local Rust SDK integration test was rerun against the final SDK ABI. It passed with
Seccomp: 0,/dev/fusemajor/minor10:229, andFUSE_OPEN_OK.Related downstream work
Ivanbeethoven/wslc-rscommitd0603d3preserves the public privileged-flag ABI and includes the FFI pointer-lifetime regression fix required by real exec and privileged-FUSE use.