[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 <dgoeddel@trustedcs.com> Acked-by: Stephen 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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
3a6b9f85c6
commit
6e5a2d1d32
3 changed files with 82 additions and 1 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue