/
sysctl.go
93 lines (80 loc) · 2.36 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
package config
import (
"strings"
"github.com/pkg/errors"
)
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
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 {
sysctls = append(sysctls, Sysctl{key: split[0], value: split[1]})
} else {
return nil, errors.Errorf("%q is not in key=value format", sysctl)
}
}
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 errors.Errorf(nsErrorFmt, s.Key(), ns)
}
return nil
}
for p, ns := range prefixNamespaces {
if strings.HasPrefix(s.Key(), p) {
if ns == IpcNamespace && hostIPC {
return errors.Errorf(nsErrorFmt, s.Key(), ns)
}
if ns == NetNamespace && hostNet {
return errors.Errorf(nsErrorFmt, s.Key(), ns)
}
return nil
}
}
return errors.Errorf("%s not whitelisted", s.Key())
}