github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/capabilities/capabilities.go (about) 1 //go:build linux 2 // +build linux 3 4 package capabilities 5 6 import ( 7 "sort" 8 "strings" 9 10 "github.com/opencontainers/runc/libcontainer/configs" 11 "github.com/sirupsen/logrus" 12 "github.com/syndtr/gocapability/capability" 13 ) 14 15 const allCapabilityTypes = capability.CAPS | capability.BOUNDING | capability.AMBIENT 16 17 var ( 18 capabilityMap map[string]capability.Cap 19 capTypes = []capability.CapType{ 20 capability.BOUNDING, 21 capability.PERMITTED, 22 capability.INHERITABLE, 23 capability.EFFECTIVE, 24 capability.AMBIENT, 25 } 26 ) 27 28 func init() { 29 capabilityMap = make(map[string]capability.Cap, capability.CAP_LAST_CAP+1) 30 for _, c := range capability.List() { 31 if c > capability.CAP_LAST_CAP { 32 continue 33 } 34 capabilityMap["CAP_"+strings.ToUpper(c.String())] = c 35 } 36 } 37 38 // KnownCapabilities returns the list of the known capabilities. 39 // Used by `runc features`. 40 func KnownCapabilities() []string { 41 list := capability.List() 42 res := make([]string, len(list)) 43 for i, c := range list { 44 res[i] = "CAP_" + strings.ToUpper(c.String()) 45 } 46 return res 47 } 48 49 // New creates a new Caps from the given Capabilities config. Unknown Capabilities 50 // or Capabilities that are unavailable in the current environment are ignored, 51 // printing a warning instead. 52 func New(capConfig *configs.Capabilities) (*Caps, error) { 53 var ( 54 err error 55 c Caps 56 ) 57 58 unknownCaps := make(map[string]struct{}) 59 c.caps = map[capability.CapType][]capability.Cap{ 60 capability.BOUNDING: capSlice(capConfig.Bounding, unknownCaps), 61 capability.EFFECTIVE: capSlice(capConfig.Effective, unknownCaps), 62 capability.INHERITABLE: capSlice(capConfig.Inheritable, unknownCaps), 63 capability.PERMITTED: capSlice(capConfig.Permitted, unknownCaps), 64 capability.AMBIENT: capSlice(capConfig.Ambient, unknownCaps), 65 } 66 if c.pid, err = capability.NewPid2(0); err != nil { 67 return nil, err 68 } 69 if err = c.pid.Load(); err != nil { 70 return nil, err 71 } 72 if len(unknownCaps) > 0 { 73 logrus.Warn("ignoring unknown or unavailable capabilities: ", mapKeys(unknownCaps)) 74 } 75 return &c, nil 76 } 77 78 // capSlice converts the slice of capability names in caps, to their numeric 79 // equivalent, and returns them as a slice. Unknown or unavailable capabilities 80 // are not returned, but appended to unknownCaps. 81 func capSlice(caps []string, unknownCaps map[string]struct{}) []capability.Cap { 82 var out []capability.Cap 83 for _, c := range caps { 84 if v, ok := capabilityMap[c]; !ok { 85 unknownCaps[c] = struct{}{} 86 } else { 87 out = append(out, v) 88 } 89 } 90 return out 91 } 92 93 // mapKeys returns the keys of input in sorted order 94 func mapKeys(input map[string]struct{}) []string { 95 var keys []string 96 for c := range input { 97 keys = append(keys, c) 98 } 99 sort.Strings(keys) 100 return keys 101 } 102 103 // Caps holds the capabilities for a container. 104 type Caps struct { 105 pid capability.Capabilities 106 caps map[capability.CapType][]capability.Cap 107 } 108 109 // ApplyBoundingSet sets the capability bounding set to those specified in the whitelist. 110 func (c *Caps) ApplyBoundingSet() error { 111 c.pid.Clear(capability.BOUNDING) 112 c.pid.Set(capability.BOUNDING, c.caps[capability.BOUNDING]...) 113 return c.pid.Apply(capability.BOUNDING) 114 } 115 116 // Apply sets all the capabilities for the current process in the config. 117 func (c *Caps) ApplyCaps() error { 118 c.pid.Clear(allCapabilityTypes) 119 for _, g := range capTypes { 120 c.pid.Set(g, c.caps[g]...) 121 } 122 return c.pid.Apply(allCapabilityTypes) 123 }