fix(os): make the SELinux assertion real and match it across both backends - #1043
Merged
Conversation
…kends CONFIG_SECURITY_SELINUX=y has sat in dstack-docker.cfg without effect. The kernel is built from the linux-yocto "tiny" type, which leaves CONFIG_SECURITY off, and SELINUX is "depends on SECURITY_NETWORK && AUDIT && NET && INET" with SECURITY_NETWORK depending on SECURITY. Kconfig drops a symbol whose dependencies are unmet without saying so, so every production image built from this fragment has run without SELinux while the fragment claimed otherwise. os/mkosi has had it all along, because x86_64_defconfig sets CONFIG_SECURITY -- so the two guest images have been measuring different feature sets. Enabling the chain is not sufficient on its own, and the second failure is silent in the same way: an LSM only registers if CONFIG_LSM names it, and that string's default is selected by DEFAULT_SECURITY_*. Turning on SECURITY without naming a default lands on DEFAULT_SECURITY_DAC, whose list is "landlock,lockdown,yama,loadpin,safesetid,ipe,bpf" -- selinux absent -- so the hooks would compile in and never initialize. Both the DEFAULT_SECURITY_SELINUX choice and the resulting CONFIG_LSM order are therefore asserted in both fragments, so neither a defconfig change nor a new DEFAULT_SECURITY_* branch can drop selinux without failing the build. This does not change enforcement. SELinux needs a loaded policy and neither image ships one; measured in a CVM on the mkosi image, which has had SELinux all along, /sys/fs/selinux exists with enforce=0, /etc/selinux holds only semanage.conf, and `docker info` reports no security options. On the Yocto image /sys/fs/selinux does not exist at all. What this buys is that both images measure the same feature set and the hooks can be used later without another kernel change. It does change the kernel's measurements, so it needs the same release coordination as any guest-image change. Verified by merging the fragment onto a kernel-config artifact from a real build (linux-yocto 6.18.24) and by reproducing the mkosi path from x86_64_defconfig, both with olddefconfig against Linux 6.18.40 source. SECURITY, SECURITY_NETWORK, AUDIT, AUDITSYSCALL, SECURITY_SELINUX, DEFAULT_SECURITY_SELINUX, NETWORK_SECMARK and SECURITYFS all come out =y on both backends, and the two CONFIG_LSM strings are byte-identical. os/mkosi's own kernel-config gate passes.
Contributor
There was a problem hiding this comment.
Pull request overview
Enables the full SELinux dependency chain for the Yocto-built guest kernel and aligns the mkosi kernel configuration so both guest-image backends consistently build and register SELinux (via DEFAULT_SECURITY_SELINUX + explicit CONFIG_LSM ordering), avoiding silent Kconfig no-ops and backend drift.
Changes:
- Enable
CONFIG_SECURITY,CONFIG_SECURITY_NETWORK, andCONFIG_AUDITin the Yocto kernel fragment soCONFIG_SECURITY_SELINUX=yactually takes effect. - Assert
CONFIG_DEFAULT_SECURITY_SELINUX=yand an explicitCONFIG_LSM=...ordering in both Yocto and mkosi kernel configs to ensure SELinux registers predictably.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| os/yocto/layers/meta-dstack/recipes-kernel/linux/files/dstack-docker.cfg | Turns the previously-silent SELinux request into an effective configuration by enabling required dependencies and pinning LSM order. |
| os/mkosi/components/kernel/kernel.config | Matches the Yocto SELinux assertions by pinning required symbols and CONFIG_LSM ordering for mkosi builds as well. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Problem
CONFIG_SECURITY_SELINUX=yhas been indstack-docker.cfgfor a long time and has never done anything.The kernel is built from the linux-yocto
tinytype, which leavesCONFIG_SECURITYoff.SECURITY_SELINUXisdepends on SECURITY_NETWORK && AUDIT && NET && INET, andSECURITY_NETWORKin turn depends onSECURITY. Kconfig drops a symbol whose dependencies are unmet without saying so, so every production image built from this fragment has run without SELinux while the fragment claimed otherwise.os/mkosihas had it all along, becausex86_64_defconfigsetsCONFIG_SECURITY. So the two guest images have been measuring different feature sets, with nothing recording that they differ.Measured in CVMs, one per image:
/sys/fs/selinuxenforce0/sys/kernel/security/lsmcapability,selinux/etc/selinuxsemanage.confonlydocker infosecurity optionsFix
Enable the whole chain on Yocto, and assert it on both backends.
There is a second failure mode behind the first, silent in the same way. Compiling SELinux in is not enough — an LSM only registers if
CONFIG_LSMnames it, and that string's default is selected byDEFAULT_SECURITY_*. Turning onSECURITYwithout naming a default lands onDEFAULT_SECURITY_DAC:— no selinux. The hooks would build and never initialize, which is exactly the class of silent no-op this PR exists to remove.
CONFIG_DEFAULT_SECURITY_SELINUXand the resultingCONFIG_LSMorder are therefore both asserted, in both fragments, so neither a defconfig change nor a newDEFAULT_SECURITY_*branch can drop selinux without failing the build.What this does and does not change
Does not change enforcement. SELinux needs a loaded policy and neither image ships one, so the state after this change is what mkosi already has today: hooks registered,
enforce=0, no policy, no security options reported by Docker. Nothing starts being denied.Does change the kernel's measurements, so it needs the same release coordination as any guest-image change.
Adds the audit subsystem to the Yocto image (
AUDIT/AUDITSYSCALL), which SELinux depends on (depends on SECURITY_NETWORK && AUDIT && NET && INET). mkosi already has it, and the Yocto guest kernel log will start carrying audit records where it carried none.To be precise about what those records are, since it is easy to read this as "SELinux starts logging": they come from the audit subsystem, not from SELinux. Counted over a full boot plus an Incus session on the mkosi image — 32 lines total:
SERVICE_START/SERVICE_STOP, from systemdNETFILTER_CFG, when something programs nftablesSYSCALL/PROCTITLENo AVC records, because AVC decisions require a loaded policy. Without one SELinux makes no access decisions and logs nothing at all;
setenforceis not a factor either way, and neither image even installs it.Verification
Merged the fragment onto a
kernel-configartifact from a real build (linux-yocto 6.18.24), and separately reproduced the mkosi path fromx86_64_defconfig, both witholddefconfigagainst Linux 6.18.40 source:SECURITYyySECURITY_NETWORKyyAUDITyyAUDITSYSCALLyySECURITY_SELINUXyyDEFAULT_SECURITY_SELINUXyyNETWORK_SECMARKyySECURITYFSyyThe two
CONFIG_LSMstrings come out byte-identical.os/mkosi/scripts/check-kernel-config.shpasses on the produced mkosi config. REUSE lint clean.Not verified: no image was built or booted with this change. The runtime numbers in the table above are from the mkosi image as it already ships, which is the state this brings Yocto to.
Relationship to #1042
Independent — this can merge in either order. Both touch the same region of
dstack-docker.cfg, so whichever lands second needs a trivial rebase: #1042 removes the deadCONFIG_SECURITY_SELINUX=yline and documents why, this PR replaces it with a working chain. #1042 also adds a shared kernel-config gate that would then cover these assertions on the Yocto side too, which today onlyos/mkosihas.