summaryrefslogtreecommitdiff
path: root/pkg/apparmor/apparmor_linux.go
diff options
context:
space:
mode:
authorValentin Rothberg <vrothberg@suse.com>2018-07-09 08:50:52 +0200
committerAtomic Bot <atomic-devel@projectatomic.io>2018-07-11 16:36:24 +0000
commit06ab343bd7c113fe761631142dde4829e8aa4d40 (patch)
tree0f38b5dd752683d59f9cfe335b748bf759a76a9c /pkg/apparmor/apparmor_linux.go
parent84cfdb20617ac7a5a1138375599e28cdad26b824 (diff)
downloadpodman-06ab343bd7c113fe761631142dde4829e8aa4d40.tar.gz
podman-06ab343bd7c113fe761631142dde4829e8aa4d40.tar.bz2
podman-06ab343bd7c113fe761631142dde4829e8aa4d40.zip
podman/libpod: add default AppArmor profile
Make users of libpod more secure by adding the libpod/apparmor package to load a pre-defined AppArmor profile. Large chunks of libpod/apparmor come from github.com/moby/moby. Also check if a specified AppArmor profile is actually loaded and throw an error if necessary. The default profile is loaded only on Linux builds with the `apparmor` buildtag enabled. Signed-off-by: Valentin Rothberg <vrothberg@suse.com> Closes: #1063 Approved by: rhatdan
Diffstat (limited to 'pkg/apparmor/apparmor_linux.go')
-rw-r--r--pkg/apparmor/apparmor_linux.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/pkg/apparmor/apparmor_linux.go b/pkg/apparmor/apparmor_linux.go
new file mode 100644
index 000000000..6e8b7f312
--- /dev/null
+++ b/pkg/apparmor/apparmor_linux.go
@@ -0,0 +1,110 @@
+// +build linux,apparmor
+
+package apparmor
+
+import (
+ "bufio"
+ "io"
+ "io/ioutil"
+ "os"
+ "path"
+ "strings"
+ "text/template"
+)
+
+// profileData holds information about the given profile for generation.
+type profileData struct {
+ // Name is profile name.
+ Name string
+ // Imports defines the apparmor functions to import, before defining the profile.
+ Imports []string
+ // InnerImports defines the apparmor functions to import in the profile.
+ InnerImports []string
+ // Version is the {major, minor, patch} version of apparmor_parser as a single number.
+ Version int
+}
+
+// generateDefault creates an apparmor profile from ProfileData.
+func (p *profileData) generateDefault(out io.Writer) error {
+ compiled, err := template.New("apparmor_profile").Parse(libpodProfileTemplate)
+ if err != nil {
+ return err
+ }
+
+ if macroExists("tunables/global") {
+ p.Imports = append(p.Imports, "#include <tunables/global>")
+ } else {
+ p.Imports = append(p.Imports, "@{PROC}=/proc/")
+ }
+
+ if macroExists("abstractions/base") {
+ p.InnerImports = append(p.InnerImports, "#include <abstractions/base>")
+ }
+
+ ver, err := getVersion()
+ if err != nil {
+ return err
+ }
+ p.Version = ver
+
+ return compiled.Execute(out, p)
+}
+
+// macrosExists checks if the passed macro exists.
+func macroExists(m string) bool {
+ _, err := os.Stat(path.Join(profileDirectory, m))
+ return err == nil
+}
+
+// InstallDefault generates a default profile in a temp directory determined by
+// os.TempDir(), then loads the profile into the kernel using 'apparmor_parser'.
+func InstallDefault(name string) error {
+ p := profileData{
+ Name: name,
+ }
+
+ // 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 {
+ return err
+ }
+
+ return loadProfile(profilePath)
+}
+
+// IsLoaded checks if a profile with the given name has been loaded into the
+// kernel.
+func IsLoaded(name string) (bool, error) {
+ file, err := os.Open("/sys/kernel/security/apparmor/profiles")
+ if err != nil {
+ if os.IsNotExist(err) {
+ return false, nil
+ }
+ return false, err
+ }
+ defer file.Close()
+
+ r := bufio.NewReader(file)
+ for {
+ p, err := r.ReadString('\n')
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return false, err
+ }
+ if strings.HasPrefix(p, name+" ") {
+ return true, nil
+ }
+ }
+
+ return false, nil
+}