From e543f1957caa24d5b254ef664885ceb5e4033375 Mon Sep 17 00:00:00 2001 From: "Patrick W. Healy" Date: Mon, 27 Jul 2026 12:28:58 +0000 Subject: [PATCH 1/2] agent: preserve mapped device ownership Enable containerd to derive mapped device ownership from the pod security context so non-root workloads retain access to devices such as KVM. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f55fcca7-1344-4ce2-8f86-06e677157287 --- .../phases/nodestart/assets/containerd.toml | 3 +++ pkg/agent/phases/nodestart/cri_test.go | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/pkg/agent/phases/nodestart/assets/containerd.toml b/pkg/agent/phases/nodestart/assets/containerd.toml index 4fde3521f..5481e48d1 100644 --- a/pkg/agent/phases/nodestart/assets/containerd.toml +++ b/pkg/agent/phases/nodestart/assets/containerd.toml @@ -3,6 +3,9 @@ imports = ["/etc/containerd/conf.d/*.toml"] oom_score = 0 version = 2 +[plugins.'io.containerd.cri.v1.runtime'] +device_ownership_from_security_context = true + [plugins."io.containerd.grpc.v1.cri"] sandbox_image = "{{.SandboxImage}}" diff --git a/pkg/agent/phases/nodestart/cri_test.go b/pkg/agent/phases/nodestart/cri_test.go index 01bf6478c..e1a33e0a6 100644 --- a/pkg/agent/phases/nodestart/cri_test.go +++ b/pkg/agent/phases/nodestart/cri_test.go @@ -35,6 +35,24 @@ func TestConfigureContainerdWritesGantryHostsConfig(t *testing.T) { require.Equal(t, os.FileMode(0o644), info.Mode().Perm()) } +func TestConfigureContainerdEnablesDeviceOwnershipFromSecurityContext(t *testing.T) { + t.Parallel() + + machineDir := t.TempDir() + goalState := &goalstates.NodeStart{ + MachineDir: machineDir, + Containerd: goalstates.ResolveContainerd(""), + } + + require.NoError(t, ConfigureContainerd(goalState).Do(context.Background())) + + path := filepath.Join(machineDir, goalstates.ContainerdConfigPath) + data, err := os.ReadFile(path) + require.NoError(t, err) + require.Contains(t, string(data), `[plugins.'io.containerd.cri.v1.runtime'] +device_ownership_from_security_context = true`) +} + func TestConfigureContainerdUpdatesManagedGantryHostsConfig(t *testing.T) { t.Parallel() From d2eb365b108cbb24bd26ca671646e37dc3d7bf1f Mon Sep 17 00:00:00 2001 From: "Patrick W. Healy" Date: Thu, 6 Aug 2026 17:08:11 +0000 Subject: [PATCH 2/2] Fix containerd device ownership config section Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7b5e2080-53bb-4e91-93b1-56dac5f0e214 --- .../phases/nodestart/assets/containerd.toml | 4 +--- pkg/agent/phases/nodestart/cri_test.go | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pkg/agent/phases/nodestart/assets/containerd.toml b/pkg/agent/phases/nodestart/assets/containerd.toml index 5481e48d1..c728daf02 100644 --- a/pkg/agent/phases/nodestart/assets/containerd.toml +++ b/pkg/agent/phases/nodestart/assets/containerd.toml @@ -3,10 +3,8 @@ imports = ["/etc/containerd/conf.d/*.toml"] oom_score = 0 version = 2 -[plugins.'io.containerd.cri.v1.runtime'] -device_ownership_from_security_context = true - [plugins."io.containerd.grpc.v1.cri"] +device_ownership_from_security_context = true sandbox_image = "{{.SandboxImage}}" [plugins."io.containerd.grpc.v1.cri".containerd] diff --git a/pkg/agent/phases/nodestart/cri_test.go b/pkg/agent/phases/nodestart/cri_test.go index e1a33e0a6..0f40a2aa9 100644 --- a/pkg/agent/phases/nodestart/cri_test.go +++ b/pkg/agent/phases/nodestart/cri_test.go @@ -7,6 +7,7 @@ import ( "context" "os" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/require" @@ -49,8 +50,20 @@ func TestConfigureContainerdEnablesDeviceOwnershipFromSecurityContext(t *testing path := filepath.Join(machineDir, goalstates.ContainerdConfigPath) data, err := os.ReadFile(path) require.NoError(t, err) - require.Contains(t, string(data), `[plugins.'io.containerd.cri.v1.runtime'] -device_ownership_from_security_context = true`) + + config := string(data) + + const sectionHeader = `[plugins."io.containerd.grpc.v1.cri"]` + + sectionStart := strings.Index(config, sectionHeader) + require.NotEqual(t, -1, sectionStart) + + section := config[sectionStart+len(sectionHeader):] + if sectionEnd := strings.Index(section, "\n["); sectionEnd >= 0 { + section = section[:sectionEnd] + } + + require.Contains(t, section, "device_ownership_from_security_context = true") } func TestConfigureContainerdUpdatesManagedGantryHostsConfig(t *testing.T) {