Browse code

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 authored on 2016/07/20 21:24:55
Showing 2 changed files
... ...
@@ -23,10 +23,10 @@ func GetVersion() (int, error) {
23 23
 	return parseVersion(output)
24 24
 }
25 25
 
26
-// LoadProfile runs `apparmor_parser -r -W` on a specified apparmor profile to
27
-// replace and write it to disk.
26
+// LoadProfile runs `apparmor_parser -r` on a specified apparmor profile to
27
+// replace the profile.
28 28
 func LoadProfile(profilePath string) error {
29
-	_, err := cmd(filepath.Dir(profilePath), "-r", "-W", filepath.Base(profilePath))
29
+	_, err := cmd("-r", filepath.Dir(profilePath))
30 30
 	if err != nil {
31 31
 		return err
32 32
 	}
... ...
@@ -5,6 +5,7 @@ package apparmor
5 5
 import (
6 6
 	"bufio"
7 7
 	"io"
8
+	"io/ioutil"
8 9
 	"os"
9 10
 	"path"
10 11
 	"strings"
... ...
@@ -16,8 +17,6 @@ import (
16 16
 var (
17 17
 	// profileDirectory is the file store for apparmor profiles and macros.
18 18
 	profileDirectory = "/etc/apparmor.d"
19
-	// defaultProfilePath is the default path for the apparmor profile to be saved.
20
-	defaultProfilePath = path.Join(profileDirectory, "docker")
21 19
 )
22 20
 
23 21
 // profileData holds information about the given profile for generation.
... ...
@@ -70,26 +69,26 @@ func macroExists(m string) bool {
70 70
 // InstallDefault generates a default profile and installs it in the
71 71
 // ProfileDirectory with `apparmor_parser`.
72 72
 func InstallDefault(name string) error {
73
-	// Make sure the path where they want to save the profile exists
74
-	if err := os.MkdirAll(profileDirectory, 0755); err != nil {
75
-		return err
76
-	}
77
-
78 73
 	p := profileData{
79 74
 		Name: name,
80 75
 	}
81 76
 
82
-	f, err := os.OpenFile(defaultProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
77
+	// Install to a temporary directory.
78
+	f, err := ioutil.TempFile("", name)
83 79
 	if err != nil {
84 80
 		return err
85 81
 	}
82
+	profilePath := f.Name()
83
+
84
+	defer f.Close()
85
+	defer os.Remove(profilePath)
86
+
86 87
 	if err := p.generateDefault(f); err != nil {
87 88
 		f.Close()
88 89
 		return err
89 90
 	}
90
-	f.Close()
91 91
 
92
-	if err := aaparser.LoadProfile(defaultProfilePath); err != nil {
92
+	if err := aaparser.LoadProfile(profilePath); err != nil {
93 93
 		return err
94 94
 	}
95 95