Skip to content

Commit 3e3f960

Browse files
kolyshkinlifubang
andcommitted
runc exec --cap: do not add capabilities to ambient
Commit 98fe566 removed setting inheritable capabilities from runc exec --cap, but neglected to also remove ambient capabilities. An ambient capability could only be set if the same inheritable capability is set, so as a result of the above change ambient capabilities were not set (but due to a bug in gocapability package, those errors are never reported). Once we start using a library with the fix [1], that bug will become apparent. Alas, we do not have any tests for runc exec --cap, so add one. Yet, if some inheritable bits are already set from spec, let's set ambient to avoid a possible regression. Add a test case for that, too. [1]: kolyshkin/capability#3 Fixes: 98fe566 ("runc: do not set inheritable capabilities") Co-authored-by: lifubang <[email protected]> Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 8e03054 commit 3e3f960

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

exec.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,12 @@ func getProcess(context *cli.Context, bundle string) (*specs.Process, error) {
234234
p.Capabilities.Bounding = append(p.Capabilities.Bounding, c)
235235
p.Capabilities.Effective = append(p.Capabilities.Effective, c)
236236
p.Capabilities.Permitted = append(p.Capabilities.Permitted, c)
237-
p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
237+
// Since ambient capabilities can't be set without inherritable,
238+
// and runc exec --cap don't set inheritable, let's only set
239+
// ambient if we already have some inheritable bits set from spec.
240+
if p.Capabilities.Inheritable != nil {
241+
p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
242+
}
238243
}
239244
}
240245
// append the passed env variables

tests/integration/capabilities.bats

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,66 @@ function teardown() {
5353
[[ "${output}" == *"CapPrm: 0000000000200000"* ]]
5454
[[ "${output}" == *"NoNewPrivs: 1"* ]]
5555
}
56+
57+
@test "runc exec --cap" {
58+
update_config ' .process.args = ["/bin/sh"]
59+
| .process.capabilities = {}'
60+
runc run -d --console-socket "$CONSOLE_SOCKET" test_exec_cap
61+
[ "$status" -eq 0 ]
62+
63+
runc exec test_exec_cap cat /proc/self/status
64+
[ "$status" -eq 0 ]
65+
# Check no capabilities are set.
66+
[[ "${output}" == *"CapInh: 0000000000000000"* ]]
67+
[[ "${output}" == *"CapPrm: 0000000000000000"* ]]
68+
[[ "${output}" == *"CapEff: 0000000000000000"* ]]
69+
[[ "${output}" == *"CapBnd: 0000000000000000"* ]]
70+
[[ "${output}" == *"CapAmb: 0000000000000000"* ]]
71+
72+
runc exec --cap CAP_KILL --cap CAP_AUDIT_WRITE test_exec_cap cat /proc/self/status
73+
[ "$status" -eq 0 ]
74+
# Check capabilities are added into bounding/effective/permitted only,
75+
# but not to inheritable or ambient.
76+
#
77+
# CAP_KILL is 5, the bit mask is 0x20 (1 << 5).
78+
# CAP_AUDIT_WRITE is 26, the bit mask is 0x20000000 (1 << 26).
79+
[[ "${output}" == *"CapInh: 0000000000000000"* ]]
80+
[[ "${output}" == *"CapPrm: 0000000020000020"* ]]
81+
[[ "${output}" == *"CapEff: 0000000020000020"* ]]
82+
[[ "${output}" == *"CapBnd: 0000000020000020"* ]]
83+
[[ "${output}" == *"CapAmb: 0000000000000000"* ]]
84+
}
85+
86+
@test "runc exec --cap [ambient is set from spec]" {
87+
update_config ' .process.args = ["/bin/sh"]
88+
| .process.capabilities.inheritable = ["CAP_CHOWN", "CAP_SYSLOG"]
89+
| .process.capabilities.permitted = ["CAP_KILL", "CAP_CHOWN"]
90+
| .process.capabilities.effective = ["CAP_KILL"]
91+
| .process.capabilities.bounding = ["CAP_KILL", "CAP_CHOWN", "CAP_SYSLOG"]
92+
| .process.capabilities.ambient = ["CAP_CHOWN"]'
93+
runc run -d --console-socket "$CONSOLE_SOCKET" test_some_caps
94+
[ "$status" -eq 0 ]
95+
96+
runc exec test_some_caps cat /proc/self/status
97+
[ "$status" -eq 0 ]
98+
# Check that capabilities are as set in spec.
99+
#
100+
# CAP_CHOWN is 0, the bit mask is 0x1 (1 << 0)
101+
# CAP_KILL is 5, the bit mask is 0x20 (1 << 5).
102+
# CAP_SYSLOG is 34, the bit mask is 0x400000000 (1 << 34).
103+
[[ "${output}" == *"CapInh: 0000000400000001"* ]]
104+
[[ "${output}" == *"CapPrm: 0000000000000021"* ]]
105+
[[ "${output}" == *"CapEff: 0000000000000021"* ]]
106+
[[ "${output}" == *"CapBnd: 0000000400000021"* ]]
107+
[[ "${output}" == *"CapAmb: 0000000000000001"* ]]
108+
109+
# Check that if config.json has an inheritable capability set,
110+
# runc exec --cap adds ambient capabilities.
111+
runc exec --cap CAP_SYSLOG test_some_caps cat /proc/self/status
112+
[ "$status" -eq 0 ]
113+
[[ "${output}" == *"CapInh: 0000000400000001"* ]]
114+
[[ "${output}" == *"CapPrm: 0000000400000021"* ]]
115+
[[ "${output}" == *"CapEff: 0000000400000021"* ]]
116+
[[ "${output}" == *"CapBnd: 0000000400000021"* ]]
117+
[[ "${output}" == *"CapAmb: 0000000400000001"* ]]
118+
}

0 commit comments

Comments
 (0)