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

Commit 6e5a2d1d authored by Darrel Goeddel's avatar Darrel Goeddel Committed by Al Viro
Browse files

[PATCH] audit: support for object context filters



This patch introduces object audit filters based on the elements
of the SELinux context.

Signed-off-by: default avatarDarrel Goeddel <dgoeddel@trustedcs.com>
Acked-by: default avatarStephen Smalley <sds@tycho.nsa.gov>

 kernel/auditfilter.c           |   25 +++++++++++++++++++++++++
 kernel/auditsc.c               |   40 ++++++++++++++++++++++++++++++++++++++++
 security/selinux/ss/services.c |   18 +++++++++++++++++-
 3 files changed, 82 insertions(+), 1 deletion(-)
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3a6b9f85
Loading
Loading
Loading
Loading
+25 −0
Original line number Original line Diff line number Diff line
@@ -475,6 +475,11 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
		case AUDIT_SUBJ_CLR:
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			str = audit_unpack_string(&bufp, &remain, f->val);
			str = audit_unpack_string(&bufp, &remain, f->val);
			if (IS_ERR(str))
			if (IS_ERR(str))
				goto exit_free;
				goto exit_free;
@@ -616,6 +621,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
		case AUDIT_SUBJ_CLR:
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			data->buflen += data->values[i] =
			data->buflen += data->values[i] =
				audit_pack_string(&bufp, f->se_str);
				audit_pack_string(&bufp, f->se_str);
			break;
			break;
@@ -659,6 +669,11 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
		case AUDIT_SUBJ_CLR:
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
			if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
				return 1;
				return 1;
			break;
			break;
@@ -779,6 +794,11 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
		case AUDIT_SUBJ_CLR:
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			err = audit_dupe_selinux_field(&new->fields[i],
			err = audit_dupe_selinux_field(&new->fields[i],
						       &old->fields[i]);
						       &old->fields[i]);
			break;
			break;
@@ -1542,6 +1562,11 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule)
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
		case AUDIT_SUBJ_CLR:
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			return 1;
			return 1;
		}
		}
	}
	}
+40 −0
Original line number Original line Diff line number Diff line
@@ -342,6 +342,46 @@ static int audit_filter_rules(struct task_struct *tsk,
				                                  ctx);
				                                  ctx);
			}
			}
			break;
			break;
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
			   also applies here */
			if (f->se_rule) {
				/* Find files that match */
				if (name) {
					result = selinux_audit_rule_match(
					           name->osid, f->type, f->op,
					           f->se_rule, ctx);
				} else if (ctx) {
					for (j = 0; j < ctx->name_count; j++) {
						if (selinux_audit_rule_match(
						      ctx->names[j].osid,
						      f->type, f->op,
						      f->se_rule, ctx)) {
							++result;
							break;
						}
					}
				}
				/* Find ipc objects that match */
				if (ctx) {
					struct audit_aux_data *aux;
					for (aux = ctx->aux; aux;
					     aux = aux->next) {
						if (aux->type == AUDIT_IPC) {
							struct audit_aux_data_ipcctl *axi = (void *)aux;
							if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) {
								++result;
								break;
							}
						}
					}
				}
			}
			break;
		case AUDIT_ARG0:
		case AUDIT_ARG0:
		case AUDIT_ARG1:
		case AUDIT_ARG1:
		case AUDIT_ARG2:
		case AUDIT_ARG2:
+17 −1
Original line number Original line Diff line number Diff line
@@ -1848,12 +1848,17 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
	case AUDIT_SUBJ_USER:
	case AUDIT_SUBJ_USER:
	case AUDIT_SUBJ_ROLE:
	case AUDIT_SUBJ_ROLE:
	case AUDIT_SUBJ_TYPE:
	case AUDIT_SUBJ_TYPE:
	case AUDIT_OBJ_USER:
	case AUDIT_OBJ_ROLE:
	case AUDIT_OBJ_TYPE:
		/* only 'equals' and 'not equals' fit user, role, and type */
		/* only 'equals' and 'not equals' fit user, role, and type */
		if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
		if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
			return -EINVAL;
			return -EINVAL;
		break;
		break;
	case AUDIT_SUBJ_SEN:
	case AUDIT_SUBJ_SEN:
	case AUDIT_SUBJ_CLR:
	case AUDIT_SUBJ_CLR:
	case AUDIT_OBJ_LEV_LOW:
	case AUDIT_OBJ_LEV_HIGH:
		/* we do not allow a range, indicated by the presense of '-' */
		/* we do not allow a range, indicated by the presense of '-' */
		if (strchr(rulestr, '-'))
		if (strchr(rulestr, '-'))
			return -EINVAL;
			return -EINVAL;
@@ -1875,6 +1880,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,


	switch (field) {
	switch (field) {
	case AUDIT_SUBJ_USER:
	case AUDIT_SUBJ_USER:
	case AUDIT_OBJ_USER:
		userdatum = hashtab_search(policydb.p_users.table, rulestr);
		userdatum = hashtab_search(policydb.p_users.table, rulestr);
		if (!userdatum)
		if (!userdatum)
			rc = -EINVAL;
			rc = -EINVAL;
@@ -1882,6 +1888,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
			tmprule->au_ctxt.user = userdatum->value;
			tmprule->au_ctxt.user = userdatum->value;
		break;
		break;
	case AUDIT_SUBJ_ROLE:
	case AUDIT_SUBJ_ROLE:
	case AUDIT_OBJ_ROLE:
		roledatum = hashtab_search(policydb.p_roles.table, rulestr);
		roledatum = hashtab_search(policydb.p_roles.table, rulestr);
		if (!roledatum)
		if (!roledatum)
			rc = -EINVAL;
			rc = -EINVAL;
@@ -1889,6 +1896,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
			tmprule->au_ctxt.role = roledatum->value;
			tmprule->au_ctxt.role = roledatum->value;
		break;
		break;
	case AUDIT_SUBJ_TYPE:
	case AUDIT_SUBJ_TYPE:
	case AUDIT_OBJ_TYPE:
		typedatum = hashtab_search(policydb.p_types.table, rulestr);
		typedatum = hashtab_search(policydb.p_types.table, rulestr);
		if (!typedatum)
		if (!typedatum)
			rc = -EINVAL;
			rc = -EINVAL;
@@ -1897,6 +1905,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
		break;
		break;
	case AUDIT_SUBJ_SEN:
	case AUDIT_SUBJ_SEN:
	case AUDIT_SUBJ_CLR:
	case AUDIT_SUBJ_CLR:
	case AUDIT_OBJ_LEV_LOW:
	case AUDIT_OBJ_LEV_HIGH:
		rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
		rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
		break;
		break;
	}
	}
@@ -1949,6 +1959,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
	   without a match */
	   without a match */
	switch (field) {
	switch (field) {
	case AUDIT_SUBJ_USER:
	case AUDIT_SUBJ_USER:
	case AUDIT_OBJ_USER:
		switch (op) {
		switch (op) {
		case AUDIT_EQUAL:
		case AUDIT_EQUAL:
			match = (ctxt->user == rule->au_ctxt.user);
			match = (ctxt->user == rule->au_ctxt.user);
@@ -1959,6 +1970,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
		}
		}
		break;
		break;
	case AUDIT_SUBJ_ROLE:
	case AUDIT_SUBJ_ROLE:
	case AUDIT_OBJ_ROLE:
		switch (op) {
		switch (op) {
		case AUDIT_EQUAL:
		case AUDIT_EQUAL:
			match = (ctxt->role == rule->au_ctxt.role);
			match = (ctxt->role == rule->au_ctxt.role);
@@ -1969,6 +1981,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
		}
		}
		break;
		break;
	case AUDIT_SUBJ_TYPE:
	case AUDIT_SUBJ_TYPE:
	case AUDIT_OBJ_TYPE:
		switch (op) {
		switch (op) {
		case AUDIT_EQUAL:
		case AUDIT_EQUAL:
			match = (ctxt->type == rule->au_ctxt.type);
			match = (ctxt->type == rule->au_ctxt.type);
@@ -1980,7 +1993,10 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
		break;
		break;
	case AUDIT_SUBJ_SEN:
	case AUDIT_SUBJ_SEN:
	case AUDIT_SUBJ_CLR:
	case AUDIT_SUBJ_CLR:
		level = (field == AUDIT_SUBJ_SEN ?
	case AUDIT_OBJ_LEV_LOW:
	case AUDIT_OBJ_LEV_HIGH:
		level = ((field == AUDIT_SUBJ_SEN ||
		          field == AUDIT_OBJ_LEV_LOW) ?
		         &ctxt->range.level[0] : &ctxt->range.level[1]);
		         &ctxt->range.level[0] : &ctxt->range.level[1]);
		switch (op) {
		switch (op) {
		case AUDIT_EQUAL:
		case AUDIT_EQUAL: