Browse Source

apparmor: do not save profile to /etc/apparmor.d

Writing the profile to /etc/apparmor.d, while also manually loading it
into the kernel results in quite a bit of confusion. In addition, it
means that people using apparmor but have /etc mounted read-only cannot
use apparmor at all on a Docker host.

Fix this by writing the profile to a temporary directory and deleting it
after it's been inserted.

Signed-off-by: Aleksa Sarai <asarai@suse.de>
Aleksa Sarai 9 years ago
parent
commit
2f7596aaef
2 changed files with 12 additions and 13 deletions
  1. 3 3
      pkg/aaparser/aaparser.go
  2. 9 10
      profiles/apparmor/apparmor.go

+ 3 - 3
pkg/aaparser/aaparser.go

@@ -23,10 +23,10 @@ func GetVersion() (int, error) {
 	return parseVersion(output)
 }
 
-// LoadProfile runs `apparmor_parser -r -W` on a specified apparmor profile to
-// replace and write it to disk.
+// LoadProfile runs `apparmor_parser -r` on a specified apparmor profile to
+// replace the profile.
 func LoadProfile(profilePath string) error {
-	_, err := cmd(filepath.Dir(profilePath), "-r", "-W", filepath.Base(profilePath))
+	_, err := cmd("-r", filepath.Dir(profilePath))
 	if err != nil {
 		return err
 	}

+ 9 - 10
profiles/apparmor/apparmor.go

@@ -5,6 +5,7 @@ package apparmor
 import (
 	"bufio"
 	"io"
+	"io/ioutil"
 	"os"
 	"path"
 	"strings"
@@ -16,8 +17,6 @@ import (
 var (
 	// profileDirectory is the file store for apparmor profiles and macros.
 	profileDirectory = "/etc/apparmor.d"
-	// defaultProfilePath is the default path for the apparmor profile to be saved.
-	defaultProfilePath = path.Join(profileDirectory, "docker")
 )
 
 // profileData holds information about the given profile for generation.
@@ -70,26 +69,26 @@ func macroExists(m string) bool {
 // InstallDefault generates a default profile and installs it in the
 // ProfileDirectory with `apparmor_parser`.
 func InstallDefault(name string) error {
-	// Make sure the path where they want to save the profile exists
-	if err := os.MkdirAll(profileDirectory, 0755); err != nil {
-		return err
-	}
-
 	p := profileData{
 		Name: name,
 	}
 
-	f, err := os.OpenFile(defaultProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+	// Install to a temporary directory.
+	f, err := ioutil.TempFile("", name)
 	if err != nil {
 		return err
 	}
+	profilePath := f.Name()
+
+	defer f.Close()
+	defer os.Remove(profilePath)
+
 	if err := p.generateDefault(f); err != nil {
 		f.Close()
 		return err
 	}
-	f.Close()
 
-	if err := aaparser.LoadProfile(defaultProfilePath); err != nil {
+	if err := aaparser.LoadProfile(profilePath); err != nil {
 		return err
 	}