Move cgroup namespace placement higher in spec builder

Moves cgroup namespace addition logic higher in buildLinuxSpec so it
runs before any custom spec adjusters (such as WithMounts).

This is necessary because subsequent spec adjusters may want to inspect
the set of namespaces to make decisions (e.g., configuring mount options
based on whether or not they are shared with the host).

Signed-off-by: Chris Henzie <chrishenzie@gmail.com>
This commit is contained in:
Chris Henzie
2026-03-10 17:14:44 -07:00
parent 3580af3c96
commit e15141a1fd
2 changed files with 54 additions and 8 deletions

View File

@@ -792,6 +792,14 @@ func (c *criService) buildLinuxSpec(
}
}()
// cgroupns is used for hiding /sys/fs/cgroup from containers.
// For compatibility, cgroupns is not used when running in cgroup v1 mode or in privileged.
// https://github.com/containers/libpod/issues/4363
// https://github.com/kubernetes/enhancements/blob/0e409b47497e398b369c281074485c8de129694f/keps/sig-node/20191118-cgroups-v2.md#cgroup-namespace
if isUnifiedCgroupsMode() && !securityContext.GetPrivileged() {
specOpts = append(specOpts, oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.CgroupNamespace}))
}
var ociSpecOpts oci.SpecOpts
if ociRuntime.CgroupWritable {
ociSpecOpts = customopts.WithMountsCgroupWritable(c.os, config, extraMounts, mountLabel, runtimeHandler)
@@ -930,14 +938,6 @@ func (c *criService) buildLinuxSpec(
annotations.DefaultCRIAnnotations(sandboxID, containerName, imageName, sandboxConfig, false)...,
)
// cgroupns is used for hiding /sys/fs/cgroup from containers.
// For compatibility, cgroupns is not used when running in cgroup v1 mode or in privileged.
// https://github.com/containers/libpod/issues/4363
// https://github.com/kubernetes/enhancements/blob/0e409b47497e398b369c281074485c8de129694f/keps/sig-node/20191118-cgroups-v2.md#cgroup-namespace
if isUnifiedCgroupsMode() && !securityContext.GetPrivileged() {
specOpts = append(specOpts, oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.CgroupNamespace}))
}
return specOpts, nil
}

View File

@@ -487,6 +487,52 @@ func TestPrivilegedBindMount(t *testing.T) {
}
}
func TestCgroupNamespace(t *testing.T) {
testPid := uint32(1234)
c := newTestCRIService()
testSandboxID := "sandbox-id"
testContainerName := "container-name"
containerConfig, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
ociRuntime := config.Runtime{}
tests := []struct {
desc string
privileged bool
expectCgroupNamespace bool
}{
{
desc: "non-privileged container should get cgroup namespace",
privileged: false,
expectCgroupNamespace: true,
},
{
desc: "privileged container should not get cgroup namespace",
privileged: true,
expectCgroupNamespace: false,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
containerConfig.Linux.SecurityContext.Privileged = tt.privileged
sandboxConfig.Linux.SecurityContext.Privileged = tt.privileged
spec, err := c.buildContainerSpec(currentPlatform, t.Name(), testSandboxID, testPid, "", testContainerName, testImageName, containerConfig, sandboxConfig, imageConfig, nil, ociRuntime, nil)
assert.NoError(t, err)
hasCgroupNS := false
for _, ns := range spec.Linux.Namespaces {
if ns.Type == runtimespec.CgroupNamespace {
hasCgroupNS = true
break
}
}
assert.Equal(t, tt.expectCgroupNamespace, hasCgroupNS)
})
}
}
func TestMountPropagation(t *testing.T) {
sharedLookupMountFn := func(string) (mount.Info, error) {