Skip to content

Commit 426aa3d

Browse files
authored
Merge pull request kubernetes#127489 from pacoxu/feature/125234
feat: Added net.ipv4.tcp_rmem and net.ipv4.tcp_wmem into safe sysctl list
2 parents 4812ea8 + e9d999d commit 426aa3d

File tree

135 files changed

+3345
-16
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+3345
-16
lines changed

pkg/kubelet/sysctl/safe_sysctls.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ var safeSysctls = []sysctl{
6060
name: "net.ipv4.tcp_keepalive_probes",
6161
kernel: utilkernel.TCPKeepAliveProbesNamespacedKernelVersion,
6262
},
63+
{
64+
name: "net.ipv4.tcp_rmem",
65+
kernel: utilkernel.TCPReceiveMemoryNamespacedKernelVersion,
66+
},
67+
{
68+
name: "net.ipv4.tcp_wmem",
69+
kernel: utilkernel.TCPTransmitMemoryNamespacedKernelVersion,
70+
},
6371
}
6472

6573
// SafeSysctlAllowlist returns the allowlist of safe sysctls and safe sysctl patterns (ending in *).

pkg/kubelet/sysctl/safe_sysctls_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ func Test_getSafeSysctlAllowlist(t *testing.T) {
7575
"net.ipv4.tcp_fin_timeout",
7676
"net.ipv4.tcp_keepalive_intvl",
7777
"net.ipv4.tcp_keepalive_probes",
78+
"net.ipv4.tcp_rmem",
79+
"net.ipv4.tcp_wmem",
7880
},
7981
},
8082
}

pkg/util/kernel/constants.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,11 @@ const TmpfsNoswapSupportKernelVersion = "6.4"
5454
// nftables mode with by default. This is not directly related to any specific kernel
5555
// commit; see https://issues.k8s.io/122743#issuecomment-1893922424
5656
const NFTablesKubeProxyKernelVersion = "5.13"
57+
58+
// TCPReceiveMemoryNamespacedKernelVersion is the kernel version in which net.ipv4.tcp_rmem was namespaced(netns).
59+
// (ref: https://github.com/torvalds/linux/commit/356d1833b638bd465672aefeb71def3ab93fc17d)
60+
const TCPReceiveMemoryNamespacedKernelVersion = "4.15"
61+
62+
// TCPTransmitMemoryNamespacedKernelVersion is the kernel version in which net.ipv4.tcp_wmem was namespaced(netns).
63+
// (ref: https://github.com/torvalds/linux/commit/356d1833b638bd465672aefeb71def3ab93fc17d)
64+
const TCPTransmitMemoryNamespacedKernelVersion = "4.15"

staging/src/k8s.io/pod-security-admission/policy/check_sysctls.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ spec.securityContext.sysctls[*].name
4747
'net.ipv4.tcp_fin_timeout'
4848
'net.ipv4.tcp_keepalive_intvl'
4949
'net.ipv4.tcp_keepalive_probes'
50+
'net.ipv4.tcp_rmem'
51+
'net.ipv4.tcp_wmem'
5052
5153
*/
5254

@@ -72,6 +74,10 @@ func CheckSysctls() Check {
7274
MinimumVersion: api.MajorMinorVersion(1, 29),
7375
CheckPod: sysctlsV1Dot29,
7476
},
77+
{
78+
MinimumVersion: api.MajorMinorVersion(1, 32),
79+
CheckPod: sysctlsV1Dot32,
80+
},
7581
},
7682
}
7783
}
@@ -84,26 +90,19 @@ var (
8490
"net.ipv4.ping_group_range",
8591
"net.ipv4.ip_unprivileged_port_start",
8692
)
87-
sysctlsAllowedV1Dot27 = sets.NewString(
88-
"kernel.shm_rmid_forced",
89-
"net.ipv4.ip_local_port_range",
90-
"net.ipv4.tcp_syncookies",
91-
"net.ipv4.ping_group_range",
92-
"net.ipv4.ip_unprivileged_port_start",
93-
"net.ipv4.ip_local_reserved_ports",
94-
)
95-
sysctlsAllowedV1Dot29 = sets.NewString(
96-
"kernel.shm_rmid_forced",
97-
"net.ipv4.ip_local_port_range",
98-
"net.ipv4.tcp_syncookies",
99-
"net.ipv4.ping_group_range",
100-
"net.ipv4.ip_unprivileged_port_start",
93+
sysctlsAllowedV1Dot27 = sysctlsAllowedV1Dot0.Union(sets.NewString(
10194
"net.ipv4.ip_local_reserved_ports",
95+
))
96+
sysctlsAllowedV1Dot29 = sysctlsAllowedV1Dot27.Union(sets.NewString(
10297
"net.ipv4.tcp_keepalive_time",
10398
"net.ipv4.tcp_fin_timeout",
10499
"net.ipv4.tcp_keepalive_intvl",
105100
"net.ipv4.tcp_keepalive_probes",
106-
)
101+
))
102+
sysctlsAllowedV1Dot32 = sysctlsAllowedV1Dot29.Union(sets.NewString(
103+
"net.ipv4.tcp_rmem",
104+
"net.ipv4.tcp_wmem",
105+
))
107106
)
108107

109108
func sysctlsV1Dot0(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) CheckResult {
@@ -118,6 +117,10 @@ func sysctlsV1Dot29(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) Che
118117
return sysctls(podMetadata, podSpec, sysctlsAllowedV1Dot29)
119118
}
120119

120+
func sysctlsV1Dot32(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) CheckResult {
121+
return sysctls(podMetadata, podSpec, sysctlsAllowedV1Dot32)
122+
}
123+
121124
func sysctls(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec, sysctls_allowed_set sets.String) CheckResult {
122125
var forbiddenSysctls []string
123126

staging/src/k8s.io/pod-security-admission/policy/check_sysctls_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,28 @@ func TestSysctls(t *testing.T) {
9696
expectReason: `forbidden sysctls`,
9797
expectDetail: `net.ipv4.tcp_keepalive_probes`,
9898
},
99+
{
100+
name: "new supported sysctls not supported: net.ipv4.tcp_rmem",
101+
pod: &corev1.Pod{Spec: corev1.PodSpec{
102+
SecurityContext: &corev1.PodSecurityContext{
103+
Sysctls: []corev1.Sysctl{{Name: "net.ipv4.tcp_rmem", Value: "4096 87380 16777216"}},
104+
},
105+
}},
106+
allowed: false,
107+
expectReason: `forbidden sysctls`,
108+
expectDetail: `net.ipv4.tcp_rmem`,
109+
},
110+
{
111+
name: "new supported sysctls not supported: net.ipv4.tcp_wmem",
112+
pod: &corev1.Pod{Spec: corev1.PodSpec{
113+
SecurityContext: &corev1.PodSecurityContext{
114+
Sysctls: []corev1.Sysctl{{Name: "net.ipv4.tcp_wmem", Value: "4096 87380 16777216"}},
115+
},
116+
}},
117+
allowed: false,
118+
expectReason: `forbidden sysctls`,
119+
expectDetail: `net.ipv4.tcp_wmem`,
120+
},
99121
}
100122

101123
for _, tc := range tests {
@@ -244,3 +266,62 @@ func TestSysctls_1_29(t *testing.T) {
244266
})
245267
}
246268
}
269+
270+
func TestSysctls_1_32(t *testing.T) {
271+
tests := []struct {
272+
name string
273+
pod *corev1.Pod
274+
allowed bool
275+
expectReason string
276+
expectDetail string
277+
}{
278+
{
279+
name: "forbidden sysctls",
280+
pod: &corev1.Pod{Spec: corev1.PodSpec{
281+
SecurityContext: &corev1.PodSecurityContext{
282+
Sysctls: []corev1.Sysctl{{Name: "a"}, {Name: "b"}},
283+
},
284+
}},
285+
allowed: false,
286+
expectReason: `forbidden sysctls`,
287+
expectDetail: `a, b`,
288+
},
289+
{
290+
name: "new supported sysctls: net.ipv4.tcp_rmem",
291+
pod: &corev1.Pod{Spec: corev1.PodSpec{
292+
SecurityContext: &corev1.PodSecurityContext{
293+
Sysctls: []corev1.Sysctl{{Name: "net.ipv4.tcp_rmem", Value: "4096 87380 16777216"}},
294+
},
295+
}},
296+
allowed: true,
297+
},
298+
{
299+
name: "new supported sysctls: net.ipv4.tcp_wmem",
300+
pod: &corev1.Pod{Spec: corev1.PodSpec{
301+
SecurityContext: &corev1.PodSecurityContext{
302+
Sysctls: []corev1.Sysctl{{Name: "net.ipv4.tcp_wmem", Value: "4096 65536 16777216"}},
303+
},
304+
}},
305+
allowed: true,
306+
},
307+
}
308+
309+
for _, tc := range tests {
310+
t.Run(tc.name, func(t *testing.T) {
311+
result := sysctlsV1Dot32(&tc.pod.ObjectMeta, &tc.pod.Spec)
312+
if !tc.allowed {
313+
if result.Allowed {
314+
t.Fatal("expected disallowed")
315+
}
316+
if e, a := tc.expectReason, result.ForbiddenReason; e != a {
317+
t.Errorf("expected\n%s\ngot\n%s", e, a)
318+
}
319+
if e, a := tc.expectDetail, result.ForbiddenDetail; e != a {
320+
t.Errorf("expected\n%s\ngot\n%s", e, a)
321+
}
322+
} else if !result.Allowed {
323+
t.Fatal("expected allowed")
324+
}
325+
})
326+
}
327+
}

staging/src/k8s.io/pod-security-admission/test/fixtures_sysctls.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,39 @@ func init() {
156156
fixtureKey{level: api.LevelBaseline, version: api.MajorMinorVersion(1, 29), check: "sysctls"},
157157
fixtureDataV1Dot29,
158158
)
159+
160+
fixtureDataV1Dot32 := fixtureGenerator{
161+
expectErrorSubstring: "forbidden sysctl",
162+
generatePass: func(p *corev1.Pod) []*corev1.Pod {
163+
if p.Spec.SecurityContext == nil {
164+
p.Spec.SecurityContext = &corev1.PodSecurityContext{}
165+
}
166+
return []*corev1.Pod{
167+
// security context with no sysctls
168+
tweak(p, func(p *corev1.Pod) { p.Spec.SecurityContext.Sysctls = nil }),
169+
// sysctls with name="net.ipv4.tcp_rmem", "net.ipv4.tcp_wmem"
170+
tweak(p, func(p *corev1.Pod) {
171+
p.Spec.SecurityContext.Sysctls = []corev1.Sysctl{
172+
{Name: "net.ipv4.tcp_rmem", Value: "4096 87380 16777216"},
173+
{Name: "net.ipv4.tcp_wmem", Value: "4096 65536 16777216"},
174+
}
175+
}),
176+
}
177+
},
178+
generateFail: func(p *corev1.Pod) []*corev1.Pod {
179+
if p.Spec.SecurityContext == nil {
180+
p.Spec.SecurityContext = &corev1.PodSecurityContext{}
181+
}
182+
return []*corev1.Pod{
183+
// sysctls with out of allowed name
184+
tweak(p, func(p *corev1.Pod) {
185+
p.Spec.SecurityContext.Sysctls = []corev1.Sysctl{{Name: "othersysctl", Value: "other"}}
186+
}),
187+
}
188+
},
189+
}
190+
registerFixtureGenerator(
191+
fixtureKey{level: api.LevelBaseline, version: api.MajorMinorVersion(1, 32), check: "sysctls"},
192+
fixtureDataV1Dot32,
193+
)
159194
}

staging/src/k8s.io/pod-security-admission/test/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import (
3737
)
3838

3939
const (
40-
newestMinorVersionToTest = 31
40+
newestMinorVersionToTest = 32
4141
podOSBasedRestrictionEnabledVersion = 29
4242
)
4343

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
annotations:
5+
container.apparmor.security.beta.kubernetes.io/container1: unconfined
6+
name: apparmorprofile0
7+
spec:
8+
containers:
9+
- image: registry.k8s.io/pause
10+
name: container1
11+
initContainers:
12+
- image: registry.k8s.io/pause
13+
name: initcontainer1
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
annotations:
5+
container.apparmor.security.beta.kubernetes.io/initcontainer1: unconfined
6+
name: apparmorprofile1
7+
spec:
8+
containers:
9+
- image: registry.k8s.io/pause
10+
name: container1
11+
initContainers:
12+
- image: registry.k8s.io/pause
13+
name: initcontainer1
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: capabilities_baseline0
5+
spec:
6+
containers:
7+
- image: registry.k8s.io/pause
8+
name: container1
9+
securityContext:
10+
capabilities:
11+
add:
12+
- NET_RAW
13+
initContainers:
14+
- image: registry.k8s.io/pause
15+
name: initcontainer1
16+
securityContext:
17+
capabilities: {}
18+
securityContext: {}

0 commit comments

Comments
 (0)