123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- // +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
- }
|