Fix neverallowxperm checking on attributes
am: d922fef844

* commit 'd922fef84424ad3bba2e2f3fbd592cc51319b4ba':
  Fix neverallowxperm checking on attributes

Change-Id: I5e387ef684e5393dc440880b368d033e0da96010
diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c
index f4429ad..a4be880 100644
--- a/libsepol/src/assertion.c
+++ b/libsepol/src/assertion.c
@@ -147,8 +147,8 @@
 	avtab_key_t tmp_key;
 	avtab_extended_perms_t *xperms;
 	avtab_extended_perms_t error;
-	ebitmap_t *sattr = &p->type_attr_map[k->source_type - 1];
-	ebitmap_t *tattr = &p->type_attr_map[k->target_type - 1];
+	ebitmap_t *sattr = &p->type_attr_map[stype];
+	ebitmap_t *tattr = &p->type_attr_map[ttype];
 	ebitmap_node_t *snode, *tnode;
 	unsigned int i, j;
 	int rc = 1;
@@ -174,14 +174,14 @@
 					continue;
 
 				rc = check_extended_permissions(avrule->xperms, xperms);
-				/* failure on the extended permission check_extended_permissionss */
+				/* failure on the extended permission check_extended_permissions */
 				if (rc) {
 					extended_permissions_violated(&error, avrule->xperms, xperms);
 					ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
 							"allowxperm %s %s:%s %s;",
 							avrule->source_line, avrule->source_filename, avrule->line,
-							p->p_type_val_to_name[stype],
-							p->p_type_val_to_name[ttype],
+							p->p_type_val_to_name[i],
+							p->p_type_val_to_name[j],
 							p->p_class_val_to_name[curperm->tclass - 1],
 							sepol_extended_perms_to_string(&error));
 
@@ -317,29 +317,19 @@
 }
 
 /*
- * If the ioctl permission is granted in check_assertion_avtab_match for the
- * source/target/class matching the current avrule neverallow, a lookup is
- * performed to determine if extended permissions exist for the source/target/class.
- *
- * Four scenarios of interest:
- * 1. PASS - the ioctl permission is not granted for this source/target/class
- *    This case is handled in check_assertion_avtab_match
- * 2. PASS - The ioctl permission is granted AND the extended permission
- *    is NOT granted
- * 3. FAIL - The ioctl permission is granted AND no extended permissions
- *    exist
- * 4. FAIL - The ioctl permission is granted AND the extended permission is
- *    granted
+ * Look up the extended permissions in avtab and verify that neverallowed
+ * permissions are not granted.
  */
-static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
+static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab,
+						unsigned int stype, unsigned int ttype,
 						avtab_key_t *k, policydb_t *p)
 {
 	avtab_ptr_t node;
 	avtab_key_t tmp_key;
 	avtab_extended_perms_t *xperms;
 	av_extended_perms_t *neverallow_xperms = avrule->xperms;
-	ebitmap_t *sattr = &p->type_attr_map[k->source_type - 1];
-	ebitmap_t *tattr = &p->type_attr_map[k->target_type - 1];
+	ebitmap_t *sattr = &p->type_attr_map[stype];
+	ebitmap_t *tattr = &p->type_attr_map[ttype];
 	ebitmap_node_t *snode, *tnode;
 	unsigned int i, j;
 	int rc = 1;
@@ -373,6 +363,89 @@
 	return rc;
 }
 
+/*
+ * When the ioctl permission is granted on an avtab entry that matches an
+ * avrule neverallowxperm entry, enumerate over the matching
+ * source/target/class sets to determine if the extended permissions exist
+ * and if the neverallowed ioctls are granted.
+ *
+ * Four scenarios of interest:
+ * 1. PASS - the ioctl permission is not granted for this source/target/class
+ *    This case is handled in check_assertion_avtab_match
+ * 2. PASS - The ioctl permission is granted AND the extended permission
+ *    is NOT granted
+ * 3. FAIL - The ioctl permission is granted AND no extended permissions
+ *    exist
+ * 4. FAIL - The ioctl permission is granted AND the extended permission is
+ *    granted
+ */
+static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
+						avtab_key_t *k, policydb_t *p)
+{
+	ebitmap_t src_matches, tgt_matches, matches;
+	unsigned int i, j;
+	ebitmap_node_t *snode, *tnode;
+	class_perm_node_t *cp;
+	int rc;
+	int ret = 1;
+
+	ebitmap_init(&src_matches);
+	ebitmap_init(&tgt_matches);
+	ebitmap_init(&matches);
+	rc = ebitmap_and(&src_matches, &avrule->stypes.types,
+			 &p->attr_type_map[k->source_type - 1]);
+	if (rc)
+		goto oom;
+
+	if (ebitmap_length(&src_matches) == 0)
+		goto exit;
+
+	if (avrule->flags == RULE_SELF) {
+		rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1],
+				&p->attr_type_map[k->target_type - 1]);
+		if (rc)
+			goto oom;
+		rc = ebitmap_and(&tgt_matches, &avrule->stypes.types, &matches);
+		if (rc)
+			goto oom;
+	} else {
+		rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types,
+				&p->attr_type_map[k->target_type -1]);
+		if (rc)
+			goto oom;
+	}
+
+	if (ebitmap_length(&tgt_matches) == 0)
+		goto exit;
+
+	for (cp = avrule->perms; cp; cp = cp->next) {
+		if (cp->tclass != k->target_class)
+			continue;
+		ebitmap_for_each_bit(&src_matches, snode, i) {
+			if (!ebitmap_node_get_bit(snode, i))
+				continue;
+			ebitmap_for_each_bit(&tgt_matches, tnode, j) {
+				if (!ebitmap_node_get_bit(tnode, j))
+					continue;
+
+				ret = check_assertion_extended_permissions_avtab(
+						avrule, avtab, i, j, k, p);
+				if (ret)
+					goto exit;
+			}
+		}
+	}
+	goto exit;
+
+oom:
+	ERR(NULL, "Out of memory - unable to check neverallows");
+
+exit:
+	ebitmap_destroy(&src_matches);
+	ebitmap_destroy(&tgt_matches);
+	ebitmap_destroy(&matches);
+	return ret;
+}
 
 static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args)
 {
@@ -382,7 +455,7 @@
 	avrule_t *avrule = a->avrule;
 	avtab_t *avtab = a->avtab;
 
-	if (k->specified != AVTAB_ALLOWED && k->specified != AVTAB_XPERMS_ALLOWED)
+	if (k->specified != AVTAB_ALLOWED)
 		goto exit;
 
 	if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))