Skip to content

Commit 199e195

Browse files
committed
Add support for ambient capabilities
Linux kernel 4.3 and later supports "ambient capabilities" which are the only way to pass capabilities to containers running as a non root uid. Previously there was no way to allow containers not running as root capabilities in a useful way. Fix #8460 Signed-off-by: Justin Cormack <justin.cormack@docker.com>
1 parent 4a68c98 commit 199e195

4 files changed

Lines changed: 40 additions & 0 deletions

File tree

docs/reference/run.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,10 @@ since Docker 1.12. In Docker 1.10 and 1.11 this did not happen and it may be nec
12201220
to use a custom seccomp profile or use `--security-opt seccomp=unconfined` when adding
12211221
capabilities.
12221222

1223+
It is only possible to grant capabilities to a container running as a user other than `root`
1224+
on a system with a Linux kernel version of 4.3 or later, as this requires "ambient capabilities"
1225+
to be granted. These will be added if the kernel allows it from Docker version 1.13.
1226+
12231227
## Logging drivers (--log-driver)
12241228

12251229
The container can have a different logging driver than the Docker daemon. Use

docs/security/security.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,14 @@ capability removal, or less secure through the addition of capabilities.
212212
The best practice for users would be to remove all capabilities except
213213
those explicitly required for their processes.
214214

215+
Linux kernel versions since 4.3 allow Docker to grant capabilities to
216+
container processes running as a non root user. This adds an extra
217+
layer of protection as the process can then be denied access to be able
218+
to write files belonging to the root uid, for example. User namespaces
219+
also allow capabilities to be granted to processes that are effectively
220+
non root, but these capabilities are limited to resources created in the
221+
user namespace, so they have limitations.
222+
215223
## Other kernel security features
216224

217225
Capabilities are just one of the many security features provided by

integration-cli/docker_cli_run_unix_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,24 @@ func (s *DockerSuite) TestRunNoNewPrivSetuid(c *check.C) {
11551155
}
11561156
}
11571157

1158+
func (s *DockerSuite) TestRunAmbientCapabilities(c *check.C) {
1159+
testRequires(c, DaemonIsLinux, ambientCapabilities)
1160+
1161+
// test that a non root user can gain capabilities
1162+
runCmd := exec.Command(dockerBinary, "run", "--user", "1000", "--cap-add", "chown", "busybox", "chown", "100", "/tmp")
1163+
_, _, err := runCommandWithOutput(runCmd)
1164+
c.Assert(err, check.IsNil)
1165+
// test that non root user has default capabilities
1166+
runCmd = exec.Command(dockerBinary, "run", "--user", "1000", "busybox", "chown", "100", "/tmp")
1167+
_, _, err = runCommandWithOutput(runCmd)
1168+
c.Assert(err, check.IsNil)
1169+
// test this fails without cap_chown
1170+
runCmd = exec.Command(dockerBinary, "run", "--user", "1000", "--cap-drop", "chown", "busybox", "chown", "100", "/tmp")
1171+
out, _, err := runCommandWithOutput(runCmd)
1172+
c.Assert(err, checker.NotNil, check.Commentf(out))
1173+
c.Assert(strings.TrimSpace(out), checker.Equals, "chown: /tmp: Operation not permitted")
1174+
}
1175+
11581176
func (s *DockerSuite) TestRunApparmorProcDirectory(c *check.C) {
11591177
testRequires(c, SameHostDaemon, Apparmor)
11601178

integration-cli/requirements_unix.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ var (
112112
},
113113
"Test cannot be run with 'sysctl kernel.unprivileged_userns_clone' = 0",
114114
}
115+
ambientCapabilities = testRequirement{
116+
func() bool {
117+
content, err := ioutil.ReadFile("/proc/self/status")
118+
if err == nil && strings.Contains(string(content), "CapAmb:") {
119+
return true
120+
}
121+
return false
122+
},
123+
"Test cannot be run without a kernel (4.3+) supporting ambient capabilities",
124+
}
115125
)
116126

117127
func init() {

0 commit comments

Comments
 (0)