]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - security/selinux/ss/services.c
SELinux: Add network port SID cache
[linux-3.10.git] / security / selinux / ss / services.c
index f374186012151e42ba197ac80391a147fb3821f7..d75050819b0641c346cbbe0d4e3dbbfacbbada99 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"
@@ -61,6 +62,7 @@ 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 +414,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 +707,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 +737,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 +837,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 +857,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 +1123,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 +1134,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 +1152,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 +1163,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 +1184,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 +1199,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 +1210,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 +1246,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 +1326,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 +1335,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 +1379,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 +1413,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 +1472,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;
@@ -2201,7 +2226,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;
        }