]> err.no Git - linux-2.6/blobdiff - security/selinux/ss/services.c
SELinux: mls.c whitespace, syntax, and static declaraction cleanups
[linux-2.6] / security / selinux / ss / services.c
index f96dec1f9258f31c88525543c59d586354619649..b341b8fd8c7cddf6d0672cb31ec650a402396c45 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/sched.h>
 #include <linux/audit.h>
 #include <linux/mutex.h>
+#include <linux/selinux.h>
 #include <net/netlabel.h>
 
 #include "flask.h"
 #include "netlabel.h"
 #include "xfrm.h"
 #include "ebitmap.h"
+#include "audit.h"
 
 extern void selnl_notify_policyload(u32 seqno);
 unsigned int policydb_loaded_version;
 
 int selinux_policycap_netpeer;
+int selinux_policycap_openperm;
 
 /*
  * This is declared in avc.c
@@ -412,10 +415,35 @@ static int context_struct_compute_av(struct context *scontext,
        return 0;
 
 inval_class:
-       printk(KERN_ERR "%s:  unrecognized class %d\n", __FUNCTION__, tclass);
+       printk(KERN_ERR "%s:  unrecognized class %d\n", __func__, tclass);
        return -EINVAL;
 }
 
+/*
+ * Given a sid find if the type has the permissive flag set
+ */
+int security_permissive_sid(u32 sid)
+{
+       struct context *context;
+       u32 type;
+       int rc;
+
+       POLICY_RDLOCK;
+
+       context = sidtab_search(&sidtab, sid);
+       BUG_ON(!context);
+
+       type = context->type;
+       /*
+        * we are intentionally using type here, not type-1, the 0th bit may
+        * someday indicate that we are globally setting permissive in policy.
+        */
+       rc = ebitmap_get_bit(&policydb.permissive_map, type);
+
+       POLICY_RDUNLOCK;
+       return rc;
+}
+
 static int security_validtrans_handle_fail(struct context *ocontext,
                                            struct context *ncontext,
                                            struct context *tcontext,
@@ -680,7 +708,8 @@ out:
 
 }
 
-static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
+static int security_context_to_sid_core(char *scontext, u32 scontext_len,
+                                       u32 *sid, u32 def_sid, gfp_t gfp_flags)
 {
        char *scontext2;
        struct context context;
@@ -709,7 +738,7 @@ static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *s
           null suffix to the copy to avoid problems with the existing
           attr package, which doesn't view the null terminator as part
           of the attribute value. */
-       scontext2 = kmalloc(scontext_len+1,GFP_KERNEL);
+       scontext2 = kmalloc(scontext_len+1, gfp_flags);
        if (!scontext2) {
                rc = -ENOMEM;
                goto out;
@@ -809,7 +838,7 @@ out:
 int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
 {
        return security_context_to_sid_core(scontext, scontext_len,
-                                           sid, SECSID_NULL);
+                                           sid, SECSID_NULL, GFP_KERNEL);
 }
 
 /**
@@ -829,10 +858,11 @@ int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
-int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid)
+int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid,
+                                   u32 def_sid, gfp_t gfp_flags)
 {
        return security_context_to_sid_core(scontext, scontext_len,
-                                           sid, def_sid);
+                                           sid, def_sid, gfp_flags);
 }
 
 static int compute_sid_handle_invalid_context(
@@ -1094,7 +1124,7 @@ static int validate_classes(struct policydb *p)
                        continue;
                if (i > p->p_classes.nprim) {
                        printk(KERN_INFO
-                              "security:  class %s not defined in policy\n",
+                              "SELinux:  class %s not defined in policy\n",
                               def_class);
                        if (p->reject_unknown)
                                return -EINVAL;
@@ -1105,7 +1135,7 @@ static int validate_classes(struct policydb *p)
                pol_class = p->p_class_val_to_name[i-1];
                if (strcmp(pol_class, def_class)) {
                        printk(KERN_ERR
-                              "security:  class %d is incorrect, found %s but should be %s\n",
+                              "SELinux:  class %d is incorrect, found %s but should be %s\n",
                               i, pol_class, def_class);
                        return -EINVAL;
                }
@@ -1123,7 +1153,7 @@ static int validate_classes(struct policydb *p)
                nprim = 1 << (perms->nprim - 1);
                if (perm_val > nprim) {
                        printk(KERN_INFO
-                              "security:  permission %s in class %s not defined in policy\n",
+                              "SELinux:  permission %s in class %s not defined in policy\n",
                               def_perm, pol_class);
                        if (p->reject_unknown)
                                return -EINVAL;
@@ -1134,14 +1164,14 @@ static int validate_classes(struct policydb *p)
                perdatum = hashtab_search(perms->table, def_perm);
                if (perdatum == NULL) {
                        printk(KERN_ERR
-                              "security:  permission %s in class %s not found in policy, bad policy\n",
+                              "SELinux:  permission %s in class %s not found in policy, bad policy\n",
                               def_perm, pol_class);
                        return -EINVAL;
                }
                pol_val = 1 << (perdatum->value - 1);
                if (pol_val != perm_val) {
                        printk(KERN_ERR
-                              "security:  permission %s in class %s has incorrect value\n",
+                              "SELinux:  permission %s in class %s has incorrect value\n",
                               def_perm, pol_class);
                        return -EINVAL;
                }
@@ -1155,7 +1185,7 @@ static int validate_classes(struct policydb *p)
                BUG_ON(!cladatum);
                if (!cladatum->comdatum) {
                        printk(KERN_ERR
-                              "security:  class %s should have an inherits clause but does not\n",
+                              "SELinux:  class %s should have an inherits clause but does not\n",
                               pol_class);
                        return -EINVAL;
                }
@@ -1170,7 +1200,7 @@ static int validate_classes(struct policydb *p)
                        def_perm = kdefs->av_inherit[i].common_pts[j];
                        if (j >= perms->nprim) {
                                printk(KERN_INFO
-                                      "security:  permission %s in class %s not defined in policy\n",
+                                      "SELinux:  permission %s in class %s not defined in policy\n",
                                       def_perm, pol_class);
                                if (p->reject_unknown)
                                        return -EINVAL;
@@ -1181,13 +1211,13 @@ static int validate_classes(struct policydb *p)
                        perdatum = hashtab_search(perms->table, def_perm);
                        if (perdatum == NULL) {
                                printk(KERN_ERR
-                                      "security:  permission %s in class %s not found in policy, bad policy\n",
+                                      "SELinux:  permission %s in class %s not found in policy, bad policy\n",
                                       def_perm, pol_class);
                                return -EINVAL;
                        }
                        if (perdatum->value != j + 1) {
                                printk(KERN_ERR
-                                      "security:  permission %s in class %s has incorrect value\n",
+                                      "SELinux:  permission %s in class %s has incorrect value\n",
                                       def_perm, pol_class);
                                return -EINVAL;
                        }
@@ -1217,7 +1247,7 @@ static inline int convert_context_handle_invalid_context(struct context *context
                u32 len;
 
                context_struct_to_string(context, &s, &len);
-               printk(KERN_ERR "security:  context %s is invalid\n", s);
+               printk(KERN_ERR "SELinux:  context %s is invalid\n", s);
                kfree(s);
        }
        return rc;
@@ -1297,7 +1327,7 @@ out:
 bad:
        context_struct_to_string(&oldc, &s, &len);
        context_destroy(&oldc);
-       printk(KERN_ERR "security:  invalidating context %s\n", s);
+       printk(KERN_ERR "SELinux:  invalidating context %s\n", s);
        kfree(s);
        goto out;
 }
@@ -1306,6 +1336,8 @@ static void security_load_policycaps(void)
 {
        selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
                                                  POLICYDB_CAPABILITY_NETPEER);
+       selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
+                                                 POLICYDB_CAPABILITY_OPENPERM);
 }
 
 extern void selinux_complete_init(void);
@@ -1348,7 +1380,7 @@ int security_load_policy(void *data, size_t len)
                /* Verify that the kernel defined classes are correct. */
                if (validate_classes(&policydb)) {
                        printk(KERN_ERR
-                              "security:  the definition of a class is incorrect\n");
+                              "SELinux:  the definition of a class is incorrect\n");
                        LOAD_UNLOCK;
                        sidtab_destroy(&sidtab);
                        policydb_destroy(&policydb);
@@ -1382,14 +1414,14 @@ int security_load_policy(void *data, size_t len)
        /* Verify that the kernel defined classes are correct. */
        if (validate_classes(&newpolicydb)) {
                printk(KERN_ERR
-                      "security:  the definition of a class is incorrect\n");
+                      "SELinux:  the definition of a class is incorrect\n");
                rc = -EINVAL;
                goto err;
        }
 
        rc = security_preserve_bools(&newpolicydb);
        if (rc) {
-               printk(KERN_ERR "security:  unable to preserve booleans\n");
+               printk(KERN_ERR "SELinux:  unable to preserve booleans\n");
                goto err;
        }
 
@@ -1441,17 +1473,11 @@ err:
 
 /**
  * security_port_sid - Obtain the SID for a port.
- * @domain: communication domain aka address family
- * @type: socket type
  * @protocol: protocol number
  * @port: port number
  * @out_sid: security identifier
  */
-int security_port_sid(u16 domain,
-                     u16 type,
-                     u8 protocol,
-                     u16 port,
-                     u32 *out_sid)
+int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 {
        struct ocontext *c;
        int rc = 0;
@@ -1905,11 +1931,12 @@ int security_set_bools(int len, int *values)
                if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
                        audit_log(current->audit_context, GFP_ATOMIC,
                                AUDIT_MAC_CONFIG_CHANGE,
-                               "bool=%s val=%d old_val=%d auid=%u",
+                               "bool=%s val=%d old_val=%d auid=%u ses=%u",
                                policydb.p_bool_val_to_name[i],
                                !!values[i],
                                policydb.bool_val_to_struct[i]->state,
-                               audit_get_loginuid(current->audit_context));
+                               audit_get_loginuid(current),
+                               audit_get_sessionid(current));
                }
                if (values[i]) {
                        policydb.bool_val_to_struct[i]->state = 1;
@@ -2200,7 +2227,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
        match = hashtab_search(policydb.p_classes.table, class);
        if (!match) {
                printk(KERN_ERR "%s:  unrecognized class %s\n",
-                       __FUNCTION__, class);
+                       __func__, class);
                rc = -EINVAL;
                goto out;
        }
@@ -2244,39 +2271,6 @@ int security_get_allow_unknown(void)
        return policydb.allow_unknown;
 }
 
-/**
- * security_get_policycaps - Query the loaded policy for its capabilities
- * @len: the number of capability bits
- * @values: the capability bit array
- *
- * Description:
- * Get an array of the policy capabilities in @values where each entry in
- * @values is either true (1) or false (0) depending the policy's support of
- * that feature.  The policy capabilities are defined by the
- * POLICYDB_CAPABILITY_* enums.  The size of the array is stored in @len and it
- * is up to the caller to free the array in @values.  Returns zero on success,
- * negative values on failure.
- *
- */
-int security_get_policycaps(int *len, int **values)
-{
-       int rc = -ENOMEM;
-       unsigned int iter;
-
-       POLICY_RDLOCK;
-
-       *values = kcalloc(POLICYDB_CAPABILITY_MAX, sizeof(int), GFP_ATOMIC);
-       if (*values == NULL)
-               goto out;
-       for (iter = 0; iter < POLICYDB_CAPABILITY_MAX; iter++)
-               (*values)[iter] = ebitmap_get_bit(&policydb.policycaps, iter);
-       *len = POLICYDB_CAPABILITY_MAX;
-
-out:
-       POLICY_RDUNLOCK;
-       return rc;
-}
-
 /**
  * security_policycap_supported - Check for a specific policy capability
  * @req_cap: capability
@@ -2303,21 +2297,23 @@ struct selinux_audit_rule {
        struct context au_ctxt;
 };
 
-void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+void selinux_audit_rule_free(void *vrule)
 {
+       struct selinux_audit_rule *rule = vrule;
+
        if (rule) {
                context_destroy(&rule->au_ctxt);
                kfree(rule);
        }
 }
 
-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
-                            struct selinux_audit_rule **rule)
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 {
        struct selinux_audit_rule *tmprule;
        struct role_datum *roledatum;
        struct type_datum *typedatum;
        struct user_datum *userdatum;
+       struct selinux_audit_rule **rule = (struct selinux_audit_rule **)vrule;
        int rc = 0;
 
        *rule = NULL;
@@ -2404,12 +2400,37 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
        return rc;
 }
 
-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
-                             struct selinux_audit_rule *rule,
+/* Check to see if the rule contains any selinux fields */
+int selinux_audit_rule_known(struct audit_krule *rule)
+{
+       int i;
+
+       for (i = 0; i < rule->field_count; i++) {
+               struct audit_field *f = &rule->fields[i];
+               switch (f->type) {
+               case AUDIT_SUBJ_USER:
+               case AUDIT_SUBJ_ROLE:
+               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;
+               }
+       }
+
+       return 0;
+}
+
+int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
                              struct audit_context *actx)
 {
        struct context *ctxt;
        struct mls_level *level;
+       struct selinux_audit_rule *rule = vrule;
        int match = 0;
 
        if (!rule) {
@@ -2516,7 +2537,7 @@ out:
        return match;
 }
 
-static int (*aurule_callback)(void) = NULL;
+static int (*aurule_callback)(void) = audit_update_lsm_rules;
 
 static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
                                u16 class, u32 perms, u32 *retained)
@@ -2541,11 +2562,6 @@ static int __init aurule_init(void)
 }
 __initcall(aurule_init);
 
-void selinux_audit_set_callback(int (*callback)(void))
-{
-       aurule_callback = callback;
-}
-
 #ifdef CONFIG_NETLABEL
 /**
  * security_netlbl_cache_add - Add an entry to the NetLabel cache
@@ -2681,7 +2697,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
                goto netlbl_sid_to_secattr_failure;
        secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
                                  GFP_ATOMIC);
-       secattr->flags |= NETLBL_SECATTR_DOMAIN;
+       secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY;
        mls_export_netlbl_lvl(ctx, secattr);
        rc = mls_export_netlbl_cat(ctx, secattr);
        if (rc != 0)
@@ -2692,7 +2708,6 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 
 netlbl_sid_to_secattr_failure:
        POLICY_RDUNLOCK;
-       netlbl_secattr_destroy(secattr);
        return rc;
 }
 #endif /* CONFIG_NETLABEL */