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