fix(init): prevent binfmt_misc handler loss on distro termination#14443
fix(init): prevent binfmt_misc handler loss on distro termination#14443yeelam-gordon wants to merge 5 commits intomicrosoft:masterfrom
Conversation
Fixes the issue where terminating a WSL2 distro with systemd clears binfmt_misc handlers across all running distros. Changes: - Add mount unit override to prevent binfmt_misc unmount during shutdown - Fix FP vs P flag inconsistency in WSLInterop registration - Use declarative /run/binfmt.d/ approach for handler persistence Fixes microsoft#13885 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a WSL2/systemd shutdown interaction where terminating one distro could clear binfmt_misc handlers (including WSLInterop) for other running distros, breaking Windows interop.
Changes:
- Generate a declarative
systemd-binfmtconfig in/run/binfmt.d/WSLInterop.conffor persistentWSLInteropregistration. - Add systemd generator drop-in overrides to prevent
systemd-binfmtstop actions and keepbinfmt_miscmounted during shutdown. - Align the
WSLInteropbinfmt registration string to consistently use:FP.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| test/windows/UnitTests.cpp | Adds assertions that the generated /run/binfmt.d config and systemd generator overrides exist (and stay consistent across restarts/reloads), and that protectBinfmt=false disables generation. |
| src/linux/init/main.cpp | Switches BINFMT_REGISTER_STRING to use the shared registration macro (now consistent with :FP). |
| src/linux/init/init.cpp | Implements generation of /run/binfmt.d/WSLInterop.conf and generator drop-ins for systemd-binfmt and the binfmt_misc mount unit when protectBinfmt is enabled. |
| src/linux/init/binfmt.h | Updates the shared binfmt registration macro to use :FP (fixing prior inconsistency). |
You can also share your feedback on Copilot code review. Take the survey.
Introduce BINFMT_INTEROP_REGISTRATION_STRING_VM with ':FP' flags for WSL2-only paths (mini_init, systemd generator), while keeping the original BINFMT_INTEROP_REGISTRATION_STRING with ':P' for WSL1 (lxcore) which does not support the 'F' (fix-binary) flag. - binfmt.h: Add _VM variant macro with ':FP', restore base macro to ':P' - main.cpp: Use _VM macro for mini_init registration (WSL2 only) - init.cpp: Use _VM macro for /run/binfmt.d/ config (systemd, WSL2 only) - config.cpp: Unchanged, continues using ':P' for WSL1 registration Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Prevents binfmt_misc handlers (notably WSLInterop) from being cleared across other running WSL2 distros when one systemd-enabled distro is terminated, by changing how WSL registers/preserves the handler and how systemd shutdown interacts with the binfmt_misc mount.
Changes:
- Switch WSL interop registration in VM paths to use an explicit
:FPflag combination and centralize the VM registration string. - Generate
/run/binfmt.d/WSLInterop.confand systemd generator drop-ins to avoid handler removal during shutdown and keepbinfmt_miscmounted late into shutdown. - Extend Windows unit tests to validate the generated config/drop-in files and their persistence across restarts/daemon-reload.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/linux/init/binfmt.h |
Introduces VM-specific binfmt registration string (:FP) and documents flag semantics/constraints. |
src/linux/init/main.cpp |
Updates VM-side registration to use the new VM registration string macro. |
src/linux/init/init.cpp |
Generates /run/binfmt.d config and new systemd generator drop-ins to prevent shutdown unmount/handler removal when protectBinfmt=true. |
test/windows/UnitTests.cpp |
Adds assertions validating the generated binfmt config and generator drop-ins across restarts/service reloads and the protectBinfmt=false path. |
The pure declarative approach via /run/binfmt.d/ does not handle conflicting binfmt configs. When a distro installs its own binfmt handler with the same name (WSLInterop), systemd-binfmt processes files alphabetically, potentially letting the conflicting handler win. Add ExecStartPost to the systemd-binfmt service override that forcefully unregisters any conflicting handler and re-registers WSL's after systemd-binfmt's normal ExecStart completes. This combines declarative config for proper re-registration with imperative override for guaranteed priority. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| constexpr auto* binfmtConfigDirectory = "/run/binfmt.d"; | ||
| constexpr auto* binfmtConfigPath = "/run/binfmt.d/WSLInterop.conf"; | ||
| const auto binfmtConfigContent = std::format("{}\n", BINFMT_INTEROP_REGISTRATION_STRING_VM(LX_INIT_BINFMT_NAME)); | ||
| const auto serviceOverrideContent = std::format( | ||
| R"(# Note: This file is generated by WSL to prevent distributions from removing the WSL binfmt entry on shutdown. | ||
| # To disable this unit, add the following to /etc/wsl.conf: | ||
| # [boot] | ||
| # protectBinfmt=false | ||
|
|
||
| [Service] | ||
| ExecStop= | ||
| ExecStart=/bin/sh -c '(echo -1 > {}/{}) ; (echo "{}" > {})' )", | ||
| ExecStartPost=/bin/sh -c '(echo -1 > {}/{} 2>/dev/null || true) ; echo "{}" > {}' | ||
| )", | ||
| BINFMT_MISC_MOUNT_TARGET, | ||
| LX_INIT_BINFMT_NAME, | ||
| BINFMT_INTEROP_REGISTRATION_STRING(LX_INIT_BINFMT_NAME), | ||
| BINFMT_INTEROP_REGISTRATION_STRING_VM(LX_INIT_BINFMT_NAME), | ||
| BINFMT_MISC_REGISTER_FILE); | ||
| constexpr auto* mountOverrideContent = R"(# Note: This file is generated by WSL to keep binfmt_misc mounted during shutdown. | ||
| # To disable this unit, add the following to /etc/wsl.conf: | ||
| # [boot] | ||
| # protectBinfmt=false | ||
|
|
||
| [Unit] | ||
| DefaultDependencies=no | ||
| Before=umount.target | ||
|
|
||
| [Mount] | ||
| Options=nosuid,nodev,noexec | ||
| )"; | ||
|
|
||
| THROW_LAST_ERROR_IF(UtilMkdirPath(binfmtConfigDirectory, 0755) < 0); | ||
| THROW_LAST_ERROR_IF(WriteToFile(binfmtConfigPath, binfmtConfigContent.c_str()) < 0); | ||
|
|
There was a problem hiding this comment.
/run/systemd/generator is regenerated on daemon-reload, but /run/binfmt.d/WSLInterop.conf is written outside the generator tree and is never removed when protectBinfmt or interopEnabled are later turned off. If a user flips protectBinfmt=false in /etc/wsl.conf and runs systemctl daemon-reload (or restarts systemd-binfmt), the stale /run/binfmt.d/WSLInterop.conf will continue to override distro binfmt config. Consider deleting /run/binfmt.d/WSLInterop.conf (and optionally the directory if empty) when the feature is disabled, so config changes take effect without requiring a full distro restart.
Summary of the Pull Request
This pull request enhances the way WSL registers and protects its binfmt_misc interpreter, especially for WSL2 (VM) environments. The changes introduce a more robust and systemd-friendly approach to managing binfmt configuration files and service overrides, and add comprehensive unit tests to verify correct behavior across various scenarios.
Binfmt_misc registration and systemd integration improvements:
BINFMT_INTEROP_REGISTRATION_STRING_VM, to generate the binfmt registration string with both the 'F' (fix-binary) and 'P' (preserve Argv[0]) flags for WSL2, ensuring the interpreter is accessible across namespaces and chroots.main.cppto use the new macro, aligning the registration string with WSL2 requirements.Systemd override and configuration file handling:
init.cppto:/run/binfmt.d/WSLInterop.conf.systemd-binfmt.service,binfmt-support.service, andproc-sys-fs-binfmt_misc.mountto ensure proper registration and prevent accidental removal or unmounting during shutdown.Unit test enhancements:
UnitTests.cppto validate the creation and contents of the generated binfmt configuration and override files, and to check their correct removal and regeneration in response to systemd service restarts and configuration changes.PR Checklist
Validation Steps Performed
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com