summaryrefslogtreecommitdiff
path: root/pkg/apparmor/apparmor_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/apparmor/apparmor_linux.go')
-rw-r--r--pkg/apparmor/apparmor_linux.go66
1 files changed, 66 insertions, 0 deletions
diff --git a/pkg/apparmor/apparmor_linux.go b/pkg/apparmor/apparmor_linux.go
index b0e3ca0fd..0787b3fa5 100644
--- a/pkg/apparmor/apparmor_linux.go
+++ b/pkg/apparmor/apparmor_linux.go
@@ -13,7 +13,10 @@ import (
"strings"
"text/template"
+ "github.com/containers/libpod/pkg/rootless"
runcaa "github.com/opencontainers/runc/libcontainer/apparmor"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
// profileDirectory is the file store for apparmor profiles and macros.
@@ -21,6 +24,9 @@ var profileDirectory = "/etc/apparmor.d"
// IsEnabled returns true if AppArmor is enabled on the host.
func IsEnabled() bool {
+ if rootless.IsRootless() {
+ return false
+ }
return runcaa.IsEnabled()
}
@@ -71,6 +77,10 @@ func macroExists(m string) bool {
// InstallDefault generates a default profile and loads it into the kernel
// using 'apparmor_parser'.
func InstallDefault(name string) error {
+ if rootless.IsRootless() {
+ return ErrApparmorRootless
+ }
+
p := profileData{
Name: name,
}
@@ -97,6 +107,10 @@ func InstallDefault(name string) error {
// IsLoaded checks if a profile with the given name has been loaded into the
// kernel.
func IsLoaded(name string) (bool, error) {
+ if name != "" && rootless.IsRootless() {
+ return false, errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
+ }
+
file, err := os.Open("/sys/kernel/security/apparmor/profiles")
if err != nil {
if os.IsNotExist(err) {
@@ -188,3 +202,55 @@ func parseAAParserVersion(output string) (int, error) {
return numericVersion, nil
}
+
+// CheckProfileAndLoadDefault checks if the specified profile is loaded and
+// loads the DefaultLibpodProfile if the specified on is prefixed by
+// DefaultLipodProfilePrefix. This allows to always load and apply the latest
+// default AppArmor profile. Note that AppArmor requires root. If it's a
+// default profile, return DefaultLipodProfilePrefix, otherwise the specified
+// one.
+func CheckProfileAndLoadDefault(name string) (string, error) {
+ if name == "unconfined" {
+ return name, nil
+ }
+
+ if name != "" && rootless.IsRootless() {
+ return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
+ }
+
+ if name != "" && !runcaa.IsEnabled() {
+ return "", fmt.Errorf("profile %q specified but AppArmor is disabled on the host", name)
+ }
+
+ // If the specified name is not empty or is not a default libpod one,
+ // ignore it and return the name.
+ if name != "" && !strings.HasPrefix(name, DefaultLipodProfilePrefix) {
+ isLoaded, err := IsLoaded(name)
+ if err != nil {
+ return "", err
+ }
+ if !isLoaded {
+ return "", fmt.Errorf("AppArmor profile %q specified but not loaded")
+ }
+ return name, nil
+ }
+
+ name = DefaultLibpodProfile
+ // To avoid expensive redundant loads on each invocation, check
+ // if it's loaded before installing it.
+ isLoaded, err := IsLoaded(name)
+ if err != nil {
+ return "", err
+ }
+ if !isLoaded {
+ err = InstallDefault(name)
+ if err != nil {
+ return "", err
+ }
+ logrus.Infof("successfully loaded AppAmor profile %q", name)
+ } else {
+ logrus.Infof("AppAmor profile %q is already loaded", name)
+ }
+
+ return name, nil
+}