Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e79c26d0 authored by Matthew Garrett's avatar Matthew Garrett Committed by John Johansen
Browse files

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: default avatarMatthew Garrett <mjg59@google.com>
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent b896c54e
Loading
Loading
Loading
Loading
+94 −1
Original line number Diff line number Diff line
@@ -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;
}
+6 −0
Original line number Diff line number Diff line
@@ -189,4 +189,10 @@ static inline int complain_error(int error)
	return error;
}

void aa_audit_rule_free(void *vrule);
int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule);
int aa_audit_rule_known(struct audit_krule *rule);
int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
			struct audit_context *actx);

#endif /* __AA_AUDIT_H */
+7 −0
Original line number Diff line number Diff line
@@ -1198,6 +1198,13 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
	LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
	LSM_HOOK_INIT(task_kill, apparmor_task_kill),

#ifdef CONFIG_AUDIT
	LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init),
	LSM_HOOK_INIT(audit_rule_known, aa_audit_rule_known),
	LSM_HOOK_INIT(audit_rule_match, aa_audit_rule_match),
	LSM_HOOK_INIT(audit_rule_free, aa_audit_rule_free),
#endif

	LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx),
	LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid),
	LSM_HOOK_INIT(release_secctx, apparmor_release_secctx),