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