From: Darrel Goeddel Date: Thu, 29 Jun 2006 21:57:08 +0000 (-0500) Subject: [PATCH] audit: support for object context filters X-Git-Tag: v2.6.18-rc1~191^2~1 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e5a2d1d32596850a0ebf7fb3e54c0d69901dabd;p=linux-2.6 [PATCH] audit: support for object context filters This patch introduces object audit filters based on the elements of the SELinux context. Signed-off-by: Darrel Goeddel Acked-by: Stephen Smalley kernel/auditfilter.c | 25 +++++++++++++++++++++++++ kernel/auditsc.c | 40 ++++++++++++++++++++++++++++++++++++++++ security/selinux/ss/services.c | 18 +++++++++++++++++- 3 files changed, 82 insertions(+), 1 deletion(-) Signed-off-by: Al Viro --- diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 40a9931a13..7f2ea8b84a 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -475,6 +475,11 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_SUBJ_TYPE: case AUDIT_SUBJ_SEN: 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); if (IS_ERR(str)) 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_SEN: 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] = audit_pack_string(&bufp, f->se_str); 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_SEN: 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)) return 1; break; @@ -779,6 +794,11 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, case AUDIT_SUBJ_TYPE: case AUDIT_SUBJ_SEN: 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], &old->fields[i]); break; @@ -1542,6 +1562,11 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule) case AUDIT_SUBJ_TYPE: case AUDIT_SUBJ_SEN: 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; } } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 1d24fade17..ae40ac8c39 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -342,6 +342,46 @@ static int audit_filter_rules(struct task_struct *tsk, ctx); } 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_ARG1: case AUDIT_ARG2: diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 92e80b99d1..d2e80e62ff 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1848,12 +1848,17 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, case AUDIT_SUBJ_USER: case AUDIT_SUBJ_ROLE: 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 */ if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) return -EINVAL; break; case AUDIT_SUBJ_SEN: 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 '-' */ if (strchr(rulestr, '-')) return -EINVAL; @@ -1875,6 +1880,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, switch (field) { case AUDIT_SUBJ_USER: + case AUDIT_OBJ_USER: userdatum = hashtab_search(policydb.p_users.table, rulestr); if (!userdatum) rc = -EINVAL; @@ -1882,6 +1888,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, tmprule->au_ctxt.user = userdatum->value; break; case AUDIT_SUBJ_ROLE: + case AUDIT_OBJ_ROLE: roledatum = hashtab_search(policydb.p_roles.table, rulestr); if (!roledatum) rc = -EINVAL; @@ -1889,6 +1896,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, tmprule->au_ctxt.role = roledatum->value; break; case AUDIT_SUBJ_TYPE: + case AUDIT_OBJ_TYPE: typedatum = hashtab_search(policydb.p_types.table, rulestr); if (!typedatum) rc = -EINVAL; @@ -1897,6 +1905,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, break; case AUDIT_SUBJ_SEN: case AUDIT_SUBJ_CLR: + case AUDIT_OBJ_LEV_LOW: + case AUDIT_OBJ_LEV_HIGH: rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); break; } @@ -1949,6 +1959,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, without a match */ switch (field) { case AUDIT_SUBJ_USER: + case AUDIT_OBJ_USER: switch (op) { case AUDIT_EQUAL: match = (ctxt->user == rule->au_ctxt.user); @@ -1959,6 +1970,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, } break; case AUDIT_SUBJ_ROLE: + case AUDIT_OBJ_ROLE: switch (op) { case AUDIT_EQUAL: match = (ctxt->role == rule->au_ctxt.role); @@ -1969,6 +1981,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, } break; case AUDIT_SUBJ_TYPE: + case AUDIT_OBJ_TYPE: switch (op) { case AUDIT_EQUAL: match = (ctxt->type == rule->au_ctxt.type); @@ -1980,7 +1993,10 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, break; case AUDIT_SUBJ_SEN: 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]); switch (op) { case AUDIT_EQUAL: