33package capabilities
44
55import (
6+ "fmt"
67 "sort"
78 "strings"
9+ "sync"
810
11+ "github.com/moby/sys/capability"
912 "github.com/opencontainers/runc/libcontainer/configs"
1013 "github.com/sirupsen/logrus"
11- "github.com/syndtr/gocapability/capability"
1214)
1315
14- const allCapabilityTypes = capability .CAPS | capability .BOUNDING | capability .AMBIENT
16+ func capToStr (c capability.Cap ) string {
17+ return "CAP_" + strings .ToUpper (c .String ())
18+ }
1519
16- var (
17- capabilityMap map [string ]capability.Cap
18- capTypes = []capability.CapType {
19- capability .BOUNDING ,
20- capability .PERMITTED ,
21- capability .INHERITABLE ,
22- capability .EFFECTIVE ,
23- capability .AMBIENT ,
20+ var capMap = sync .OnceValues (func () (map [string ]capability.Cap , error ) {
21+ list , err := capability .ListSupported ()
22+ if err != nil {
23+ return nil , err
2424 }
25- )
26-
27- func init () {
28- capabilityMap = make (map [string ]capability.Cap , capability .CAP_LAST_CAP + 1 )
29- for _ , c := range capability .List () {
30- if c > capability .CAP_LAST_CAP {
31- continue
32- }
33- capabilityMap ["CAP_" + strings .ToUpper (c .String ())] = c
25+ cm := make (map [string ]capability.Cap , len (list ))
26+ for _ , c := range list {
27+ cm [capToStr (c )] = c
3428 }
35- }
29+ return cm , nil
30+ })
3631
3732// KnownCapabilities returns the list of the known capabilities.
3833// Used by `runc features`.
3934func KnownCapabilities () []string {
40- list := capability .List ()
35+ list := capability .ListKnown ()
4136 res := make ([]string , len (list ))
4237 for i , c := range list {
4338 res [i ] = "CAP_" + strings .ToUpper (c .String ())
@@ -49,11 +44,12 @@ func KnownCapabilities() []string {
4944// or Capabilities that are unavailable in the current environment are ignored,
5045// printing a warning instead.
5146func New (capConfig * configs.Capabilities ) (* Caps , error ) {
52- var (
53- err error
54- c Caps
55- )
47+ var c Caps
5648
49+ _ , err := capMap ()
50+ if err != nil {
51+ return nil , err
52+ }
5753 unknownCaps := make (map [string ]struct {})
5854 c .caps = map [capability.CapType ][]capability.Cap {
5955 capability .BOUNDING : capSlice (capConfig .Bounding , unknownCaps ),
@@ -75,9 +71,10 @@ func New(capConfig *configs.Capabilities) (*Caps, error) {
7571// equivalent, and returns them as a slice. Unknown or unavailable capabilities
7672// are not returned, but appended to unknownCaps.
7773func capSlice (caps []string , unknownCaps map [string ]struct {}) []capability.Cap {
78- var out []capability.Cap
74+ cm , _ := capMap ()
75+ out := make ([]capability.Cap , 0 , len (caps ))
7976 for _ , c := range caps {
80- if v , ok := capabilityMap [c ]; ! ok {
77+ if v , ok := cm [c ]; ! ok {
8178 unknownCaps [c ] = struct {}{}
8279 } else {
8380 out = append (out , v )
@@ -88,7 +85,7 @@ func capSlice(caps []string, unknownCaps map[string]struct{}) []capability.Cap {
8885
8986// mapKeys returns the keys of input in sorted order
9087func mapKeys (input map [string ]struct {}) []string {
91- var keys []string
88+ keys := make ( []string , 0 , len ( input ))
9289 for c := range input {
9390 keys = append (keys , c )
9491 }
@@ -111,9 +108,36 @@ func (c *Caps) ApplyBoundingSet() error {
111108
112109// Apply sets all the capabilities for the current process in the config.
113110func (c * Caps ) ApplyCaps () error {
114- c .pid .Clear (allCapabilityTypes )
115- for _ , g := range capTypes {
111+ c .pid .Clear (capability .CAPS | capability .BOUNDS )
112+ for _ , g := range []capability.CapType {
113+ capability .EFFECTIVE ,
114+ capability .PERMITTED ,
115+ capability .INHERITABLE ,
116+ capability .BOUNDING ,
117+ } {
116118 c .pid .Set (g , c .caps [g ]... )
117119 }
118- return c .pid .Apply (allCapabilityTypes )
120+ if err := c .pid .Apply (capability .CAPS | capability .BOUNDS ); err != nil {
121+ return fmt .Errorf ("can't apply capabilities: %w" , err )
122+ }
123+
124+ // Old version of capability package used to ignore errors from setting
125+ // ambient capabilities, which is now fixed (see
126+ // https://github.com/kolyshkin/capability/pull/3).
127+ //
128+ // To maintain backward compatibility, set ambient caps one by one and
129+ // don't return any errors, only warn.
130+ ambs := c .caps [capability .AMBIENT ]
131+ err := capability .ResetAmbient ()
132+ if err != nil {
133+ return fmt .Errorf ("can't reset ambient capabilities: %w" , err )
134+ }
135+ for _ , a := range ambs {
136+ err := capability .SetAmbient (true , a )
137+ if err != nil {
138+ logrus .Warnf ("can't raise ambient capability %s: %v" , capToStr (a ), err )
139+ }
140+ }
141+
142+ return nil
119143}
0 commit comments