diff --git a/oci/caps/utils.go b/oci/caps/utils.go index eb32c0b3eb..8e71bf3840 100644 --- a/oci/caps/utils.go +++ b/oci/caps/utils.go @@ -8,52 +8,44 @@ import ( "github.com/syndtr/gocapability/capability" ) -var capabilityList Capabilities +var ( + allCaps []string -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 + // capabilityList maps linux capability name to its value of capability.Cap + // type. This list contains nil entries for capabilities that are known, but + // not supported by the current kernel. // 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 + capabilityList map[string]*capability.Cap ) -// String returns of CapabilityMapping -func (c *CapabilityMapping) String() string { - return c.Key +func init() { + last := capability.CAP_LAST_CAP + rawCaps := capability.List() + allCaps = make([]string, min(int(last+1), len(rawCaps))) + capabilityList = make(map[string]*capability.Cap, len(rawCaps)) + for i, c := range rawCaps { + capName := "CAP_" + strings.ToUpper(c.String()) + if c > last { + capabilityList[capName] = nil + continue + } + allCaps[i] = capName + capabilityList[capName] = &c + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b } // 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 + return allCaps } // inSlice tests whether a string is contained in a slice of strings or not. @@ -75,7 +67,6 @@ const allCapabilities = "ALL" func NormalizeLegacyCapabilities(caps []string) ([]string, error) { var normalized []string - valids := GetAllCapabilities() for _, c := range caps { c = strings.ToUpper(c) if c == allCapabilities { @@ -85,8 +76,10 @@ func NormalizeLegacyCapabilities(caps []string) ([]string, error) { if !strings.HasPrefix(c, "CAP_") { c = "CAP_" + c } - if !inSlice(valids, c) { + if v, ok := capabilityList[c]; !ok { return nil, errdefs.InvalidParameter(fmt.Errorf("unknown capability: %q", c)) + } else if v == nil { + return nil, errdefs.InvalidParameter(fmt.Errorf("capability not supported by your kernel: %q", c)) } normalized = append(normalized, c) }