-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathsysctl.go
99 lines (86 loc) · 2.7 KB
/
sysctl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package config
import (
"fmt"
"strings"
)
func NewSysctl(key, value string) *Sysctl {
return &Sysctl{key, value}
}
// Sysctl is a generic abstraction over key value based sysctls.
type Sysctl struct {
key, value string
}
// Key returns the key of the sysctl (key=value format).
func (s *Sysctl) Key() string {
return s.key
}
// Value returns the value of the sysctl (key=value format).
func (s *Sysctl) Value() string {
return s.value
}
// Sysctls returns the parsed sysctl slice and an error if not parsable
// Some validation based on https://github.com/containers/common/blob/main/pkg/sysctl/sysctl.go
func (c *RuntimeConfig) Sysctls() ([]Sysctl, error) {
sysctls := make([]Sysctl, 0, len(c.DefaultSysctls))
for _, sysctl := range c.DefaultSysctls {
// skip empty values for sake of backwards compatibility
if sysctl == "" {
continue
}
split := strings.SplitN(sysctl, "=", 2)
if len(split) != 2 {
return nil, fmt.Errorf("%q is not in key=value format", sysctl)
}
// pinns nor runc expect sysctls of the form 'key = value', but rather
// 'key=value'
trimmed := strings.TrimSpace(split[0]) + "=" + strings.TrimSpace(split[1])
if trimmed != sysctl {
return nil, fmt.Errorf("'%s' is invalid, extra spaces found: format should be key=value", sysctl)
}
sysctls = append(sysctls, Sysctl{key: split[0], value: split[1]})
}
return sysctls, nil
}
// Namespace represents a kernel namespace name.
type Namespace string
const (
// IpcNamespace is the Linux IPC namespace.
IpcNamespace = Namespace("ipc")
// NetNamespace is the network namespace.
NetNamespace = Namespace("net")
)
var namespaces = map[string]Namespace{
"kernel.sem": IpcNamespace,
}
var prefixNamespaces = map[string]Namespace{
"kernel.shm": IpcNamespace,
"kernel.msg": IpcNamespace,
"fs.mqueue.": IpcNamespace,
"net.": NetNamespace,
}
// Validate checks that a sysctl is whitelisted because it is known to be
// namespaced by the Linux kernel. The parameters hostNet and hostIPC are used
// to forbid sysctls for pod sharing the respective namespaces with the host.
// This check is only used on sysctls defined by the user in the crio.conf
// file.
func (s *Sysctl) Validate(hostNet, hostIPC bool) error {
nsErrorFmt := "%q not allowed with host %s enabled"
if ns, found := namespaces[s.Key()]; found {
if ns == IpcNamespace && hostIPC {
return fmt.Errorf(nsErrorFmt, s.Key(), ns)
}
return nil
}
for p, ns := range prefixNamespaces {
if strings.HasPrefix(s.Key(), p) {
if ns == IpcNamespace && hostIPC {
return fmt.Errorf(nsErrorFmt, s.Key(), ns)
}
if ns == NetNamespace && hostNet {
return fmt.Errorf(nsErrorFmt, s.Key(), ns)
}
return nil
}
}
return fmt.Errorf("%s not whitelisted", s.Key())
}