diff --git a/daemon/exec_linux.go b/daemon/exec_linux.go index 1ed26c2fcc..cd52f4886f 100644 --- a/daemon/exec_linux.go +++ b/daemon/exec_linux.go @@ -34,6 +34,8 @@ func (daemon *Daemon) execSetPlatformOpt(c *container.Container, ec *exec.Config if c.AppArmorProfile != "" { appArmorProfile = c.AppArmorProfile } else if c.HostConfig.Privileged { + // `docker exec --privileged` does not currently disable AppArmor + // profiles. Privileged configuration of the container is inherited appArmorProfile = "unconfined" } else { appArmorProfile = "docker-default" @@ -50,6 +52,7 @@ func (daemon *Daemon) execSetPlatformOpt(c *container.Container, ec *exec.Config return err } } + p.ApparmorProfile = appArmorProfile } daemon.setRlimits(&specs.Spec{Process: p}, c) return nil diff --git a/daemon/exec_linux_test.go b/daemon/exec_linux_test.go new file mode 100644 index 0000000000..9e5496ae4b --- /dev/null +++ b/daemon/exec_linux_test.go @@ -0,0 +1,53 @@ +// +build linux + +package daemon + +import ( + "testing" + + containertypes "github.com/docker/docker/api/types/container" + "github.com/docker/docker/container" + "github.com/docker/docker/daemon/exec" + "github.com/gotestyourself/gotestyourself/assert" + "github.com/opencontainers/runc/libcontainer/apparmor" + "github.com/opencontainers/runtime-spec/specs-go" +) + +func TestExecSetPlatformOpt(t *testing.T) { + if !apparmor.IsEnabled() { + t.Skip("requires AppArmor to be enabled") + } + d := &Daemon{} + c := &container.Container{AppArmorProfile: "my-custom-profile"} + ec := &exec.Config{} + p := &specs.Process{} + + err := d.execSetPlatformOpt(c, ec, p) + assert.NilError(t, err) + assert.Equal(t, "my-custom-profile", p.ApparmorProfile) +} + +// TestExecSetPlatformOptPrivileged verifies that `docker exec --privileged` +// does not disable AppArmor profiles. Exec currently inherits the `Privileged` +// configuration of the container. See https://github.com/moby/moby/pull/31773#discussion_r105586900 +// +// This behavior may change in future, but test for the behavior to prevent it +// from being changed accidentally. +func TestExecSetPlatformOptPrivileged(t *testing.T) { + if !apparmor.IsEnabled() { + t.Skip("requires AppArmor to be enabled") + } + d := &Daemon{} + c := &container.Container{AppArmorProfile: "my-custom-profile"} + ec := &exec.Config{Privileged: true} + p := &specs.Process{} + + err := d.execSetPlatformOpt(c, ec, p) + assert.NilError(t, err) + assert.Equal(t, "my-custom-profile", p.ApparmorProfile) + + c.HostConfig = &containertypes.HostConfig{Privileged: true} + err = d.execSetPlatformOpt(c, ec, p) + assert.NilError(t, err) + assert.Equal(t, "unconfined", p.ApparmorProfile) +}