-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils_unix.go
131 lines (111 loc) · 3.12 KB
/
utils_unix.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// +build !windows
package caps
import (
"fmt"
"strings"
"github.com/docker/docker/pkg/stringutils"
"github.com/syndtr/gocapability/capability"
)
var capabilityList Capabilities
func init() {
last := capability.CAP_LAST_CAP
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
if last == capability.Cap(63) {
last = capability.CAP_BLOCK_SUSPEND
}
for _, cap := range capability.List() {
if cap > last {
continue
}
capabilityList = append(capabilityList,
&CapabilityMapping{
Key: "CAP_" + strings.ToUpper(cap.String()),
Value: cap,
},
)
}
}
type (
// CapabilityMapping maps linux capability name to its value of capability.Cap type
// Capabilities is one of the security systems in Linux Security Module (LSM)
// framework provided by the kernel.
// For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
CapabilityMapping struct {
Key string `json:"key,omitempty"`
Value capability.Cap `json:"value,omitempty"`
}
// Capabilities contains all CapabilityMapping
Capabilities []*CapabilityMapping
)
// String returns <key> of CapabilityMapping
func (c *CapabilityMapping) String() string {
return c.Key
}
// GetCapability returns CapabilityMapping which contains specific key
func GetCapability(key string) *CapabilityMapping {
for _, capp := range capabilityList {
if capp.Key == key {
cpy := *capp
return &cpy
}
}
return nil
}
// GetAllCapabilities returns all of the capabilities
func GetAllCapabilities() []string {
output := make([]string, len(capabilityList))
for i, capability := range capabilityList {
output[i] = capability.String()
}
return output
}
// TweakCapabilities can tweak capabilities by adding or dropping capabilities
// based on the basics capabilities.
func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
var (
newCaps []string
allCaps = GetAllCapabilities()
)
// FIXME(tonistiigi): docker format is without CAP_ prefix, oci is with prefix
// Currently they are mixed in here. We should do conversion in one place.
// look for invalid cap in the drop list
for _, cap := range drops {
if strings.ToLower(cap) == "all" {
continue
}
if !stringutils.InSlice(allCaps, "CAP_"+cap) {
return nil, fmt.Errorf("Unknown capability drop: %q", cap)
}
}
// handle --cap-add=all
if stringutils.InSlice(adds, "all") {
basics = allCaps
}
if !stringutils.InSlice(drops, "all") {
for _, cap := range basics {
// skip `all` already handled above
if strings.ToLower(cap) == "all" {
continue
}
// if we don't drop `all`, add back all the non-dropped caps
if !stringutils.InSlice(drops, cap[4:]) {
newCaps = append(newCaps, strings.ToUpper(cap))
}
}
}
for _, cap := range adds {
// skip `all` already handled above
if strings.ToLower(cap) == "all" {
continue
}
cap = "CAP_" + cap
if !stringutils.InSlice(allCaps, cap) {
return nil, fmt.Errorf("Unknown capability to add: %q", cap)
}
// add cap if not already in the list
if !stringutils.InSlice(newCaps, cap) {
newCaps = append(newCaps, strings.ToUpper(cap))
}
}
return newCaps, nil
}