github.com/akerouanton/docker@v1.11.0-rc3/daemon/caps/utils_unix.go (about) 1 // +build !windows 2 3 package caps 4 5 import ( 6 "fmt" 7 "strings" 8 9 "github.com/docker/docker/pkg/stringutils" 10 "github.com/syndtr/gocapability/capability" 11 ) 12 13 var capabilityList Capabilities 14 15 func init() { 16 last := capability.CAP_LAST_CAP 17 // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap 18 if last == capability.Cap(63) { 19 last = capability.CAP_BLOCK_SUSPEND 20 } 21 for _, cap := range capability.List() { 22 if cap > last { 23 continue 24 } 25 capabilityList = append(capabilityList, 26 &CapabilityMapping{ 27 Key: "CAP_" + strings.ToUpper(cap.String()), 28 Value: cap, 29 }, 30 ) 31 } 32 } 33 34 type ( 35 // CapabilityMapping maps linux capability name to its value of capability.Cap type 36 // Capabilities is one of the security systems in Linux Security Module (LSM) 37 // framework provided by the kernel. 38 // For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html 39 CapabilityMapping struct { 40 Key string `json:"key,omitempty"` 41 Value capability.Cap `json:"value,omitempty"` 42 } 43 // Capabilities contains all CapabilityMapping 44 Capabilities []*CapabilityMapping 45 ) 46 47 // String returns <key> of CapabilityMapping 48 func (c *CapabilityMapping) String() string { 49 return c.Key 50 } 51 52 // GetCapability returns CapabilityMapping which contains specific key 53 func GetCapability(key string) *CapabilityMapping { 54 for _, capp := range capabilityList { 55 if capp.Key == key { 56 cpy := *capp 57 return &cpy 58 } 59 } 60 return nil 61 } 62 63 // GetAllCapabilities returns all of the capabilities 64 func GetAllCapabilities() []string { 65 output := make([]string, len(capabilityList)) 66 for i, capability := range capabilityList { 67 output[i] = capability.String() 68 } 69 return output 70 } 71 72 // TweakCapabilities can tweak capabilities by adding or dropping capabilities 73 // based on the basics capabilities. 74 func TweakCapabilities(basics, adds, drops []string) ([]string, error) { 75 var ( 76 newCaps []string 77 allCaps = GetAllCapabilities() 78 ) 79 80 // FIXME(tonistiigi): docker format is without CAP_ prefix, oci is with prefix 81 // Currently they are mixed in here. We should do conversion in one place. 82 83 // look for invalid cap in the drop list 84 for _, cap := range drops { 85 if strings.ToLower(cap) == "all" { 86 continue 87 } 88 89 if !stringutils.InSlice(allCaps, "CAP_"+cap) { 90 return nil, fmt.Errorf("Unknown capability drop: %q", cap) 91 } 92 } 93 94 // handle --cap-add=all 95 if stringutils.InSlice(adds, "all") { 96 basics = allCaps 97 } 98 99 if !stringutils.InSlice(drops, "all") { 100 for _, cap := range basics { 101 // skip `all` already handled above 102 if strings.ToLower(cap) == "all" { 103 continue 104 } 105 106 // if we don't drop `all`, add back all the non-dropped caps 107 if !stringutils.InSlice(drops, cap[4:]) { 108 newCaps = append(newCaps, strings.ToUpper(cap)) 109 } 110 } 111 } 112 113 for _, cap := range adds { 114 // skip `all` already handled above 115 if strings.ToLower(cap) == "all" { 116 continue 117 } 118 119 cap = "CAP_" + cap 120 121 if !stringutils.InSlice(allCaps, cap) { 122 return nil, fmt.Errorf("Unknown capability to add: %q", cap) 123 } 124 125 // add cap if not already in the list 126 if !stringutils.InSlice(newCaps, cap) { 127 newCaps = append(newCaps, strings.ToUpper(cap)) 128 } 129 } 130 return newCaps, nil 131 }