|
3 | 3 | package capabilities
|
4 | 4 |
|
5 | 5 | import (
|
6 |
| - "fmt" |
| 6 | + "sort" |
7 | 7 | "strings"
|
8 | 8 |
|
9 | 9 | "github.com/opencontainers/runc/libcontainer/configs"
|
| 10 | + "github.com/sirupsen/logrus" |
10 | 11 | "github.com/syndtr/gocapability/capability"
|
11 | 12 | )
|
12 | 13 |
|
@@ -34,50 +35,57 @@ func init() {
|
34 | 35 | }
|
35 | 36 |
|
36 | 37 | // New creates a new Caps from the given Capabilities config. Unknown Capabilities
|
37 |
| -// or Capabilities that are unavailable in the current environment produce an error. |
| 38 | +// or Capabilities that are unavailable in the current environment are ignored, |
| 39 | +// printing a warning instead. |
38 | 40 | func New(capConfig *configs.Capabilities) (*Caps, error) {
|
39 | 41 | var (
|
40 | 42 | err error
|
41 |
| - c = Caps{caps: make(map[capability.CapType][]capability.Cap, len(capTypes))} |
| 43 | + c Caps |
42 | 44 | )
|
43 | 45 |
|
44 |
| - if c.caps[capability.BOUNDING], err = capSlice(capConfig.Bounding); err != nil { |
45 |
| - return nil, err |
46 |
| - } |
47 |
| - if c.caps[capability.EFFECTIVE], err = capSlice(capConfig.Effective); err != nil { |
48 |
| - return nil, err |
49 |
| - } |
50 |
| - if c.caps[capability.INHERITABLE], err = capSlice(capConfig.Inheritable); err != nil { |
51 |
| - return nil, err |
52 |
| - } |
53 |
| - if c.caps[capability.PERMITTED], err = capSlice(capConfig.Permitted); err != nil { |
54 |
| - return nil, err |
55 |
| - } |
56 |
| - if c.caps[capability.AMBIENT], err = capSlice(capConfig.Ambient); err != nil { |
57 |
| - return nil, err |
| 46 | + unknownCaps := make(map[string]struct{}) |
| 47 | + c.caps = map[capability.CapType][]capability.Cap{ |
| 48 | + capability.BOUNDING: capSlice(capConfig.Bounding, unknownCaps), |
| 49 | + capability.EFFECTIVE: capSlice(capConfig.Effective, unknownCaps), |
| 50 | + capability.INHERITABLE: capSlice(capConfig.Inheritable, unknownCaps), |
| 51 | + capability.PERMITTED: capSlice(capConfig.Permitted, unknownCaps), |
| 52 | + capability.AMBIENT: capSlice(capConfig.Ambient, unknownCaps), |
58 | 53 | }
|
59 | 54 | if c.pid, err = capability.NewPid2(0); err != nil {
|
60 | 55 | return nil, err
|
61 | 56 | }
|
62 | 57 | if err = c.pid.Load(); err != nil {
|
63 | 58 | return nil, err
|
64 | 59 | }
|
| 60 | + if len(unknownCaps) > 0 { |
| 61 | + logrus.Warn("ignoring unknown or unavailable capabilities: ", mapKeys(unknownCaps)) |
| 62 | + } |
65 | 63 | return &c, nil
|
66 | 64 | }
|
67 | 65 |
|
68 | 66 | // capSlice converts the slice of capability names in caps, to their numeric
|
69 | 67 | // equivalent, and returns them as a slice. Unknown or unavailable capabilities
|
70 |
| -// produce an error. |
71 |
| -func capSlice(caps []string) ([]capability.Cap, error) { |
72 |
| - out := make([]capability.Cap, len(caps)) |
73 |
| - for i, c := range caps { |
74 |
| - v, ok := capabilityMap[c] |
75 |
| - if !ok { |
76 |
| - return nil, fmt.Errorf("unknown capability %q", c) |
| 68 | +// are not returned, but appended to unknownCaps. |
| 69 | +func capSlice(caps []string, unknownCaps map[string]struct{}) []capability.Cap { |
| 70 | + var out []capability.Cap |
| 71 | + for _, c := range caps { |
| 72 | + if v, ok := capabilityMap[c]; !ok { |
| 73 | + unknownCaps[c] = struct{}{} |
| 74 | + } else { |
| 75 | + out = append(out, v) |
77 | 76 | }
|
78 |
| - out[i] = v |
79 | 77 | }
|
80 |
| - return out, nil |
| 78 | + return out |
| 79 | +} |
| 80 | + |
| 81 | +// mapKeys returns the keys of input in sorted order |
| 82 | +func mapKeys(input map[string]struct{}) []string { |
| 83 | + var keys []string |
| 84 | + for c := range input { |
| 85 | + keys = append(keys, c) |
| 86 | + } |
| 87 | + sort.Strings(keys) |
| 88 | + return keys |
81 | 89 | }
|
82 | 90 |
|
83 | 91 | // Caps holds the capabilities for a container.
|
|
0 commit comments