mark net.ipv4.tcp_keepalive_time as a safe sysctl

This commit is contained in:
cyclinder 2023-07-11 11:43:11 +08:00
parent 36b474b008
commit 0167a9f833
2 changed files with 134 additions and 26 deletions

View File

@ -25,24 +25,33 @@ import (
"k8s.io/kubernetes/pkg/proxy/ipvs"
)
// refer to https://github.com/torvalds/linux/commit/122ff243f5f104194750ecbc76d5946dd1eec934.
const ipLocalReservedPortsMinNamespacedKernelVersion = "3.16"
var safeSysctls = []string{
"kernel.shm_rmid_forced",
"net.ipv4.ip_local_port_range",
"net.ipv4.tcp_syncookies",
"net.ipv4.ping_group_range",
"net.ipv4.ip_unprivileged_port_start",
type sysctl struct {
// the name of sysctl
name string
// the minimum kernel version where the sysctl is available
kernel string
}
var safeSysctlsIncludeReservedPorts = []string{
"kernel.shm_rmid_forced",
"net.ipv4.ip_local_port_range",
"net.ipv4.tcp_syncookies",
"net.ipv4.ping_group_range",
"net.ipv4.ip_unprivileged_port_start",
"net.ipv4.ip_local_reserved_ports",
var safeSysctls = []sysctl{
{
name: "kernel.shm_rmid_forced",
}, {
name: "net.ipv4.ip_local_port_range",
}, {
name: "net.ipv4.tcp_syncookies",
}, {
name: "net.ipv4.ping_group_range",
}, {
name: "net.ipv4.ip_unprivileged_port_start",
}, {
name: "net.ipv4.ip_local_reserved_ports",
// refer to https://github.com/torvalds/linux/commit/122ff243f5f104194750ecbc76d5946dd1eec934.
kernel: "3.16",
}, {
name: "net.ipv4.tcp_keepalive_time",
// refer to https://github.com/torvalds/linux/commit/13b287e8d1cad951634389f85b8c9b816bd3bb1e.
kernel: "4.5",
},
}
// SafeSysctlAllowlist returns the allowlist of safe sysctls and safe sysctl patterns (ending in *).
@ -51,19 +60,32 @@ var safeSysctlsIncludeReservedPorts = []string{
// - it is namespaced in the container or the pod
// - it is isolated, i.e. has no influence on any other pod on the same node.
func SafeSysctlAllowlist() []string {
if goruntime.GOOS == "linux" {
// make sure we're on a new enough kernel that the ip_local_reserved_ports sysctl is namespaced
kernelVersion, err := getKernelVersion()
if err != nil {
klog.ErrorS(err, "Failed to get kernel version, dropping net.ipv4.ip_local_reserved_ports from safe sysctl list")
return safeSysctls
if goruntime.GOOS != "linux" {
return nil
}
return getSafeSysctlAllowlist(getKernelVersion)
}
func getSafeSysctlAllowlist(getVersion func() (*version.Version, error)) []string {
kernelVersion, err := getVersion()
if err != nil {
klog.ErrorS(err, "failed to get kernel version, unable to determine which sysctls are available")
}
var safeSysctlAllowlist []string
for _, sc := range safeSysctls {
if sc.kernel == "" {
safeSysctlAllowlist = append(safeSysctlAllowlist, sc.name)
continue
}
if kernelVersion.LessThan(version.MustParseGeneric(ipLocalReservedPortsMinNamespacedKernelVersion)) {
klog.ErrorS(nil, "Kernel version is too old, dropping net.ipv4.ip_local_reserved_ports from safe sysctl list", "kernelVersion", kernelVersion)
return safeSysctls
if kernelVersion != nil && kernelVersion.AtLeast(version.MustParseGeneric(sc.kernel)) {
safeSysctlAllowlist = append(safeSysctlAllowlist, sc.name)
} else {
klog.ErrorS(nil, "kernel version is too small, dropping the sysctl from safe sysctl list", "kernelVersion", kernelVersion, "sysctl", sc.name)
}
}
return safeSysctlsIncludeReservedPorts
return safeSysctlAllowlist
}
func getKernelVersion() (*version.Version, error) {
@ -71,6 +93,7 @@ func getKernelVersion() (*version.Version, error) {
if err != nil {
return nil, fmt.Errorf("failed to get kernel version: %w", err)
}
kernelVersion, err := version.ParseGeneric(kernelVersionStr)
if err != nil {
return nil, fmt.Errorf("failed to parse kernel version: %w", err)

View File

@ -0,0 +1,85 @@
/*
Copyright 2016 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 sysctl
import (
"fmt"
"reflect"
"testing"
"k8s.io/apimachinery/pkg/util/version"
)
func Test_getSafeSysctlAllowlist(t *testing.T) {
tests := []struct {
name string
getVersion func() (*version.Version, error)
want []string
}{
{
name: "failed to get kernelVersion, only return safeSysctls with no kernelVersion limit",
getVersion: func() (*version.Version, error) {
return nil, fmt.Errorf("fork error")
},
want: []string{
"kernel.shm_rmid_forced",
"net.ipv4.ip_local_port_range",
"net.ipv4.tcp_syncookies",
"net.ipv4.ping_group_range",
"net.ipv4.ip_unprivileged_port_start",
},
},
{
name: "kernelVersion is 3.18.0, return safeSysctls with no kernelVersion limit and net.ipv4.ip_local_reserved_ports",
getVersion: func() (*version.Version, error) {
kernelVersionStr := "3.18.0-957.27.2.el7.x86_64"
return version.ParseGeneric(kernelVersionStr)
},
want: []string{
"kernel.shm_rmid_forced",
"net.ipv4.ip_local_port_range",
"net.ipv4.tcp_syncookies",
"net.ipv4.ping_group_range",
"net.ipv4.ip_unprivileged_port_start",
"net.ipv4.ip_local_reserved_ports",
},
},
{
name: "kernelVersion is 5.15.0, return safeSysctls with no kernelVersion limit and net.ipv4.ip_local_reserved_ports and net.ipv4.tcp_keepalive_time",
getVersion: func() (*version.Version, error) {
kernelVersionStr := "5.15.0-75-generic"
return version.ParseGeneric(kernelVersionStr)
},
want: []string{
"kernel.shm_rmid_forced",
"net.ipv4.ip_local_port_range",
"net.ipv4.tcp_syncookies",
"net.ipv4.ping_group_range",
"net.ipv4.ip_unprivileged_port_start",
"net.ipv4.ip_local_reserved_ports",
"net.ipv4.tcp_keepalive_time",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getSafeSysctlAllowlist(tt.getVersion); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getSafeSysctlAllowlist() = %v, want %v", got, tt.want)
}
})
}
}