diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-02 00:43:05 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-02 00:43:05 -0400 |
| commit | 532f57da408c5a5710075d17047e2d97bdfd22f3 (patch) | |
| tree | 3fb378bea1816f637aeeed0df805d0c30969cfc3 /security/selinux/ss | |
| parent | 46c5ea3c9ae7fbc6e52a13c92e59d4fc7f4ca80a (diff) | |
| parent | 2ad312d2093ae506ae0fa184d8d026b559083087 (diff) | |
Merge branch 'audit.b10' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current
* 'audit.b10' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current:
[PATCH] Audit Filter Performance
[PATCH] Rework of IPC auditing
[PATCH] More user space subject labels
[PATCH] Reworked patch for labels on user space messages
[PATCH] change lspp ipc auditing
[PATCH] audit inode patch
[PATCH] support for context based audit filtering, part 2
[PATCH] support for context based audit filtering
[PATCH] no need to wank with task_lock() and pinning task down in audit_syscall_exit()
[PATCH] drop task argument of audit_syscall_{entry,exit}
[PATCH] drop gfp_mask in audit_log_exit()
[PATCH] move call of audit_free() into do_exit()
[PATCH] sockaddr patch
[PATCH] deal with deadlocks in audit_free()
Diffstat (limited to 'security/selinux/ss')
| -rw-r--r-- | security/selinux/ss/mls.c | 30 | ||||
| -rw-r--r-- | security/selinux/ss/mls.h | 4 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 235 |
3 files changed, 266 insertions, 3 deletions
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 84047f69f9c1..7bc5b6440f70 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * | 8 | * |
| 9 | * Support for enhanced MLS infrastructure. | 9 | * Support for enhanced MLS infrastructure. |
| 10 | * | 10 | * |
| 11 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 11 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| @@ -385,6 +385,34 @@ out: | |||
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | /* | 387 | /* |
| 388 | * Set the MLS fields in the security context structure | ||
| 389 | * `context' based on the string representation in | ||
| 390 | * the string `str'. This function will allocate temporary memory with the | ||
| 391 | * given constraints of gfp_mask. | ||
| 392 | */ | ||
| 393 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | ||
| 394 | { | ||
| 395 | char *tmpstr, *freestr; | ||
| 396 | int rc; | ||
| 397 | |||
| 398 | if (!selinux_mls_enabled) | ||
| 399 | return -EINVAL; | ||
| 400 | |||
| 401 | /* we need freestr because mls_context_to_sid will change | ||
| 402 | the value of tmpstr */ | ||
| 403 | tmpstr = freestr = kstrdup(str, gfp_mask); | ||
| 404 | if (!tmpstr) { | ||
| 405 | rc = -ENOMEM; | ||
| 406 | } else { | ||
| 407 | rc = mls_context_to_sid(':', &tmpstr, context, | ||
| 408 | NULL, SECSID_NULL); | ||
| 409 | kfree(freestr); | ||
| 410 | } | ||
| 411 | |||
| 412 | return rc; | ||
| 413 | } | ||
| 414 | |||
| 415 | /* | ||
| 388 | * Copies the effective MLS range from `src' into `dst'. | 416 | * Copies the effective MLS range from `src' into `dst'. |
| 389 | */ | 417 | */ |
| 390 | static inline int mls_scopy_context(struct context *dst, | 418 | static inline int mls_scopy_context(struct context *dst, |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 03de697c8058..fbb42f07dd7c 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * | 8 | * |
| 9 | * Support for enhanced MLS infrastructure. | 9 | * Support for enhanced MLS infrastructure. |
| 10 | * | 10 | * |
| 11 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 11 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #ifndef _SS_MLS_H_ | 14 | #ifndef _SS_MLS_H_ |
| @@ -27,6 +27,8 @@ int mls_context_to_sid(char oldc, | |||
| 27 | struct sidtab *s, | 27 | struct sidtab *s, |
| 28 | u32 def_sid); | 28 | u32 def_sid); |
| 29 | 29 | ||
| 30 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); | ||
| 31 | |||
| 30 | int mls_convert_context(struct policydb *oldp, | 32 | int mls_convert_context(struct policydb *oldp, |
| 31 | struct policydb *newp, | 33 | struct policydb *newp, |
| 32 | struct context *context); | 34 | struct context *context); |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 61492485de84..7177e98df7f3 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -7,12 +7,13 @@ | |||
| 7 | * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> | 7 | * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> |
| 8 | * | 8 | * |
| 9 | * Support for enhanced MLS infrastructure. | 9 | * Support for enhanced MLS infrastructure. |
| 10 | * Support for context based audit filters. | ||
| 10 | * | 11 | * |
| 11 | * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> | 12 | * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> |
| 12 | * | 13 | * |
| 13 | * Added conditional policy language extensions | 14 | * Added conditional policy language extensions |
| 14 | * | 15 | * |
| 15 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 16 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
| 16 | * Copyright (C) 2003 - 2004 Tresys Technology, LLC | 17 | * Copyright (C) 2003 - 2004 Tresys Technology, LLC |
| 17 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> | 18 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> |
| 18 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
| @@ -1811,3 +1812,235 @@ out: | |||
| 1811 | POLICY_RDUNLOCK; | 1812 | POLICY_RDUNLOCK; |
| 1812 | return rc; | 1813 | return rc; |
| 1813 | } | 1814 | } |
| 1815 | |||
| 1816 | struct selinux_audit_rule { | ||
| 1817 | u32 au_seqno; | ||
| 1818 | struct context au_ctxt; | ||
| 1819 | }; | ||
| 1820 | |||
| 1821 | void selinux_audit_rule_free(struct selinux_audit_rule *rule) | ||
| 1822 | { | ||
| 1823 | if (rule) { | ||
| 1824 | context_destroy(&rule->au_ctxt); | ||
| 1825 | kfree(rule); | ||
| 1826 | } | ||
| 1827 | } | ||
| 1828 | |||
| 1829 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | ||
| 1830 | struct selinux_audit_rule **rule) | ||
| 1831 | { | ||
| 1832 | struct selinux_audit_rule *tmprule; | ||
| 1833 | struct role_datum *roledatum; | ||
| 1834 | struct type_datum *typedatum; | ||
| 1835 | struct user_datum *userdatum; | ||
| 1836 | int rc = 0; | ||
| 1837 | |||
| 1838 | *rule = NULL; | ||
| 1839 | |||
| 1840 | if (!ss_initialized) | ||
| 1841 | return -ENOTSUPP; | ||
| 1842 | |||
| 1843 | switch (field) { | ||
| 1844 | case AUDIT_SE_USER: | ||
| 1845 | case AUDIT_SE_ROLE: | ||
| 1846 | case AUDIT_SE_TYPE: | ||
| 1847 | /* only 'equals' and 'not equals' fit user, role, and type */ | ||
| 1848 | if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) | ||
| 1849 | return -EINVAL; | ||
| 1850 | break; | ||
| 1851 | case AUDIT_SE_SEN: | ||
| 1852 | case AUDIT_SE_CLR: | ||
| 1853 | /* we do not allow a range, indicated by the presense of '-' */ | ||
| 1854 | if (strchr(rulestr, '-')) | ||
| 1855 | return -EINVAL; | ||
| 1856 | break; | ||
| 1857 | default: | ||
| 1858 | /* only the above fields are valid */ | ||
| 1859 | return -EINVAL; | ||
| 1860 | } | ||
| 1861 | |||
| 1862 | tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL); | ||
| 1863 | if (!tmprule) | ||
| 1864 | return -ENOMEM; | ||
| 1865 | |||
| 1866 | context_init(&tmprule->au_ctxt); | ||
| 1867 | |||
| 1868 | POLICY_RDLOCK; | ||
| 1869 | |||
| 1870 | tmprule->au_seqno = latest_granting; | ||
| 1871 | |||
| 1872 | switch (field) { | ||
| 1873 | case AUDIT_SE_USER: | ||
| 1874 | userdatum = hashtab_search(policydb.p_users.table, rulestr); | ||
| 1875 | if (!userdatum) | ||
| 1876 | rc = -EINVAL; | ||
| 1877 | else | ||
| 1878 | tmprule->au_ctxt.user = userdatum->value; | ||
| 1879 | break; | ||
| 1880 | case AUDIT_SE_ROLE: | ||
| 1881 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); | ||
| 1882 | if (!roledatum) | ||
| 1883 | rc = -EINVAL; | ||
| 1884 | else | ||
| 1885 | tmprule->au_ctxt.role = roledatum->value; | ||
| 1886 | break; | ||
| 1887 | case AUDIT_SE_TYPE: | ||
| 1888 | typedatum = hashtab_search(policydb.p_types.table, rulestr); | ||
| 1889 | if (!typedatum) | ||
| 1890 | rc = -EINVAL; | ||
| 1891 | else | ||
| 1892 | tmprule->au_ctxt.type = typedatum->value; | ||
| 1893 | break; | ||
| 1894 | case AUDIT_SE_SEN: | ||
| 1895 | case AUDIT_SE_CLR: | ||
| 1896 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); | ||
| 1897 | break; | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | POLICY_RDUNLOCK; | ||
| 1901 | |||
| 1902 | if (rc) { | ||
| 1903 | selinux_audit_rule_free(tmprule); | ||
| 1904 | tmprule = NULL; | ||
| 1905 | } | ||
| 1906 | |||
| 1907 | *rule = tmprule; | ||
| 1908 | |||
| 1909 | return rc; | ||
| 1910 | } | ||
| 1911 | |||
| 1912 | int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | ||
| 1913 | struct selinux_audit_rule *rule, | ||
| 1914 | struct audit_context *actx) | ||
| 1915 | { | ||
| 1916 | struct context *ctxt; | ||
| 1917 | struct mls_level *level; | ||
| 1918 | int match = 0; | ||
| 1919 | |||
| 1920 | if (!rule) { | ||
| 1921 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
| 1922 | "selinux_audit_rule_match: missing rule\n"); | ||
| 1923 | return -ENOENT; | ||
| 1924 | } | ||
| 1925 | |||
| 1926 | POLICY_RDLOCK; | ||
| 1927 | |||
| 1928 | if (rule->au_seqno < latest_granting) { | ||
| 1929 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
| 1930 | "selinux_audit_rule_match: stale rule\n"); | ||
| 1931 | match = -ESTALE; | ||
| 1932 | goto out; | ||
| 1933 | } | ||
| 1934 | |||
| 1935 | ctxt = sidtab_search(&sidtab, ctxid); | ||
| 1936 | if (!ctxt) { | ||
| 1937 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
| 1938 | "selinux_audit_rule_match: unrecognized SID %d\n", | ||
| 1939 | ctxid); | ||
| 1940 | match = -ENOENT; | ||
| 1941 | goto out; | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | /* a field/op pair that is not caught here will simply fall through | ||
| 1945 | without a match */ | ||
| 1946 | switch (field) { | ||
| 1947 | case AUDIT_SE_USER: | ||
| 1948 | switch (op) { | ||
| 1949 | case AUDIT_EQUAL: | ||
| 1950 | match = (ctxt->user == rule->au_ctxt.user); | ||
| 1951 | break; | ||
| 1952 | case AUDIT_NOT_EQUAL: | ||
| 1953 | match = (ctxt->user != rule->au_ctxt.user); | ||
| 1954 | break; | ||
| 1955 | } | ||
| 1956 | break; | ||
| 1957 | case AUDIT_SE_ROLE: | ||
| 1958 | switch (op) { | ||
| 1959 | case AUDIT_EQUAL: | ||
| 1960 | match = (ctxt->role == rule->au_ctxt.role); | ||
| 1961 | break; | ||
| 1962 | case AUDIT_NOT_EQUAL: | ||
| 1963 | match = (ctxt->role != rule->au_ctxt.role); | ||
| 1964 | break; | ||
| 1965 | } | ||
| 1966 | break; | ||
| 1967 | case AUDIT_SE_TYPE: | ||
| 1968 | switch (op) { | ||
| 1969 | case AUDIT_EQUAL: | ||
| 1970 | match = (ctxt->type == rule->au_ctxt.type); | ||
| 1971 | break; | ||
| 1972 | case AUDIT_NOT_EQUAL: | ||
| 1973 | match = (ctxt->type != rule->au_ctxt.type); | ||
| 1974 | break; | ||
| 1975 | } | ||
| 1976 | break; | ||
| 1977 | case AUDIT_SE_SEN: | ||
| 1978 | case AUDIT_SE_CLR: | ||
| 1979 | level = (op == AUDIT_SE_SEN ? | ||
| 1980 | &ctxt->range.level[0] : &ctxt->range.level[1]); | ||
| 1981 | switch (op) { | ||
| 1982 | case AUDIT_EQUAL: | ||
| 1983 | match = mls_level_eq(&rule->au_ctxt.range.level[0], | ||
| 1984 | level); | ||
| 1985 | break; | ||
| 1986 | case AUDIT_NOT_EQUAL: | ||
| 1987 | match = !mls_level_eq(&rule->au_ctxt.range.level[0], | ||
| 1988 | level); | ||
| 1989 | break; | ||
| 1990 | case AUDIT_LESS_THAN: | ||
| 1991 | match = (mls_level_dom(&rule->au_ctxt.range.level[0], | ||
| 1992 | level) && | ||
| 1993 | !mls_level_eq(&rule->au_ctxt.range.level[0], | ||
| 1994 | level)); | ||
| 1995 | break; | ||
| 1996 | case AUDIT_LESS_THAN_OR_EQUAL: | ||
| 1997 | match = mls_level_dom(&rule->au_ctxt.range.level[0], | ||
| 1998 | level); | ||
| 1999 | break; | ||
| 2000 | case AUDIT_GREATER_THAN: | ||
| 2001 | match = (mls_level_dom(level, | ||
| 2002 | &rule->au_ctxt.range.level[0]) && | ||
| 2003 | !mls_level_eq(level, | ||
| 2004 | &rule->au_ctxt.range.level[0])); | ||
| 2005 | break; | ||
| 2006 | case AUDIT_GREATER_THAN_OR_EQUAL: | ||
| 2007 | match = mls_level_dom(level, | ||
| 2008 | &rule->au_ctxt.range.level[0]); | ||
| 2009 | break; | ||
| 2010 | } | ||
| 2011 | } | ||
| 2012 | |||
| 2013 | out: | ||
| 2014 | POLICY_RDUNLOCK; | ||
| 2015 | return match; | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | static int (*aurule_callback)(void) = NULL; | ||
| 2019 | |||
| 2020 | static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, | ||
| 2021 | u16 class, u32 perms, u32 *retained) | ||
| 2022 | { | ||
| 2023 | int err = 0; | ||
| 2024 | |||
| 2025 | if (event == AVC_CALLBACK_RESET && aurule_callback) | ||
| 2026 | err = aurule_callback(); | ||
| 2027 | return err; | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | static int __init aurule_init(void) | ||
| 2031 | { | ||
| 2032 | int err; | ||
| 2033 | |||
| 2034 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, | ||
| 2035 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
| 2036 | if (err) | ||
| 2037 | panic("avc_add_callback() failed, error %d\n", err); | ||
| 2038 | |||
| 2039 | return err; | ||
| 2040 | } | ||
| 2041 | __initcall(aurule_init); | ||
| 2042 | |||
| 2043 | void selinux_audit_set_callback(int (*callback)(void)) | ||
| 2044 | { | ||
| 2045 | aurule_callback = callback; | ||
| 2046 | } | ||
