security/selinux: Add missing "space"
[deliverable/linux.git] / security / selinux / ss / services.c
index f00161ef99ed17450ae395913730ca4154469e2d..f83b19daed16181a86ede00b8d1455432f05acec 100644 (file)
@@ -292,6 +292,7 @@ static int context_struct_compute_av(struct context *scontext,
        struct class_datum *tclass_datum;
        struct ebitmap *sattr, *tattr;
        struct ebitmap_node *snode, *tnode;
+       const struct selinux_class_perm *kdefs = &selinux_class_perm;
        unsigned int i, j;
 
        /*
@@ -305,13 +306,6 @@ static int context_struct_compute_av(struct context *scontext,
                    tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
                        tclass = SECCLASS_NETLINK_SOCKET;
 
-       if (!tclass || tclass > policydb.p_classes.nprim) {
-               printk(KERN_ERR "security_compute_av:  unrecognized class %d\n",
-                      tclass);
-               return -EINVAL;
-       }
-       tclass_datum = policydb.class_val_to_struct[tclass - 1];
-
        /*
         * Initialize the access vectors to the default values.
         */
@@ -321,6 +315,36 @@ static int context_struct_compute_av(struct context *scontext,
        avd->auditdeny = 0xffffffff;
        avd->seqno = latest_granting;
 
+       /*
+        * Check for all the invalid cases.
+        * - tclass 0
+        * - tclass > policy and > kernel
+        * - tclass > policy but is a userspace class
+        * - tclass > policy but we do not allow unknowns
+        */
+       if (unlikely(!tclass))
+               goto inval_class;
+       if (unlikely(tclass > policydb.p_classes.nprim))
+               if (tclass > kdefs->cts_len ||
+                   !kdefs->class_to_string[tclass - 1] ||
+                   !policydb.allow_unknown)
+                       goto inval_class;
+
+       /*
+        * Kernel class and we allow unknown so pad the allow decision
+        * the pad will be all 1 for unknown classes.
+        */
+       if (tclass <= kdefs->cts_len && policydb.allow_unknown)
+               avd->allowed = policydb.undefined_perms[tclass - 1];
+
+       /*
+        * Not in policy. Since decision is completed (all 1 or all 0) return.
+        */
+       if (unlikely(tclass > policydb.p_classes.nprim))
+               return 0;
+
+       tclass_datum = policydb.class_val_to_struct[tclass - 1];
+
        /*
         * If a specific type enforcement rule was defined for
         * this permission check, then use it.
@@ -329,12 +353,8 @@ static int context_struct_compute_av(struct context *scontext,
        avkey.specified = AVTAB_AV;
        sattr = &policydb.type_attr_map[scontext->type - 1];
        tattr = &policydb.type_attr_map[tcontext->type - 1];
-       ebitmap_for_each_bit(sattr, snode, i) {
-               if (!ebitmap_node_get_bit(snode, i))
-                       continue;
-               ebitmap_for_each_bit(tattr, tnode, j) {
-                       if (!ebitmap_node_get_bit(tnode, j))
-                               continue;
+       ebitmap_for_each_positive_bit(sattr, snode, i) {
+               ebitmap_for_each_positive_bit(tattr, tnode, j) {
                        avkey.source_type = i + 1;
                        avkey.target_type = j + 1;
                        for (node = avtab_search_node(&policydb.te_avtab, &avkey);
@@ -387,6 +407,10 @@ static int context_struct_compute_av(struct context *scontext,
        }
 
        return 0;
+
+inval_class:
+       printk(KERN_ERR "%s:  unrecognized class %d\n", __FUNCTION__, tclass);
+       return -EINVAL;
 }
 
 static int security_validtrans_handle_fail(struct context *ocontext,
@@ -1054,6 +1078,13 @@ static int validate_classes(struct policydb *p)
        const char *def_class, *def_perm, *pol_class;
        struct symtab *perms;
 
+       if (p->allow_unknown) {
+               u32 num_classes = kdefs->cts_len;
+               p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL);
+               if (!p->undefined_perms)
+                       return -ENOMEM;
+       }
+
        for (i = 1; i < kdefs->cts_len; i++) {
                def_class = kdefs->class_to_string[i];
                if (!def_class)
@@ -1062,6 +1093,10 @@ static int validate_classes(struct policydb *p)
                        printk(KERN_INFO
                               "security:  class %s not defined in policy\n",
                               def_class);
+                       if (p->reject_unknown)
+                               return -EINVAL;
+                       if (p->allow_unknown)
+                               p->undefined_perms[i-1] = ~0U;
                        continue;
                }
                pol_class = p->p_class_val_to_name[i-1];
@@ -1087,12 +1122,16 @@ static int validate_classes(struct policydb *p)
                        printk(KERN_INFO
                               "security:  permission %s in class %s not defined in policy\n",
                               def_perm, pol_class);
+                       if (p->reject_unknown)
+                               return -EINVAL;
+                       if (p->allow_unknown)
+                               p->undefined_perms[class_val-1] |= perm_val;
                        continue;
                }
                perdatum = hashtab_search(perms->table, def_perm);
                if (perdatum == NULL) {
                        printk(KERN_ERR
-                              "security:  permission %s in class %s not found in policy\n",
+                              "security:  permission %s in class %s not found in policy, bad policy\n",
                               def_perm, pol_class);
                        return -EINVAL;
                }
@@ -1130,12 +1169,16 @@ static int validate_classes(struct policydb *p)
                                printk(KERN_INFO
                                       "security:  permission %s in class %s not defined in policy\n",
                                       def_perm, pol_class);
+                               if (p->reject_unknown)
+                                       return -EINVAL;
+                               if (p->allow_unknown)
+                                       p->undefined_perms[class_val-1] |= (1 << j);
                                continue;
                        }
                        perdatum = hashtab_search(perms->table, def_perm);
                        if (perdatum == NULL) {
                                printk(KERN_ERR
-                                      "security:  permission %s in class %s not found in policy\n",
+                                      "security:  permission %s in class %s not found in policy, bad policy\n",
                                       def_perm, pol_class);
                                return -EINVAL;
                        }
@@ -1621,14 +1664,10 @@ int security_get_user_sids(u32 fromsid,
                goto out_unlock;
        }
 
-       ebitmap_for_each_bit(&user->roles, rnode, i) {
-               if (!ebitmap_node_get_bit(rnode, i))
-                       continue;
+       ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
                role = policydb.role_val_to_struct[i];
                usercon.role = i+1;
-               ebitmap_for_each_bit(&role->types, tnode, j) {
-                       if (!ebitmap_node_get_bit(tnode, j))
-                               continue;
+               ebitmap_for_each_positive_bit(&role->types, tnode, j) {
                        usercon.type = j+1;
 
                        if (mls_setup_user_range(fromcon, user, &usercon))
@@ -2102,6 +2141,16 @@ err:
        return rc;
 }
 
+int security_get_reject_unknown(void)
+{
+       return policydb.reject_unknown;
+}
+
+int security_get_allow_unknown(void)
+{
+       return policydb.allow_unknown;
+}
+
 struct selinux_audit_rule {
        u32 au_seqno;
        struct context au_ctxt;
@@ -2127,7 +2176,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
        *rule = NULL;
 
        if (!ss_initialized)
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        switch (field) {
        case AUDIT_SUBJ_USER:
@@ -2557,8 +2606,6 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
        int rc = -ENOENT;
        struct context *ctx;
 
-       netlbl_secattr_init(secattr);
-
        if (!ss_initialized)
                return 0;
 
This page took 0.029599 seconds and 5 git commands to generate.