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>
This commit is contained in:
Justin Cormack 2016-09-28 13:46:11 +01:00
parent 4a68c98d70
commit 199e19548e
4 changed files with 40 additions and 0 deletions

View File

@ -1220,6 +1220,10 @@ since Docker 1.12. In Docker 1.10 and 1.11 this did not happen and it may be nec
to use a custom seccomp profile or use `--security-opt seccomp=unconfined` when adding
capabilities.
It is only possible to grant capabilities to a container running as a user other than `root`
on a system with a Linux kernel version of 4.3 or later, as this requires "ambient capabilities"
to be granted. These will be added if the kernel allows it from Docker version 1.13.
## Logging drivers (--log-driver)
The container can have a different logging driver than the Docker daemon. Use

View File

@ -212,6 +212,14 @@ capability removal, or less secure through the addition of capabilities.
The best practice for users would be to remove all capabilities except
those explicitly required for their processes.
Linux kernel versions since 4.3 allow Docker to grant capabilities to
container processes running as a non root user. This adds an extra
layer of protection as the process can then be denied access to be able
to write files belonging to the root uid, for example. User namespaces
also allow capabilities to be granted to processes that are effectively
non root, but these capabilities are limited to resources created in the
user namespace, so they have limitations.
## Other kernel security features
Capabilities are just one of the many security features provided by

View File

@ -1155,6 +1155,24 @@ func (s *DockerSuite) TestRunNoNewPrivSetuid(c *check.C) {
}
}
func (s *DockerSuite) TestRunAmbientCapabilities(c *check.C) {
testRequires(c, DaemonIsLinux, ambientCapabilities)
// test that a non root user can gain capabilities
runCmd := exec.Command(dockerBinary, "run", "--user", "1000", "--cap-add", "chown", "busybox", "chown", "100", "/tmp")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user has default capabilities
runCmd = exec.Command(dockerBinary, "run", "--user", "1000", "busybox", "chown", "100", "/tmp")
_, _, err = runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test this fails without cap_chown
runCmd = exec.Command(dockerBinary, "run", "--user", "1000", "--cap-drop", "chown", "busybox", "chown", "100", "/tmp")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Equals, "chown: /tmp: Operation not permitted")
}
func (s *DockerSuite) TestRunApparmorProcDirectory(c *check.C) {
testRequires(c, SameHostDaemon, Apparmor)

View File

@ -112,6 +112,16 @@ var (
},
"Test cannot be run with 'sysctl kernel.unprivileged_userns_clone' = 0",
}
ambientCapabilities = testRequirement{
func() bool {
content, err := ioutil.ReadFile("/proc/self/status")
if err == nil && strings.Contains(string(content), "CapAmb:") {
return true
}
return false
},
"Test cannot be run without a kernel (4.3+) supporting ambient capabilities",
}
)
func init() {