1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #29130 from cyphar/29097-dynamically-reload-apparmor

daemon: switch to 'ensure' workflow for AppArmor profiles
This commit is contained in:
Victor Vieux 2016-12-12 13:32:36 -08:00 committed by GitHub
commit 96a84ed85a
5 changed files with 51 additions and 20 deletions

View file

@ -3,7 +3,8 @@
package daemon package daemon
import ( import (
"github.com/Sirupsen/logrus" "fmt"
aaprofile "github.com/docker/docker/profiles/apparmor" aaprofile "github.com/docker/docker/profiles/apparmor"
"github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/apparmor"
) )
@ -13,18 +14,23 @@ const (
defaultApparmorProfile = "docker-default" defaultApparmorProfile = "docker-default"
) )
func installDefaultAppArmorProfile() { func ensureDefaultAppArmorProfile() error {
if apparmor.IsEnabled() { if apparmor.IsEnabled() {
if err := aaprofile.InstallDefault(defaultApparmorProfile); err != nil { loaded, err := aaprofile.IsLoaded(defaultApparmorProfile)
apparmorProfiles := []string{defaultApparmorProfile} if err != nil {
return fmt.Errorf("Could not check if %s AppArmor profile was loaded: %s", defaultApparmorProfile, err)
}
// Allow daemon to run if loading failed, but are active // Nothing to do.
// (possibly through another run, manually, or via system startup) if loaded {
for _, policy := range apparmorProfiles { return nil
if err := aaprofile.IsLoaded(policy); err != nil { }
logrus.Errorf("AppArmor enabled on system but the %s profile could not be loaded.", policy)
} // Load the profile.
} if err := aaprofile.InstallDefault(defaultApparmorProfile); err != nil {
return fmt.Errorf("AppArmor enabled on system but the %s profile could not be loaded.", defaultApparmorProfile)
} }
} }
return nil
} }

View file

@ -2,5 +2,6 @@
package daemon package daemon
func installDefaultAppArmorProfile() { func ensureDefaultAppArmorProfile() error {
return nil
} }

View file

@ -524,7 +524,10 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot
logrus.Warnf("Failed to configure golang's threads limit: %v", err) logrus.Warnf("Failed to configure golang's threads limit: %v", err)
} }
installDefaultAppArmorProfile() if err := ensureDefaultAppArmorProfile(); err != nil {
logrus.Errorf(err.Error())
}
daemonRepo := filepath.Join(config.Root, "containers") daemonRepo := filepath.Join(config.Root, "containers")
if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
return nil, err return nil, err

View file

@ -733,12 +733,27 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
} }
if apparmor.IsEnabled() { if apparmor.IsEnabled() {
appArmorProfile := "docker-default" var appArmorProfile string
if len(c.AppArmorProfile) > 0 { if c.AppArmorProfile != "" {
appArmorProfile = c.AppArmorProfile appArmorProfile = c.AppArmorProfile
} else if c.HostConfig.Privileged { } else if c.HostConfig.Privileged {
appArmorProfile = "unconfined" appArmorProfile = "unconfined"
} else {
appArmorProfile = "docker-default"
} }
if appArmorProfile == "docker-default" {
// Unattended upgrades and other fun services can unload AppArmor
// profiles inadvertently. Since we cannot store our profile in
// /etc/apparmor.d, nor can we practically add other ways of
// telling the system to keep our profile loaded, in order to make
// sure that we keep the default profile enabled we dynamically
// reload it if necessary.
if err := ensureDefaultAppArmorProfile(); err != nil {
return nil, err
}
}
s.Process.ApparmorProfile = appArmorProfile s.Process.ApparmorProfile = appArmorProfile
} }
s.Process.SelinuxLabel = c.GetProcessLabel() s.Process.SelinuxLabel = c.GetProcessLabel()

View file

@ -94,22 +94,28 @@ func InstallDefault(name string) error {
return nil return nil
} }
// IsLoaded checks if a passed profile has been loaded into the kernel. // IsLoaded checks if a profile with the given name has been loaded into the
func IsLoaded(name string) error { // kernel.
func IsLoaded(name string) (bool, error) {
file, err := os.Open("/sys/kernel/security/apparmor/profiles") file, err := os.Open("/sys/kernel/security/apparmor/profiles")
if err != nil { if err != nil {
return err return false, err
} }
defer file.Close() defer file.Close()
r := bufio.NewReader(file) r := bufio.NewReader(file)
for { for {
p, err := r.ReadString('\n') p, err := r.ReadString('\n')
if err == io.EOF {
break
}
if err != nil { if err != nil {
return err return false, err
} }
if strings.HasPrefix(p, name+" ") { if strings.HasPrefix(p, name+" ") {
return nil return true, nil
} }
} }
return false, nil
} }