diff --git a/pkg/securitycontext/util.go b/pkg/securitycontext/util.go index 28771b6df27..5e000f93333 100644 --- a/pkg/securitycontext/util.go +++ b/pkg/securitycontext/util.go @@ -17,6 +17,10 @@ limitations under the License. package securitycontext import ( + "fmt" + "os" + "sync" + v1 "k8s.io/api/core/v1" ) @@ -188,21 +192,32 @@ func AddNoNewPrivileges(sc *v1.SecurityContext) bool { var ( // These *must* be kept in sync with moby/moby. - // https://github.com/moby/moby/blob/master/oci/defaults.go#L105-L124 - // @jessfraz will watch changes to those files upstream. - defaultMaskedPaths = []string{ - "/proc/asound", - "/proc/acpi", - "/proc/kcore", - "/proc/keys", - "/proc/latency_stats", - "/proc/timer_list", - "/proc/timer_stats", - "/proc/sched_debug", - "/proc/scsi", - "/sys/firmware", - "/sys/devices/virtual/powercap", - } + // https://github.com/moby/moby/blob/ecb03c4cdae6f323150fc11b303dcc5dc4d82416/oci/defaults.go#L190-L218 + defaultMaskedPaths = sync.OnceValue(func() []string { + maskedPaths := []string{ + "/proc/asound", + "/proc/acpi", + "/proc/interrupts", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/proc/scsi", + "/sys/firmware", + "/sys/devices/virtual/powercap", + } + + for _, cpu := range possibleCPUs() { + path := fmt.Sprintf("/sys/devices/system/cpu/cpu%d/thermal_throttle", cpu) + if _, err := os.Stat(path); err == nil { + maskedPaths = append(maskedPaths, path) + } + } + + return maskedPaths + }) defaultReadonlyPaths = []string{ "/proc/bus", "/proc/fs", @@ -221,7 +236,7 @@ func ConvertToRuntimeMaskedPaths(opt *v1.ProcMountType) []string { } // Otherwise, add the default masked paths to the runtime security context. - return defaultMaskedPaths + return defaultMaskedPaths() } // ConvertToRuntimeReadonlyPaths converts the ProcMountType to the specified or default diff --git a/pkg/securitycontext/util_darwin.go b/pkg/securitycontext/util_darwin.go new file mode 100644 index 00000000000..9d14502acb7 --- /dev/null +++ b/pkg/securitycontext/util_darwin.go @@ -0,0 +1,21 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package securitycontext + +func possibleCPUs() []int { + return nil +} diff --git a/pkg/securitycontext/util_linux.go b/pkg/securitycontext/util_linux.go new file mode 100644 index 00000000000..278c81ee2c1 --- /dev/null +++ b/pkg/securitycontext/util_linux.go @@ -0,0 +1,74 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package securitycontext + +import ( + "os" + "runtime" + "strconv" + "strings" + "sync" +) + +// possibleCPUs returns the number of possible CPUs on this host. +func possibleCPUs() (cpus []int) { + if ncpu := possibleCPUsParsed(); ncpu != nil { + return ncpu + } + + for i := range runtime.NumCPU() { + cpus = append(cpus, i) + } + + return cpus +} + +// possibleCPUsParsed is parsing the amount of possible CPUs on this host from +// /sys/devices. +var possibleCPUsParsed = sync.OnceValue(func() (cpus []int) { + data, err := os.ReadFile("/sys/devices/system/cpu/possible") + if err != nil { + return nil + } + + ranges := strings.SplitSeq(strings.TrimSpace(string(data)), ",") + + for r := range ranges { + if rStart, rEnd, ok := strings.Cut(r, "-"); !ok { + cpu, err := strconv.Atoi(rStart) + if err != nil { + return nil + } + cpus = append(cpus, cpu) + } else { + var start, end int + start, err := strconv.Atoi(rStart) + if err != nil { + return nil + } + end, err = strconv.Atoi(rEnd) + if err != nil { + return nil + } + for i := start; i <= end; i++ { + cpus = append(cpus, i) + } + } + } + + return cpus +}) diff --git a/pkg/securitycontext/util_test.go b/pkg/securitycontext/util_test.go index 01ae555b955..ec4159f6e73 100644 --- a/pkg/securitycontext/util_test.go +++ b/pkg/securitycontext/util_test.go @@ -73,11 +73,11 @@ func TestConvertToRuntimeMaskedPaths(t *testing.T) { }{ "procMount nil": { pm: nil, - expect: defaultMaskedPaths, + expect: defaultMaskedPaths(), }, "procMount default": { pm: &dPM, - expect: defaultMaskedPaths, + expect: defaultMaskedPaths(), }, "procMount unmasked": { pm: &uPM, diff --git a/pkg/securitycontext/util_windows.go b/pkg/securitycontext/util_windows.go new file mode 100644 index 00000000000..9d14502acb7 --- /dev/null +++ b/pkg/securitycontext/util_windows.go @@ -0,0 +1,21 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package securitycontext + +func possibleCPUs() []int { + return nil +}