mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #14113 from dit4c/10348-exec-privileged
Remerge of `docker exec --privileged` with better tests
This commit is contained in:
commit
e1f3a5ad0a
7 changed files with 68 additions and 17 deletions
|
@ -675,7 +675,7 @@ _docker_exec() {
|
||||||
|
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W "--detach -d --help --interactive -i -t --tty -u --user" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "--detach -d --help --interactive -i --privileged -t --tty -u --user" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
__docker_containers_running
|
__docker_containers_running
|
||||||
|
|
|
@ -152,6 +152,7 @@ func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, erro
|
||||||
Entrypoint: entrypoint,
|
Entrypoint: entrypoint,
|
||||||
Arguments: args,
|
Arguments: args,
|
||||||
User: user,
|
User: user,
|
||||||
|
Privileged: config.Privileged,
|
||||||
}
|
}
|
||||||
|
|
||||||
execConfig := &execConfig{
|
execConfig := &execConfig{
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
|
|
||||||
// Exec implements the exec driver Driver interface,
|
// Exec implements the exec driver Driver interface,
|
||||||
// it calls libcontainer APIs to execute a container.
|
// it calls libcontainer APIs to execute a container.
|
||||||
// TODO(vishh): Add support for running in privileged mode.
|
|
||||||
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
||||||
active := d.activeContainers[c.ID]
|
active := d.activeContainers[c.ID]
|
||||||
if active == nil {
|
if active == nil {
|
||||||
|
@ -33,6 +32,10 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||||
User: processConfig.User,
|
User: processConfig.User,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if processConfig.Privileged {
|
||||||
|
p.Capabilities = execdriver.GetAllCapabilities()
|
||||||
|
}
|
||||||
|
|
||||||
config := active.Config()
|
config := active.Config()
|
||||||
if err := setupPipes(&config, processConfig, p, pipes); err != nil {
|
if err := setupPipes(&config, processConfig, p, pipes); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
|
|
|
@ -17,6 +17,7 @@ weight=1
|
||||||
|
|
||||||
-d, --detach=false Detached mode: run command in the background
|
-d, --detach=false Detached mode: run command in the background
|
||||||
-i, --interactive=false Keep STDIN open even if not attached
|
-i, --interactive=false Keep STDIN open even if not attached
|
||||||
|
--privileged=false Give extended Linux capabilities to the command
|
||||||
-t, --tty=false Allocate a pseudo-TTY
|
-t, --tty=false Allocate a pseudo-TTY
|
||||||
-u, --user= Username or UID (format: <name|uid>[:<group|gid>])
|
-u, --user= Username or UID (format: <name|uid>[:<group|gid>])
|
||||||
|
|
||||||
|
@ -52,4 +53,3 @@ This will create a new file `/tmp/execWorks` inside the running container
|
||||||
$ docker exec -it ubuntu_bash bash
|
$ docker exec -it ubuntu_bash bash
|
||||||
|
|
||||||
This will create a new Bash session in the container `ubuntu_bash`.
|
This will create a new Bash session in the container `ubuntu_bash`.
|
||||||
|
|
||||||
|
|
|
@ -532,6 +532,44 @@ func (s *DockerSuite) TestExecWithUser(c *check.C) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestExecWithPrivileged(c *check.C) {
|
||||||
|
|
||||||
|
// 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`)
|
||||||
|
|
||||||
|
// 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 fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.TrimSpace(out); actual != "ok" {
|
||||||
|
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) {
|
func (s *DockerSuite) TestExecWithImageUser(c *check.C) {
|
||||||
name := "testbuilduser"
|
name := "testbuilduser"
|
||||||
_, err := buildImage(name,
|
_, err := buildImage(name,
|
||||||
|
|
|
@ -9,13 +9,14 @@ docker-exec - Run a command in a running container
|
||||||
[**-d**|**--detach**[=*false*]]
|
[**-d**|**--detach**[=*false*]]
|
||||||
[**--help**]
|
[**--help**]
|
||||||
[**-i**|**--interactive**[=*false*]]
|
[**-i**|**--interactive**[=*false*]]
|
||||||
|
[**--privileged**[=*false*]]
|
||||||
[**-t**|**--tty**[=*false*]]
|
[**-t**|**--tty**[=*false*]]
|
||||||
[**-u**|**--user**[=*USER*]]
|
[**-u**|**--user**[=*USER*]]
|
||||||
CONTAINER COMMAND [ARG...]
|
CONTAINER COMMAND [ARG...]
|
||||||
|
|
||||||
# DESCRIPTION
|
# 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
|
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.
|
process (`PID 1`) is running, and will not be restarted if the container is restarted.
|
||||||
|
@ -33,6 +34,14 @@ container is unpaused, and then run
|
||||||
**-i**, **--interactive**=*true*|*false*
|
**-i**, **--interactive**=*true*|*false*
|
||||||
Keep STDIN open even if not attached. The default is *false*.
|
Keep STDIN open even if not attached. The default is *false*.
|
||||||
|
|
||||||
|
**--privileged**=*true*|*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*.
|
||||||
|
|
||||||
|
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*
|
**-t**, **--tty**=*true*|*false*
|
||||||
Allocate a pseudo-TTY. The default is *false*.
|
Allocate a pseudo-TTY. The default is *false*.
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,13 @@ type ExecConfig struct {
|
||||||
// not valid, it will return an error.
|
// not valid, it will return an error.
|
||||||
func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) {
|
func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) {
|
||||||
var (
|
var (
|
||||||
flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
|
flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
|
||||||
flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
|
flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
|
||||||
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: run command in the background")
|
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: run command in the background")
|
||||||
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
|
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
|
||||||
execCmd []string
|
flPrivileged = cmd.Bool([]string{"-privileged"}, false, "Give extended privileges to the command")
|
||||||
container string
|
execCmd []string
|
||||||
|
container string
|
||||||
)
|
)
|
||||||
cmd.Require(flag.Min, 2)
|
cmd.Require(flag.Min, 2)
|
||||||
if err := cmd.ParseFlags(args, true); err != nil {
|
if err := cmd.ParseFlags(args, true); err != nil {
|
||||||
|
@ -40,13 +41,12 @@ func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) {
|
||||||
execCmd = parsedArgs[1:]
|
execCmd = parsedArgs[1:]
|
||||||
|
|
||||||
execConfig := &ExecConfig{
|
execConfig := &ExecConfig{
|
||||||
User: *flUser,
|
User: *flUser,
|
||||||
// TODO(vishh): Expose 'Privileged' once it is supported.
|
Privileged: *flPrivileged,
|
||||||
// + //Privileged: job.GetenvBool("Privileged"),
|
Tty: *flTty,
|
||||||
Tty: *flTty,
|
Cmd: execCmd,
|
||||||
Cmd: execCmd,
|
Container: container,
|
||||||
Container: container,
|
Detach: *flDetach,
|
||||||
Detach: *flDetach,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If -d is not set, attach to everything by default
|
// If -d is not set, attach to everything by default
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue