Fix AppArmor not being applied to Exec processes
Exec processes do not automatically inherit AppArmor profiles from the container. This patch sets the AppArmor profile for the exec process. Before this change: apparmor_parser -q -r <<EOF #include <tunables/global> profile deny-write flags=(attach_disconnected) { #include <abstractions/base> file, network, deny /tmp/** w, capability, } EOF docker run -dit --security-opt "apparmor=deny-write" --name aa busybox docker exec aa sh -c 'mkdir /tmp/test' (no error) With this change applied: docker exec aa sh -c 'mkdir /tmp/test' mkdir: can't create directory '/tmp/test': Permission denied Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
75377ec12c
commit
8f3308ae10
2 changed files with 56 additions and 0 deletions
|
@ -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
|
||||
|
|
53
daemon/exec_linux_test.go
Normal file
53
daemon/exec_linux_test.go
Normal file
|
@ -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)
|
||||
}
|
Loading…
Reference in a new issue