diff options
author | Darrel Goeddel <dgoeddel@trustedcs.com> | 2006-06-29 17:57:08 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-07-01 05:44:19 -0400 |
commit | 6e5a2d1d32596850a0ebf7fb3e54c0d69901dabd (patch) | |
tree | 27718d7df96c9b9f08a2ba333aa36c8e9ebbadfe | |
parent | 3a6b9f85c641a3b89420b0c8150ed377526a1fe1 (diff) |
[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>
-rw-r--r-- | kernel/auditfilter.c | 25 | ||||
-rw-r--r-- | kernel/auditsc.c | 40 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 18 |
3 files changed, 82 insertions, 1 deletions
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 40a9931a13e2..7f2ea8b84a27 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, | |||
475 | case AUDIT_SUBJ_TYPE: | 475 | case AUDIT_SUBJ_TYPE: |
476 | case AUDIT_SUBJ_SEN: | 476 | case AUDIT_SUBJ_SEN: |
477 | case AUDIT_SUBJ_CLR: | 477 | case AUDIT_SUBJ_CLR: |
478 | case AUDIT_OBJ_USER: | ||
479 | case AUDIT_OBJ_ROLE: | ||
480 | case AUDIT_OBJ_TYPE: | ||
481 | case AUDIT_OBJ_LEV_LOW: | ||
482 | case AUDIT_OBJ_LEV_HIGH: | ||
478 | str = audit_unpack_string(&bufp, &remain, f->val); | 483 | str = audit_unpack_string(&bufp, &remain, f->val); |
479 | if (IS_ERR(str)) | 484 | if (IS_ERR(str)) |
480 | goto exit_free; | 485 | goto exit_free; |
@@ -616,6 +621,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | |||
616 | case AUDIT_SUBJ_TYPE: | 621 | case AUDIT_SUBJ_TYPE: |
617 | case AUDIT_SUBJ_SEN: | 622 | case AUDIT_SUBJ_SEN: |
618 | case AUDIT_SUBJ_CLR: | 623 | case AUDIT_SUBJ_CLR: |
624 | case AUDIT_OBJ_USER: | ||
625 | case AUDIT_OBJ_ROLE: | ||
626 | case AUDIT_OBJ_TYPE: | ||
627 | case AUDIT_OBJ_LEV_LOW: | ||
628 | case AUDIT_OBJ_LEV_HIGH: | ||
619 | data->buflen += data->values[i] = | 629 | data->buflen += data->values[i] = |
620 | audit_pack_string(&bufp, f->se_str); | 630 | audit_pack_string(&bufp, f->se_str); |
621 | break; | 631 | break; |
@@ -659,6 +669,11 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
659 | case AUDIT_SUBJ_TYPE: | 669 | case AUDIT_SUBJ_TYPE: |
660 | case AUDIT_SUBJ_SEN: | 670 | case AUDIT_SUBJ_SEN: |
661 | case AUDIT_SUBJ_CLR: | 671 | case AUDIT_SUBJ_CLR: |
672 | case AUDIT_OBJ_USER: | ||
673 | case AUDIT_OBJ_ROLE: | ||
674 | case AUDIT_OBJ_TYPE: | ||
675 | case AUDIT_OBJ_LEV_LOW: | ||
676 | case AUDIT_OBJ_LEV_HIGH: | ||
662 | if (strcmp(a->fields[i].se_str, b->fields[i].se_str)) | 677 | if (strcmp(a->fields[i].se_str, b->fields[i].se_str)) |
663 | return 1; | 678 | return 1; |
664 | break; | 679 | break; |
@@ -779,6 +794,11 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, | |||
779 | case AUDIT_SUBJ_TYPE: | 794 | case AUDIT_SUBJ_TYPE: |
780 | case AUDIT_SUBJ_SEN: | 795 | case AUDIT_SUBJ_SEN: |
781 | case AUDIT_SUBJ_CLR: | 796 | case AUDIT_SUBJ_CLR: |
797 | case AUDIT_OBJ_USER: | ||
798 | case AUDIT_OBJ_ROLE: | ||
799 | case AUDIT_OBJ_TYPE: | ||
800 | case AUDIT_OBJ_LEV_LOW: | ||
801 | case AUDIT_OBJ_LEV_HIGH: | ||
782 | err = audit_dupe_selinux_field(&new->fields[i], | 802 | err = audit_dupe_selinux_field(&new->fields[i], |
783 | &old->fields[i]); | 803 | &old->fields[i]); |
784 | break; | 804 | break; |
@@ -1542,6 +1562,11 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule) | |||
1542 | case AUDIT_SUBJ_TYPE: | 1562 | case AUDIT_SUBJ_TYPE: |
1543 | case AUDIT_SUBJ_SEN: | 1563 | case AUDIT_SUBJ_SEN: |
1544 | case AUDIT_SUBJ_CLR: | 1564 | case AUDIT_SUBJ_CLR: |
1565 | case AUDIT_OBJ_USER: | ||
1566 | case AUDIT_OBJ_ROLE: | ||
1567 | case AUDIT_OBJ_TYPE: | ||
1568 | case AUDIT_OBJ_LEV_LOW: | ||
1569 | case AUDIT_OBJ_LEV_HIGH: | ||
1545 | return 1; | 1570 | return 1; |
1546 | } | 1571 | } |
1547 | } | 1572 | } |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 1d24fade17e6..ae40ac8c39e7 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -342,6 +342,46 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
342 | ctx); | 342 | ctx); |
343 | } | 343 | } |
344 | break; | 344 | break; |
345 | case AUDIT_OBJ_USER: | ||
346 | case AUDIT_OBJ_ROLE: | ||
347 | case AUDIT_OBJ_TYPE: | ||
348 | case AUDIT_OBJ_LEV_LOW: | ||
349 | case AUDIT_OBJ_LEV_HIGH: | ||
350 | /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR | ||
351 | also applies here */ | ||
352 | if (f->se_rule) { | ||
353 | /* Find files that match */ | ||
354 | if (name) { | ||
355 | result = selinux_audit_rule_match( | ||
356 | name->osid, f->type, f->op, | ||
357 | f->se_rule, ctx); | ||
358 | } else if (ctx) { | ||
359 | for (j = 0; j < ctx->name_count; j++) { | ||
360 | if (selinux_audit_rule_match( | ||
361 | ctx->names[j].osid, | ||
362 | f->type, f->op, | ||
363 | f->se_rule, ctx)) { | ||
364 | ++result; | ||
365 | break; | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | /* Find ipc objects that match */ | ||
370 | if (ctx) { | ||
371 | struct audit_aux_data *aux; | ||
372 | for (aux = ctx->aux; aux; | ||
373 | aux = aux->next) { | ||
374 | if (aux->type == AUDIT_IPC) { | ||
375 | struct audit_aux_data_ipcctl *axi = (void *)aux; | ||
376 | if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) { | ||
377 | ++result; | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | break; | ||
345 | case AUDIT_ARG0: | 385 | case AUDIT_ARG0: |
346 | case AUDIT_ARG1: | 386 | case AUDIT_ARG1: |
347 | case AUDIT_ARG2: | 387 | case AUDIT_ARG2: |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 92e80b99d183..d2e80e62ff0c 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, | |||
1848 | case AUDIT_SUBJ_USER: | 1848 | case AUDIT_SUBJ_USER: |
1849 | case AUDIT_SUBJ_ROLE: | 1849 | case AUDIT_SUBJ_ROLE: |
1850 | case AUDIT_SUBJ_TYPE: | 1850 | case AUDIT_SUBJ_TYPE: |
1851 | case AUDIT_OBJ_USER: | ||
1852 | case AUDIT_OBJ_ROLE: | ||
1853 | case AUDIT_OBJ_TYPE: | ||
1851 | /* only 'equals' and 'not equals' fit user, role, and type */ | 1854 | /* only 'equals' and 'not equals' fit user, role, and type */ |
1852 | if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) | 1855 | if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) |
1853 | return -EINVAL; | 1856 | return -EINVAL; |
1854 | break; | 1857 | break; |
1855 | case AUDIT_SUBJ_SEN: | 1858 | case AUDIT_SUBJ_SEN: |
1856 | case AUDIT_SUBJ_CLR: | 1859 | case AUDIT_SUBJ_CLR: |
1860 | case AUDIT_OBJ_LEV_LOW: | ||
1861 | case AUDIT_OBJ_LEV_HIGH: | ||
1857 | /* we do not allow a range, indicated by the presense of '-' */ | 1862 | /* we do not allow a range, indicated by the presense of '-' */ |
1858 | if (strchr(rulestr, '-')) | 1863 | if (strchr(rulestr, '-')) |
1859 | return -EINVAL; | 1864 | return -EINVAL; |
@@ -1875,6 +1880,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
1875 | 1880 | ||
1876 | switch (field) { | 1881 | switch (field) { |
1877 | case AUDIT_SUBJ_USER: | 1882 | case AUDIT_SUBJ_USER: |
1883 | case AUDIT_OBJ_USER: | ||
1878 | userdatum = hashtab_search(policydb.p_users.table, rulestr); | 1884 | userdatum = hashtab_search(policydb.p_users.table, rulestr); |
1879 | if (!userdatum) | 1885 | if (!userdatum) |
1880 | rc = -EINVAL; | 1886 | rc = -EINVAL; |
@@ -1882,6 +1888,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
1882 | tmprule->au_ctxt.user = userdatum->value; | 1888 | tmprule->au_ctxt.user = userdatum->value; |
1883 | break; | 1889 | break; |
1884 | case AUDIT_SUBJ_ROLE: | 1890 | case AUDIT_SUBJ_ROLE: |
1891 | case AUDIT_OBJ_ROLE: | ||
1885 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); | 1892 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); |
1886 | if (!roledatum) | 1893 | if (!roledatum) |
1887 | rc = -EINVAL; | 1894 | rc = -EINVAL; |
@@ -1889,6 +1896,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
1889 | tmprule->au_ctxt.role = roledatum->value; | 1896 | tmprule->au_ctxt.role = roledatum->value; |
1890 | break; | 1897 | break; |
1891 | case AUDIT_SUBJ_TYPE: | 1898 | case AUDIT_SUBJ_TYPE: |
1899 | case AUDIT_OBJ_TYPE: | ||
1892 | typedatum = hashtab_search(policydb.p_types.table, rulestr); | 1900 | typedatum = hashtab_search(policydb.p_types.table, rulestr); |
1893 | if (!typedatum) | 1901 | if (!typedatum) |
1894 | rc = -EINVAL; | 1902 | rc = -EINVAL; |
@@ -1897,6 +1905,8 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
1897 | break; | 1905 | break; |
1898 | case AUDIT_SUBJ_SEN: | 1906 | case AUDIT_SUBJ_SEN: |
1899 | case AUDIT_SUBJ_CLR: | 1907 | case AUDIT_SUBJ_CLR: |
1908 | case AUDIT_OBJ_LEV_LOW: | ||
1909 | case AUDIT_OBJ_LEV_HIGH: | ||
1900 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); | 1910 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); |
1901 | break; | 1911 | break; |
1902 | } | 1912 | } |
@@ -1949,6 +1959,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1949 | without a match */ | 1959 | without a match */ |
1950 | switch (field) { | 1960 | switch (field) { |
1951 | case AUDIT_SUBJ_USER: | 1961 | case AUDIT_SUBJ_USER: |
1962 | case AUDIT_OBJ_USER: | ||
1952 | switch (op) { | 1963 | switch (op) { |
1953 | case AUDIT_EQUAL: | 1964 | case AUDIT_EQUAL: |
1954 | match = (ctxt->user == rule->au_ctxt.user); | 1965 | match = (ctxt->user == rule->au_ctxt.user); |
@@ -1959,6 +1970,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1959 | } | 1970 | } |
1960 | break; | 1971 | break; |
1961 | case AUDIT_SUBJ_ROLE: | 1972 | case AUDIT_SUBJ_ROLE: |
1973 | case AUDIT_OBJ_ROLE: | ||
1962 | switch (op) { | 1974 | switch (op) { |
1963 | case AUDIT_EQUAL: | 1975 | case AUDIT_EQUAL: |
1964 | match = (ctxt->role == rule->au_ctxt.role); | 1976 | match = (ctxt->role == rule->au_ctxt.role); |
@@ -1969,6 +1981,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1969 | } | 1981 | } |
1970 | break; | 1982 | break; |
1971 | case AUDIT_SUBJ_TYPE: | 1983 | case AUDIT_SUBJ_TYPE: |
1984 | case AUDIT_OBJ_TYPE: | ||
1972 | switch (op) { | 1985 | switch (op) { |
1973 | case AUDIT_EQUAL: | 1986 | case AUDIT_EQUAL: |
1974 | match = (ctxt->type == rule->au_ctxt.type); | 1987 | match = (ctxt->type == rule->au_ctxt.type); |
@@ -1980,7 +1993,10 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1980 | break; | 1993 | break; |
1981 | case AUDIT_SUBJ_SEN: | 1994 | case AUDIT_SUBJ_SEN: |
1982 | case AUDIT_SUBJ_CLR: | 1995 | case AUDIT_SUBJ_CLR: |
1983 | level = (field == AUDIT_SUBJ_SEN ? | 1996 | case AUDIT_OBJ_LEV_LOW: |
1997 | case AUDIT_OBJ_LEV_HIGH: | ||
1998 | level = ((field == AUDIT_SUBJ_SEN || | ||
1999 | field == AUDIT_OBJ_LEV_LOW) ? | ||
1984 | &ctxt->range.level[0] : &ctxt->range.level[1]); | 2000 | &ctxt->range.level[0] : &ctxt->range.level[1]); |
1985 | switch (op) { | 2001 | switch (op) { |
1986 | case AUDIT_EQUAL: | 2002 | case AUDIT_EQUAL: |