github.com/moby/docker@v26.1.3+incompatible/oci/caps/utils.go (about) 1 package caps // import "github.com/docker/docker/oci/caps" 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/docker/docker/errdefs" 8 ) 9 10 var ( 11 allCaps []string 12 13 // knownCapabilities is a map of all known capabilities, using capability 14 // name as index. Nil values indicate that the capability is known, but either 15 // not supported by the Kernel, or not available in the current environment, 16 // for example, when running Docker-in-Docker with restricted capabilities. 17 // 18 // Capabilities are one of the security systems in Linux Security Module (LSM) 19 // framework provided by the kernel. 20 // For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html 21 knownCaps map[string]*struct{} 22 ) 23 24 // GetAllCapabilities returns all capabilities that are availeble in the current 25 // environment. 26 func GetAllCapabilities() []string { 27 initCaps() 28 return allCaps 29 } 30 31 // knownCapabilities returns a map of all known capabilities, using capability 32 // name as index. Nil values indicate that the capability is known, but either 33 // not supported by the Kernel, or not available in the current environment, for 34 // example, when running Docker-in-Docker with restricted capabilities. 35 func knownCapabilities() map[string]*struct{} { 36 initCaps() 37 return knownCaps 38 } 39 40 // inSlice tests whether a string is contained in a slice of strings or not. 41 func inSlice(slice []string, s string) bool { 42 for _, ss := range slice { 43 if s == ss { 44 return true 45 } 46 } 47 return false 48 } 49 50 const allCapabilities = "ALL" 51 52 // NormalizeLegacyCapabilities normalizes, and validates CapAdd/CapDrop capabilities 53 // by upper-casing them, and adding a CAP_ prefix (if not yet present). 54 // 55 // This function also accepts the "ALL" magic-value, that's used by CapAdd/CapDrop. 56 func NormalizeLegacyCapabilities(caps []string) ([]string, error) { 57 var ( 58 normalized []string 59 capabilityList = knownCapabilities() 60 ) 61 62 for _, c := range caps { 63 c = strings.ToUpper(c) 64 if c == allCapabilities { 65 normalized = append(normalized, c) 66 continue 67 } 68 if !strings.HasPrefix(c, "CAP_") { 69 c = "CAP_" + c 70 } 71 if v, ok := capabilityList[c]; !ok { 72 return nil, errdefs.InvalidParameter(fmt.Errorf("unknown capability: %q", c)) 73 } else if v == nil { 74 return nil, errdefs.InvalidParameter(fmt.Errorf("capability not supported by your kernel or not available in the current environment: %q", c)) 75 } 76 normalized = append(normalized, c) 77 } 78 return normalized, nil 79 } 80 81 // TweakCapabilities tweaks capabilities by adding, dropping, or overriding 82 // capabilities in the basics capabilities list. 83 func TweakCapabilities(basics, adds, drops []string, privileged bool) ([]string, error) { 84 switch { 85 case privileged: 86 // Privileged containers get all capabilities 87 return GetAllCapabilities(), nil 88 case len(adds) == 0 && len(drops) == 0: 89 // Nothing to tweak; we're done 90 return basics, nil 91 } 92 93 capDrop, err := NormalizeLegacyCapabilities(drops) 94 if err != nil { 95 return nil, err 96 } 97 capAdd, err := NormalizeLegacyCapabilities(adds) 98 if err != nil { 99 return nil, err 100 } 101 102 var caps []string 103 104 switch { 105 case inSlice(capAdd, allCapabilities): 106 // Add all capabilities except ones on capDrop 107 for _, c := range GetAllCapabilities() { 108 if !inSlice(capDrop, c) { 109 caps = append(caps, c) 110 } 111 } 112 case inSlice(capDrop, allCapabilities): 113 // "Drop" all capabilities; use what's in capAdd instead 114 caps = capAdd 115 default: 116 // First drop some capabilities 117 for _, c := range basics { 118 if !inSlice(capDrop, c) { 119 caps = append(caps, c) 120 } 121 } 122 // Then add the list of capabilities from capAdd 123 caps = append(caps, capAdd...) 124 } 125 return caps, nil 126 }