|
3 | 3 | package capabilities
|
4 | 4 |
|
5 | 5 | import (
|
| 6 | + "slices" |
6 | 7 | "sort"
|
7 | 8 | "strings"
|
8 | 9 | "sync"
|
@@ -57,27 +58,48 @@ func New(capConfig *configs.Capabilities) (*Caps, error) {
|
57 | 58 |
|
58 | 59 | cm := capMap()
|
59 | 60 | unknownCaps := make(map[string]struct{})
|
| 61 | + ignoredCaps := make(map[string]struct{}) |
60 | 62 | // capSlice converts the slice of capability names in caps, to their numeric
|
61 | 63 | // equivalent, and returns them as a slice. Unknown or unavailable capabilities
|
62 | 64 | // are not returned, but appended to unknownCaps.
|
63 |
| - capSlice := func(caps []string) []capability.Cap { |
| 65 | + // |
| 66 | + // If mustHave argument is not nil, caps that are not present in mustHave |
| 67 | + // are appended to ignoredCaps instead of the resulting slice. |
| 68 | + capSlice := func(caps []string, mustHave []capability.Cap) []capability.Cap { |
64 | 69 | out := make([]capability.Cap, 0, len(caps))
|
65 | 70 | for _, c := range caps {
|
66 | 71 | if v, ok := cm[c]; !ok {
|
67 | 72 | unknownCaps[c] = struct{}{}
|
68 | 73 | } else {
|
| 74 | + if mustHave != nil && !slices.Contains(mustHave, v) { |
| 75 | + ignoredCaps[c] = struct{}{} |
| 76 | + continue |
| 77 | + } |
69 | 78 | out = append(out, v)
|
70 | 79 | }
|
71 | 80 | }
|
72 | 81 | return out
|
73 | 82 | }
|
| 83 | + inheritable := capSlice(capConfig.Inheritable, nil) |
| 84 | + // Ambient vector can not contain values not raised in the Inheritable vector, |
| 85 | + // and errors setting ambient capabilities were previously ignored due to a bug |
| 86 | + // (see https://github.com/kolyshkin/capability/pull/3), so to maintain backward |
| 87 | + // compatibility we have to ignore those Ambient caps that are not also raised |
| 88 | + // in Inheritable (and issue a warning). |
| 89 | + ambient := capSlice(capConfig.Ambient, inheritable) |
| 90 | + if len(ignoredCaps) > 0 { |
| 91 | + logrus.Warn("unable to set Ambient capabilities which are not set in Inheritable; ignoring following Ambient capabilities: ", mapKeys(ignoredCaps)) |
| 92 | + clear(ignoredCaps) |
| 93 | + } |
| 94 | + |
74 | 95 | c.caps = map[capability.CapType][]capability.Cap{
|
75 |
| - capability.BOUNDING: capSlice(capConfig.Bounding), |
76 |
| - capability.EFFECTIVE: capSlice(capConfig.Effective), |
77 |
| - capability.INHERITABLE: capSlice(capConfig.Inheritable), |
78 |
| - capability.PERMITTED: capSlice(capConfig.Permitted), |
79 |
| - capability.AMBIENT: capSlice(capConfig.Ambient), |
| 96 | + capability.BOUNDING: capSlice(capConfig.Bounding, nil), |
| 97 | + capability.EFFECTIVE: capSlice(capConfig.Effective, nil), |
| 98 | + capability.INHERITABLE: inheritable, |
| 99 | + capability.PERMITTED: capSlice(capConfig.Permitted, nil), |
| 100 | + capability.AMBIENT: ambient, |
80 | 101 | }
|
| 102 | + |
81 | 103 | if c.pid, err = capability.NewPid2(0); err != nil {
|
82 | 104 | return nil, err
|
83 | 105 | }
|
|
0 commit comments