|
@@ -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.
|
|
@@ -387,6 +411,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 +1082,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 +1097,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 +1126,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 +1173,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;
|
|
|
}
|
|
@@ -2102,6 +2149,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;
|