summary refs log tree commit diff
path: root/security/apparmor/audit.c
diff options
context:
space:
mode:
authorMatthew Garrett <mjg59@google.com>2018-04-16 11:23:58 -0700
committerJohn Johansen <john.johansen@canonical.com>2018-06-07 01:50:47 -0700
commite79c26d04043b15de64f082d4da52e9fff7ca607 (patch)
treecdca29dff22fd2e145e5fabf582d0e34cfd947d1 /security/apparmor/audit.c
parentb896c54e8d7bbf6d5d48f9296b26c9d3f10ec795 (diff)
downloadlinux-e79c26d04043b15de64f082d4da52e9fff7ca607.tar.gz
apparmor: Add support for audit rule filtering
This patch adds support to Apparmor for integrating with audit rule
filtering. Right now it only handles SUBJ_ROLE, interpreting it as a
single component of a label. This is sufficient to get Apparmor working
with IMA's appraisal rules without any modifications on the IMA side.

Signed-off-by: Matthew Garrett <mjg59@google.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/apparmor/audit.c')
-rw-r--r--security/apparmor/audit.c95
1 files changed, 94 insertions, 1 deletions
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 8f9ecac7f8de..7ac7c8190cc4 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -19,7 +19,7 @@
 #include "include/audit.h"
 #include "include/policy.h"
 #include "include/policy_ns.h"
-
+#include "include/secid.h"
 
 const char *const audit_mode_names[] = {
 	"normal",
@@ -163,3 +163,96 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
 
 	return aad(sa)->error;
 }
+
+struct aa_audit_rule {
+	char *profile;
+};
+
+void aa_audit_rule_free(void *vrule)
+{
+	struct aa_audit_rule *rule = vrule;
+
+	if (rule) {
+		kfree(rule->profile);
+		kfree(rule);
+	}
+}
+
+int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
+{
+	struct aa_audit_rule *rule;
+
+	switch (field) {
+	case AUDIT_SUBJ_ROLE:
+		if (op != Audit_equal && op != Audit_not_equal)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	rule = kzalloc(sizeof(struct aa_audit_rule), GFP_KERNEL);
+
+	if (!rule)
+		return -ENOMEM;
+
+	rule->profile = kstrdup(rulestr, GFP_KERNEL);
+
+	if (!rule->profile) {
+		kfree(rule);
+		return -ENOMEM;
+	}
+
+	*vrule = rule;
+
+	return 0;
+}
+
+int aa_audit_rule_known(struct audit_krule *rule)
+{
+	int i;
+
+	for (i = 0; i < rule->field_count; i++) {
+		struct audit_field *f = &rule->fields[i];
+
+		switch (f->type) {
+		case AUDIT_SUBJ_ROLE:
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
+			struct audit_context *actx)
+{
+	struct aa_audit_rule *rule = vrule;
+	struct aa_label *label;
+	struct label_it i;
+	struct aa_profile *profile;
+	int found = 0;
+
+	label = aa_secid_to_label(sid);
+
+	if (!label)
+		return -ENOENT;
+
+	label_for_each(i, label, profile) {
+		if (strcmp(rule->profile, profile->base.hname) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	switch (field) {
+	case AUDIT_SUBJ_ROLE:
+		switch (op) {
+		case Audit_equal:
+			return found;
+		case Audit_not_equal:
+			return !found;
+		}
+	}
+	return 0;
+}