Skip to content

Commit 67c8a28

Browse files
authored
Merge pull request #4358 from kolyshkin/rm-cap-init
libct/cap: switch to moby/sys/capability, lazy init
2 parents b7da167 + 6696982 commit 67c8a28

File tree

17 files changed

+638
-408
lines changed

17 files changed

+638
-408
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/cyphar/filepath-securejoin v0.3.4
1616
github.com/docker/go-units v0.5.0
1717
github.com/godbus/dbus/v5 v5.1.0
18+
github.com/moby/sys/capability v0.4.0
1819
github.com/moby/sys/mountinfo v0.7.2
1920
github.com/moby/sys/user v0.3.0
2021
github.com/moby/sys/userns v0.1.0
@@ -23,7 +24,6 @@ require (
2324
github.com/opencontainers/selinux v1.11.1
2425
github.com/seccomp/libseccomp-golang v0.10.0
2526
github.com/sirupsen/logrus v1.9.3
26-
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
2727
github.com/urfave/cli v1.22.16
2828
github.com/vishvananda/netlink v1.3.0
2929
golang.org/x/net v0.31.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
3939
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
4040
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
4141
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
42+
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
43+
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
4244
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
4345
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
4446
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
@@ -73,8 +75,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
7375
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
7476
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
7577
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
76-
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
77-
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
7878
github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
7979
github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
8080
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=

libcontainer/capabilities/capabilities.go

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,36 @@
33
package capabilities
44

55
import (
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`.
3934
func 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.
5146
func 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.
7773
func 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
9087
func 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.
113110
func (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
}

libcontainer/capabilities/capabilities_linux_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import (
55
"os"
66
"testing"
77

8+
"github.com/moby/sys/capability"
89
"github.com/opencontainers/runc/libcontainer/configs"
910
"github.com/sirupsen/logrus"
1011
"github.com/sirupsen/logrus/hooks/test"
11-
"github.com/syndtr/gocapability/capability"
1212
)
1313

14+
var capTypes = []capability.CapType{
15+
capability.BOUNDING,
16+
capability.PERMITTED,
17+
capability.INHERITABLE,
18+
capability.EFFECTIVE,
19+
capability.AMBIENT,
20+
}
21+
1422
func TestNew(t *testing.T) {
1523
cs := []string{"CAP_CHOWN", "CAP_UNKNOWN", "CAP_UNKNOWN2"}
1624
conf := configs.Capabilities{

tests/integration/capabilities.bats

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,17 @@ function teardown() {
116116
[[ "${output}" == *"CapBnd: 0000000400000021"* ]]
117117
[[ "${output}" == *"CapAmb: 0000000400000001"* ]]
118118
}
119+
120+
@test "runc run [ambient caps not set in inheritable result in a warning]" {
121+
update_config ' .process.capabilities.inheritable = ["CAP_KILL"]
122+
| .process.capabilities.ambient = ["CAP_KILL", "CAP_CHOWN"]'
123+
runc run test_amb
124+
[ "$status" -eq 0 ]
125+
# This should result in CAP_KILL set in ambient,
126+
# and a warning about inability to set CAP_CHOWN.
127+
#
128+
# CAP_CHOWN is 0, the bit mask is 0x1 (1 << 0)
129+
# CAP_KILL is 5, the bit mask is 0x20 (1 << 5).
130+
[[ "$output" == *"can't raise ambient capability CAP_CHOWN: "* ]]
131+
[[ "${output}" == *"CapAmb: 0000000000000020"* ]]
132+
}

vendor/github.com/moby/sys/capability/CHANGELOG.md

Lines changed: 124 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/syndtr/gocapability/LICENSE renamed to vendor/github.com/moby/sys/capability/LICENSE

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/moby/sys/capability/README.md

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)