diff --git a/components/engine/docs/reference/commandline/exec.md b/components/engine/docs/reference/commandline/exec.md index b5ddc64dc7..2ff1205604 100644 --- a/components/engine/docs/reference/commandline/exec.md +++ b/components/engine/docs/reference/commandline/exec.md @@ -17,7 +17,7 @@ weight=1 -d, --detach=false Detached mode: run command in the background -i, --interactive=false Keep STDIN open even if not attached - --privileged=false Give extended privileges to the command + --privileged=false Give extended Linux capabilities to the command -t, --tty=false Allocate a pseudo-TTY -u, --user= Username or UID (format: [:]) @@ -53,4 +53,3 @@ This will create a new file `/tmp/execWorks` inside the running container $ docker exec -it ubuntu_bash bash This will create a new Bash session in the container `ubuntu_bash`. - diff --git a/components/engine/integration-cli/docker_cli_exec_test.go b/components/engine/integration-cli/docker_cli_exec_test.go index bce007b15a..e22431f854 100644 --- a/components/engine/integration-cli/docker_cli_exec_test.go +++ b/components/engine/integration-cli/docker_cli_exec_test.go @@ -534,18 +534,18 @@ func (s *DockerSuite) TestExecWithUser(c *check.C) { func (s *DockerSuite) TestExecWithPrivileged(c *check.C) { - runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "--cap-drop=ALL", "busybox", "top") - if out, _, err := runCommandWithOutput(runCmd); err != nil { - c.Fatal(out, err) - } + // Start main loop which attempts mknod repeatedly + dockerCmd(c, "run", "-d", "--name", "parent", "--cap-drop=ALL", "busybox", "sh", "-c", `while (true); do if [ -e /exec_priv ]; then cat /exec_priv && mknod /tmp/sda b 8 0 && echo "Success"; else echo "Privileged exec has not run yet"; fi; usleep 10000; done`) - cmd := exec.Command(dockerBinary, "exec", "parent", "sh", "-c", "mknod /tmp/sda b 8 0") + // Check exec mknod doesn't work + cmd := exec.Command(dockerBinary, "exec", "parent", "sh", "-c", "mknod /tmp/sdb b 8 16") out, _, err := runCommandWithOutput(cmd) if err == nil || !strings.Contains(out, "Operation not permitted") { - c.Fatalf("exec mknod in --cap-drop=ALL container without --privileged should failed") + c.Fatalf("exec mknod in --cap-drop=ALL container without --privileged should fail") } - cmd = exec.Command(dockerBinary, "exec", "--privileged", "parent", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") + // Check exec mknod does work with --privileged + cmd = exec.Command(dockerBinary, "exec", "--privileged", "parent", "sh", "-c", `echo "Running exec --privileged" > /exec_priv && mknod /tmp/sdb b 8 16 && usleep 50000 && echo "Finished exec --privileged" > /exec_priv && echo ok`) out, _, err = runCommandWithOutput(cmd) if err != nil { c.Fatal(err, out) @@ -555,6 +555,19 @@ func (s *DockerSuite) TestExecWithPrivileged(c *check.C) { c.Fatalf("exec mknod in --cap-drop=ALL container with --privileged failed: %v, output: %q", err, out) } + // Check subsequent unprivileged exec cannot mknod + cmd = exec.Command(dockerBinary, "exec", "parent", "sh", "-c", "mknod /tmp/sdc b 8 32") + out, _, err = runCommandWithOutput(cmd) + if err == nil || !strings.Contains(out, "Operation not permitted") { + c.Fatalf("repeating exec mknod in --cap-drop=ALL container after --privileged without --privileged should fail") + } + + // Confirm at no point was mknod allowed + logCmd := exec.Command(dockerBinary, "logs", "parent") + if out, _, err := runCommandWithOutput(logCmd); err != nil || strings.Contains(out, "Success") { + c.Fatal(out, err) + } + } func (s *DockerSuite) TestExecWithImageUser(c *check.C) { diff --git a/components/engine/man/docker-exec.1.md b/components/engine/man/docker-exec.1.md index 312fa397f5..5cfdb5434b 100644 --- a/components/engine/man/docker-exec.1.md +++ b/components/engine/man/docker-exec.1.md @@ -16,7 +16,7 @@ CONTAINER COMMAND [ARG...] # DESCRIPTION -Run a process in a running container. +Run a process in a running container. The command started using `docker exec` will only run while the container's primary process (`PID 1`) is running, and will not be restarted if the container is restarted. @@ -35,11 +35,12 @@ container is unpaused, and then run Keep STDIN open even if not attached. The default is *false*. **--privileged**=*true*|*false* - Give extended privileges to the process to run in a running container. The default is *false*. + Give the process extended [Linux capabilities](http://man7.org/linux/man-pages/man7/capabilities.7.html) +when running in a container. The default is *false*. - By default, the process run by docker exec in a running container -have the same capabilities of the container. By setting --privileged will give -all the capabilities to the process. + Without this flag, the process run by `docker exec` in a running container has +the same capabilities as the container, which may be limited. Set +`--privileged` to give all capabilities to the process. **-t**, **--tty**=*true*|*false* Allocate a pseudo-TTY. The default is *false*.