Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are met:
      6  *
      7  *    1. Redistributions of source code must retain the above copyright notice,
      8  *       this list of conditions and the following disclaimer.
      9  *
     10  *    2. Redistributions in binary form must reproduce the above copyright notice,
     11  *       this list of conditions and the following disclaimer in the documentation
     12  *       and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
     15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  *
     25  * The views and conclusions contained in the software and documentation are those
     26  * of the authors and should not be interpreted as representing official policies,
     27  * either expressed or implied, of Tresys Technology, LLC.
     28  */
     29 
     30 #include <stdlib.h>
     31 #include <stdio.h>
     32 #include <string.h>
     33 #include <stdint.h>
     34 #include <unistd.h>
     35 #include <ctype.h>
     36 
     37 #include <sepol/policydb/polcaps.h>
     38 #include <sepol/errcodes.h>
     39 
     40 #include "cil_internal.h"
     41 #include "cil_flavor.h"
     42 #include "cil_log.h"
     43 #include "cil_mem.h"
     44 #include "cil_tree.h"
     45 #include "cil_list.h"
     46 #include "cil_find.h"
     47 
     48 #include "cil_verify.h"
     49 
     50 int __cil_verify_name(const char *name)
     51 {
     52 	int rc = SEPOL_ERR;
     53 	int len;
     54 	int i = 0;
     55 
     56 	if (name == NULL) {
     57 		cil_log(CIL_ERR, "Name is NULL\n");
     58 		goto exit;
     59 	}
     60 
     61 	len = strlen(name);
     62 	if (len >= CIL_MAX_NAME_LENGTH) {
     63 		cil_log(CIL_ERR, "Name length greater than max name length of %d",
     64 			CIL_MAX_NAME_LENGTH);
     65 		rc = SEPOL_ERR;
     66 		goto exit;
     67 	}
     68 
     69 	if (!isalpha(name[0])) {
     70 			cil_log(CIL_ERR, "First character in %s is not a letter\n", name);
     71 			goto exit;
     72 	}
     73 
     74 	for (i = 1; i < len; i++) {
     75 		if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
     76 			cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
     77 			goto exit;
     78 		}
     79 	}
     80 	return SEPOL_OK;
     81 
     82 exit:
     83 	cil_log(CIL_ERR, "Invalid name\n");
     84 	return rc;
     85 }
     86 
     87 int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len)
     88 {
     89 	int rc = SEPOL_ERR;
     90 	int num_extras = 0;
     91 	struct cil_tree_node *c = parse_current;
     92 	int i = 0;
     93 	while (i < len) {
     94 		if ((s[i] & CIL_SYN_END) && c == NULL) {
     95 			break;
     96 		}
     97 
     98 		if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) {
     99 			if (c == NULL) {
    100 				if (num_extras > 0) {
    101 					i++;
    102 					continue;
    103 				} else {
    104 					goto exit;
    105 				}
    106 			} else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) {
    107 				c = c->next;
    108 				num_extras++;
    109 				continue;
    110 			} else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) {
    111 				c = c->next;
    112 				num_extras++;
    113 				continue;
    114 			}
    115 		}
    116 
    117 		if (c == NULL) {
    118 			goto exit;
    119 		}
    120 
    121 		if (s[i] & CIL_SYN_STRING) {
    122 			if (c->data != NULL && c->cl_head == NULL) {
    123 				c = c->next;
    124 				i++;
    125 				continue;
    126 			}
    127 		}
    128 
    129 		if (s[i] & CIL_SYN_LIST) {
    130 			if (c->data == NULL && c->cl_head != NULL) {
    131 				c = c->next;
    132 				i++;
    133 				continue;
    134 			}
    135 		}
    136 
    137 		if (s[i] & CIL_SYN_EMPTY_LIST) {
    138 			if (c->data == NULL && c->cl_head == NULL) {
    139 				c = c->next;
    140 				i++;
    141 				continue;
    142 			}
    143 		}
    144 		goto exit;
    145 	}
    146 	return SEPOL_OK;
    147 
    148 exit:
    149 	cil_log(CIL_ERR, "Invalid syntax\n");
    150 	return rc;
    151 }
    152 
    153 int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor)
    154 {
    155 	int rc;
    156 	enum cil_syntax syntax[] = {
    157 		CIL_SYN_STRING,
    158 		CIL_SYN_STRING | CIL_SYN_LIST,
    159 		CIL_SYN_STRING | CIL_SYN_LIST,
    160 		CIL_SYN_END
    161 	};
    162 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    163 
    164 	switch (op) {
    165 	case CIL_NOT:
    166 		syntax[2] = CIL_SYN_END;
    167 		syntax_len = 3;
    168 		break;
    169 	case CIL_AND:
    170 	case CIL_OR:
    171 	case CIL_XOR:
    172 		break;
    173 	case CIL_EQ:
    174 	case CIL_NEQ:
    175 		if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) {
    176 			cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data);
    177 			goto exit;
    178 		}
    179 		break;
    180 	case CIL_ALL:
    181 		if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) {
    182 			cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data);
    183 			goto exit;
    184 		}
    185 		syntax[1] = CIL_SYN_END;
    186 		syntax_len = 2;
    187 		break;
    188 	case CIL_RANGE:
    189 		if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) {
    190 			cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data);
    191 			goto exit;
    192 		}
    193 		syntax[1] = CIL_SYN_STRING;
    194 		syntax[2] = CIL_SYN_STRING;
    195 		break;
    196 	case CIL_NONE: /* String or List */
    197 		syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS;
    198 		syntax[1] = CIL_SYN_END;
    199 		syntax_len = 2;
    200 		break;
    201 	default:
    202 		cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data);
    203 		goto exit;
    204 	}
    205 
    206 	rc = __cil_verify_syntax(current, syntax, syntax_len);
    207 	if (rc != SEPOL_OK) {
    208 		goto exit;
    209 	}
    210 
    211 	return SEPOL_OK;
    212 
    213 exit:
    214 	return SEPOL_ERR;
    215 }
    216 
    217 int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor)
    218 {
    219 	if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) {
    220 		if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) {
    221 			cil_log(CIL_ERR, "l1, l2, h1, and h2 cannot be used on the left side with a string or list on the right side\n");
    222 			goto exit;
    223 		} else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) {
    224 			if (expr_flavor != CIL_MLSVALIDATETRANS) {
    225 				cil_log(CIL_ERR, "u3, r3, and t3 can only be used with mlsvalidatetrans rules\n");
    226 				goto exit;
    227 			}
    228 		}
    229 	} else {
    230 		if (r_flavor == CIL_CONS_U2) {
    231 			if (op != CIL_EQ && op != CIL_NEQ) {
    232 				cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
    233 				goto exit;
    234 			} else if (l_flavor != CIL_CONS_U1) {
    235 				cil_log(CIL_ERR, "u2 on the right side must be used with u1 on the left\n");
    236 				goto exit;
    237 			}
    238 		} else if (r_flavor == CIL_CONS_R2) {
    239 			if (l_flavor != CIL_CONS_R1) {
    240 				cil_log(CIL_ERR, "r2 on the right side must be used with r1 on the left\n");
    241 				goto exit;
    242 			}
    243 		} else if (r_flavor == CIL_CONS_T2) {
    244 			if (op != CIL_EQ && op != CIL_NEQ) {
    245 				cil_log(CIL_ERR, "t2 on the right side must be used with eq or neq as the operator\n");
    246 				goto exit;
    247 			} else if (l_flavor != CIL_CONS_T1) {
    248 				cil_log(CIL_ERR, "t2 on the right side must be used with t1 on the left\n");
    249 				goto exit;
    250 			}
    251 		} else if (r_flavor == CIL_CONS_L2) {
    252 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_H1) {
    253 				cil_log(CIL_ERR, "l2 on the right side must be used with l1 or h1 on the left\n");
    254 				goto exit;
    255 			}
    256 		} else if (r_flavor == CIL_CONS_H2) {
    257 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_L2 && l_flavor != CIL_CONS_H1 ) {
    258 				cil_log(CIL_ERR, "h2 on the right side must be used with l1, l2, or h1 on the left\n");
    259 				goto exit;
    260 			}
    261 		} else if (r_flavor == CIL_CONS_H1) {
    262 			if (l_flavor != CIL_CONS_L1) {
    263 				cil_log(CIL_ERR, "h1 on the right side must be used with l1 on the left\n");
    264 				goto exit;
    265 			}
    266 		}
    267 	}
    268 
    269 	return SEPOL_OK;
    270 
    271 exit:
    272 	return SEPOL_ERR;
    273 }
    274 
    275 int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op)
    276 {
    277 	int rc;
    278 	enum cil_syntax syntax[] = {
    279 		CIL_SYN_STRING,
    280 		CIL_SYN_END,
    281 		CIL_SYN_END,
    282 		CIL_SYN_END
    283 	};
    284 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    285 
    286 	switch (op) {
    287 	case CIL_NOT:
    288 		syntax[1] = CIL_SYN_LIST;
    289 		syntax_len--;
    290 		break;
    291 	case CIL_AND:
    292 	case CIL_OR:
    293 		syntax[1] = CIL_SYN_LIST;
    294 		syntax[2] = CIL_SYN_LIST;
    295 		break;
    296 	case CIL_EQ:
    297 	case CIL_NEQ:
    298 		syntax[1] = CIL_SYN_STRING;
    299 		syntax[2] = CIL_SYN_STRING | CIL_SYN_LIST;
    300 		break;
    301 	case CIL_CONS_DOM:
    302 	case CIL_CONS_DOMBY:
    303 	case CIL_CONS_INCOMP:
    304 		syntax[1] = CIL_SYN_STRING;
    305 		syntax[2] = CIL_SYN_STRING;
    306 		break;
    307 	default:
    308 		cil_log(CIL_ERR, "Invalid operator (%s) for constraint expression\n", (char*)current->data);
    309 		goto exit;
    310 	}
    311 
    312 	rc = __cil_verify_syntax(current, syntax, syntax_len);
    313 	if (rc != SEPOL_OK) {
    314 		cil_log(CIL_ERR, "Invalid constraint syntax\n");
    315 		goto exit;
    316 	}
    317 
    318 	return SEPOL_OK;
    319 
    320 exit:
    321 	return SEPOL_ERR;
    322 }
    323 
    324 int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
    325 {
    326 	struct cil_list_item *i;
    327 
    328 	cil_list_for_each(i, datum_list) {
    329 		if (i->flavor == CIL_DATUM) {
    330 			struct cil_symtab_datum *d = i->data;
    331 			if (d == datum) {
    332 				cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name);
    333 				return SEPOL_ERR;
    334 			}
    335 		} else if (i->flavor == CIL_LIST) {
    336 			int rc = cil_verify_no_self_reference(datum, i->data);
    337 			if (rc != SEPOL_OK) {
    338 				return SEPOL_ERR;
    339 			}
    340 		}
    341 	}
    342 
    343 	return SEPOL_OK;
    344 }
    345 
    346 int __cil_verify_ranges(struct cil_list *list)
    347 {
    348 	int rc = SEPOL_ERR;
    349 	struct cil_list_item *curr;
    350 	struct cil_list_item *range = NULL;
    351 
    352 	if (list == NULL || list->head == NULL) {
    353 		goto exit;
    354 	}
    355 
    356 	cil_list_for_each(curr, list) {
    357 		/* range */
    358 		if (curr->flavor == CIL_LIST) {
    359 			range = ((struct cil_list*)curr->data)->head;
    360 			if (range == NULL || range->next == NULL || range->next->next != NULL) {
    361 				goto exit;
    362 			}
    363 		}
    364 	}
    365 
    366 	return SEPOL_OK;
    367 
    368 exit:
    369 	cil_log(CIL_ERR,"Invalid Range syntax\n");
    370 	return rc;
    371 }
    372 
    373 struct cil_args_verify_order {
    374 	uint32_t *flavor;
    375 };
    376 
    377 int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
    378 {
    379 	struct cil_args_verify_order *args = extra_args;
    380 	uint32_t *flavor = args->flavor;
    381 
    382 	if (node->flavor == *flavor) {
    383 		if (node->flavor == CIL_SID) {
    384 			struct cil_sid *sid = node->data;
    385 			if (sid->ordered == CIL_FALSE) {
    386 				cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name);
    387 				return SEPOL_ERR;
    388 			}
    389 		} else if (node->flavor == CIL_CLASS) {
    390 			struct cil_class *class = node->data;
    391 			if (class->ordered == CIL_FALSE) {
    392 				cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name);
    393 				return SEPOL_ERR;
    394 			}
    395 		} else if (node->flavor == CIL_CAT) {
    396 			struct cil_cat *cat = node->data;
    397 			if (cat->ordered == CIL_FALSE) {
    398 				cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name);
    399 				return SEPOL_ERR;
    400 			}
    401 		} else if (node->flavor == CIL_SENS) {
    402 			struct cil_sens *sens = node->data;
    403 			if (sens->ordered == CIL_FALSE) {
    404 				cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name);
    405 				return SEPOL_ERR;
    406 			}
    407 		}
    408 	}
    409 
    410 	return SEPOL_OK;
    411 }
    412 
    413 int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor)
    414 {
    415 	struct cil_args_verify_order extra_args;
    416 	int rc = SEPOL_ERR;
    417 
    418 	extra_args.flavor = &flavor;
    419 
    420 	rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args);
    421 
    422 	return rc;
    423 }
    424 
    425 int __cil_verify_initsids(struct cil_list *sids)
    426 {
    427 	int rc = SEPOL_OK;
    428 	struct cil_list_item *i;
    429 
    430 	if (sids->head == NULL) {
    431 		cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n");
    432 		return SEPOL_ERR;
    433 	}
    434 
    435 	cil_list_for_each(i, sids) {
    436 		struct cil_sid *sid = i->data;
    437 		if (sid->context == NULL) {
    438 			struct cil_tree_node *node = sid->datum.nodes->head->data;
    439 			cil_tree_log(node, CIL_ERR, "No context assigned to SID %s declared",sid->datum.name);
    440 			rc = SEPOL_ERR;
    441 		}
    442 	}
    443 
    444 	return rc;
    445 }
    446 
    447 int __cil_is_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
    448 {
    449 	struct cil_list_item *i;
    450 
    451 	cil_list_for_each(i, cats->datum_expr) {
    452 		struct cil_cat *c = i->data;
    453 		if (c == cat) {
    454 			return CIL_TRUE;
    455 		}
    456 	}
    457 
    458 	return CIL_FALSE;
    459 }
    460 
    461 
    462 int __cil_verify_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
    463 {
    464 	if (__cil_is_cat_in_cats(cat, cats) != CIL_TRUE) {
    465 		cil_log(CIL_ERR, "Failed to find category %s in category list\n", cat->datum.name);
    466 		return SEPOL_ERR;
    467 	}
    468 
    469 	return SEPOL_OK;
    470 }
    471 
    472 int __cil_verify_cats_associated_with_sens(struct cil_sens *sens, struct cil_cats *cats)
    473 {
    474 	int rc = SEPOL_OK;
    475 	struct cil_list_item *i, *j;
    476 
    477 	if (!cats) {
    478 		return SEPOL_OK;
    479 	}
    480 
    481 	if (!sens->cats_list) {
    482 		cil_log(CIL_ERR, "No categories can be used with sensitivity %s\n", sens->datum.name);
    483 		return SEPOL_ERR;
    484 	}
    485 
    486 	cil_list_for_each(i, cats->datum_expr) {
    487 		struct cil_cat *cat = i->data;
    488 		int ok = CIL_FALSE;
    489 		cil_list_for_each(j, sens->cats_list) {
    490 			if (__cil_is_cat_in_cats(cat, j->data) == CIL_TRUE) {
    491 				ok = CIL_TRUE;
    492 				break;
    493 			}
    494 		}
    495 
    496 		if (ok != CIL_TRUE) {
    497 			cil_log(CIL_ERR, "Category %s cannot be used with sensitivity %s\n",
    498 					cat->datum.name, sens->datum.name);
    499 			rc = SEPOL_ERR;
    500 		}
    501 	}
    502 
    503 	return rc;
    504 }
    505 
    506 int __cil_verify_levelrange_sensitivity(struct cil_db *db, struct cil_sens *low, struct cil_sens *high)
    507 {
    508 	struct cil_list_item *curr;
    509 	int found = CIL_FALSE;
    510 	int rc = SEPOL_ERR;
    511 
    512 	cil_list_for_each(curr, db->sensitivityorder) {
    513 		if (curr->data == low) {
    514 			found = CIL_TRUE;
    515 		}
    516 
    517 		if ((found == CIL_TRUE) && (curr->data == high)) {
    518 			break;
    519 		}
    520 	}
    521 
    522 	if (found != CIL_TRUE || curr == NULL) {
    523 		goto exit;
    524 	}
    525 
    526 	return SEPOL_OK;
    527 
    528 exit:
    529 	cil_log(CIL_ERR, "Sensitivity %s does not dominate %s\n",
    530 		high->datum.name, low->datum.name);
    531 	return rc;
    532 
    533 }
    534 
    535 int __cil_verify_levelrange_cats(struct cil_cats *low, struct cil_cats *high)
    536 {
    537 	int rc = SEPOL_ERR;
    538 	struct cil_list_item *item;
    539 
    540 	if (low == NULL || (low == NULL && high == NULL)) {
    541 		return SEPOL_OK;
    542 	}
    543 
    544 	if (high == NULL) {
    545 		rc = SEPOL_ERR;
    546 		goto exit;
    547 	}
    548 
    549 	cil_list_for_each(item, low->datum_expr) {
    550 		rc = __cil_verify_cat_in_cats(item->data, high);
    551 		if (rc != SEPOL_OK) {
    552 			goto exit;
    553 		}
    554 	}
    555 
    556 	return SEPOL_OK;
    557 
    558 exit:
    559 	cil_log(CIL_ERR, "Low level category set must be a subset of the high level category set\n");
    560 	return rc;
    561 }
    562 
    563 int __cil_verify_levelrange(struct cil_db *db, struct cil_levelrange *lr)
    564 {
    565 	int rc = SEPOL_ERR;
    566 
    567 	rc = __cil_verify_levelrange_sensitivity(db, lr->low->sens, lr->high->sens);
    568 	if (rc != SEPOL_OK) {
    569 		goto exit;
    570 	}
    571 
    572 	rc = __cil_verify_levelrange_cats(lr->low->cats, lr->high->cats);
    573 	if (rc != SEPOL_OK) {
    574 		goto exit;
    575 	}
    576 
    577 	rc = __cil_verify_cats_associated_with_sens(lr->low->sens, lr->low->cats);
    578 	if (rc != SEPOL_OK) {
    579 		cil_log(CIL_ERR, "Low level sensitivity and categories are not associated\n");
    580 		goto exit;
    581 	}
    582 
    583 	rc = __cil_verify_cats_associated_with_sens(lr->high->sens, lr->high->cats);
    584 	if (rc != SEPOL_OK) {
    585 		cil_log(CIL_ERR, "High level sensitivity and categories are not associated\n");
    586 		goto exit;
    587 	}
    588 
    589 	return SEPOL_OK;
    590 
    591 exit:
    592 	return rc;
    593 }
    594 
    595 int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node)
    596 {
    597 	int rc = SEPOL_ERR;
    598 	struct cil_levelrange *lr = node->data;
    599 
    600 	rc = __cil_verify_levelrange(db, lr);
    601 	if (rc != SEPOL_OK) {
    602 		goto exit;
    603 	}
    604 
    605 	return SEPOL_OK;
    606 exit:
    607 	cil_tree_log(node, CIL_ERR, "Invalid named range");
    608 	return rc;
    609 }
    610 
    611 static int __cil_verify_user_pre_eval(struct cil_tree_node *node)
    612 {
    613 	int rc = SEPOL_ERR;
    614 	struct cil_user *user = node->data;
    615 
    616 	if (user->dftlevel == NULL) {
    617 		cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name);
    618 		goto exit;
    619 	} else if (user->range == NULL) {
    620 		cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name);
    621 		goto exit;
    622 	} else if (user->bounds != NULL) {
    623 		int steps = 0;
    624 		int limit = 2;
    625 		struct cil_user *u1 = user;
    626 		struct cil_user *u2 = user->bounds;
    627 
    628 		while (u2 != NULL) {
    629 			if (u1 == u2) {
    630 				cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name);
    631 				goto exit;
    632 			}
    633 
    634 			if (steps == limit) {
    635 				steps = 0;
    636 				limit *= 2;
    637 				u1 = u2;
    638 			}
    639 
    640 			u2 = u2->bounds;
    641 			steps++;
    642 		}
    643 	}
    644 
    645 	return SEPOL_OK;
    646 exit:
    647 	cil_tree_log(node, CIL_ERR, "Invalid user");
    648 	return rc;
    649 }
    650 
    651 static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node)
    652 {
    653 	int rc = SEPOL_ERR;
    654 	struct cil_user *user = node->data;
    655 
    656 	/* Verify user range only if anonymous */
    657 	if (user->range->datum.name == NULL) {
    658 		rc = __cil_verify_levelrange(db, user->range);
    659 		if (rc != SEPOL_OK) {
    660 			goto exit;
    661 		}
    662 	}
    663 
    664 	return SEPOL_OK;
    665 exit:
    666 	cil_tree_log(node, CIL_ERR, "Invalid user");
    667 	return rc;
    668 }
    669 
    670 int __cil_verify_role(struct cil_tree_node *node)
    671 {
    672 	int rc = SEPOL_ERR;
    673 	struct cil_role *role = node->data;
    674 	int steps = 0;
    675 	int limit = 2;
    676 	struct cil_role *r1 = role;
    677 	struct cil_role *r2 = role->bounds;
    678 
    679 	while (r2 != NULL) {
    680 		if (r1 == r2) {
    681 			cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name);
    682 			goto exit;
    683 		}
    684 
    685 		if (steps == limit) {
    686 			steps = 0;
    687 			limit *= 2;
    688 			r1 = r2;
    689 		}
    690 
    691 		r2 = r2->bounds;
    692 		steps++;
    693 	}
    694 
    695 	return SEPOL_OK;
    696 exit:
    697 	cil_tree_log(node, CIL_ERR, "Invalid role");
    698 	return rc;
    699 }
    700 
    701 int __cil_verify_type(struct cil_tree_node *node)
    702 {
    703 	int rc = SEPOL_ERR;
    704 	struct cil_type *type = node->data;
    705 	int steps = 0;
    706 	int limit = 2;
    707 	struct cil_type *t1 = type;
    708 	struct cil_type *t2 = type->bounds;
    709 
    710 	while (t2 != NULL) {
    711 		if (t1 == t2) {
    712 			cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name);
    713 			goto exit;
    714 		}
    715 
    716 		if (steps == limit) {
    717 			steps = 0;
    718 			limit *= 2;
    719 			t1 = t2;
    720 		}
    721 
    722 		t2 = t2->bounds;
    723 		steps++;
    724 	}
    725 
    726 	return SEPOL_OK;
    727 exit:
    728 	cil_tree_log(node, CIL_ERR, "Invalid type");
    729 	return rc;
    730 }
    731 
    732 int __cil_verify_context(struct cil_db *db, struct cil_context *ctx)
    733 {
    734 	int rc = SEPOL_ERR;
    735 	struct cil_user *user = ctx->user;
    736 	struct cil_role *role = ctx->role;
    737 	struct cil_type *type = ctx->type;
    738 	struct cil_level *user_low = user->range->low;
    739 	struct cil_level *user_high = user->range->high;
    740 	struct cil_level *ctx_low = ctx->range->low;
    741 	struct cil_level *ctx_high = ctx->range->high;
    742 	struct cil_list *sensitivityorder = db->sensitivityorder;
    743 	struct cil_list_item *curr;
    744 	int found = CIL_FALSE;
    745 
    746 	if (user->roles != NULL) {
    747 		if (!ebitmap_get_bit(user->roles, role->value)) {
    748 			cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str);
    749 			rc = SEPOL_ERR;
    750 			goto exit;
    751 		}
    752 	} else {
    753 		cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str);
    754 		rc = SEPOL_ERR;
    755 		goto exit;
    756 	}
    757 
    758 	if (role->types != NULL) {
    759 		if (!ebitmap_get_bit(role->types, type->value)) {
    760 			cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str);
    761 			rc = SEPOL_ERR;
    762 			goto exit;
    763 		}
    764 	} else {
    765 		cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str);
    766 		rc = SEPOL_ERR;
    767 		goto exit;
    768 	}
    769 
    770 	/* Verify range only when anonymous */
    771 	if (ctx->range->datum.name == NULL) {
    772 		rc = __cil_verify_levelrange(db, ctx->range);
    773 		if (rc != SEPOL_OK) {
    774 			goto exit;
    775 		}
    776 	}
    777 
    778 	for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) {
    779 		struct cil_sens *sens = curr->data;
    780 
    781 		if (found == CIL_FALSE) {
    782 			if (sens == user_low->sens) {
    783 				found = CIL_TRUE;
    784 			} else if (sens == ctx_low->sens) {
    785 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
    786 					ctx->range_str, ctx->user_str);
    787 				rc = SEPOL_ERR;
    788 				goto exit;
    789 			}
    790 		}
    791 
    792 		if (found == CIL_TRUE) {
    793 			if (sens == ctx_high->sens) {
    794 				break;
    795 			} else if (sens == user_high->sens) {
    796 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
    797 					ctx->range_str, ctx->user_str);
    798 				rc = SEPOL_ERR;
    799 				goto exit;
    800 			}
    801 		}
    802 	}
    803 
    804 	return SEPOL_OK;
    805 exit:
    806 	cil_log(CIL_ERR, "Invalid context\n");
    807 	return rc;
    808 }
    809 
    810 int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node)
    811 {
    812 	int rc = SEPOL_ERR;
    813 	struct cil_context *ctx = node->data;
    814 
    815 	rc = __cil_verify_context(db, ctx);
    816 	if (rc != SEPOL_OK) {
    817 		goto exit;
    818 	}
    819 
    820 	return SEPOL_OK;
    821 exit:
    822 	cil_tree_log(node, CIL_ERR, "Invalid named context");
    823 	return rc;
    824 }
    825 
    826 int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
    827 {
    828 
    829 	int rc = SEPOL_ERR;
    830 	struct cil_type_rule *typerule = NULL;
    831 	struct cil_roletransition *roletrans = NULL;
    832 	struct cil_complex_symtab_key ckey;
    833 
    834 	switch (node->flavor) {
    835 	case CIL_ROLETRANSITION: {
    836 		roletrans = node->data;
    837 		ckey.key1 = (intptr_t)roletrans->src;
    838 		ckey.key2 = (intptr_t)roletrans->tgt;
    839 		ckey.key3 = (intptr_t)roletrans->obj;
    840 		ckey.key4 = CIL_ROLETRANSITION;
    841 		break;
    842 	}
    843 	case CIL_TYPE_RULE: {
    844 		typerule = node->data;
    845 		ckey.key1 = (intptr_t)typerule->src;
    846 		ckey.key2 = (intptr_t)typerule->tgt;
    847 		ckey.key3 = (intptr_t)typerule->obj;
    848 		ckey.key4 = (intptr_t)typerule->rule_kind;
    849 		break;
    850 	}
    851 	default:
    852 		break;
    853 	}
    854 
    855 
    856 	rc = cil_complex_symtab_insert(symtab, &ckey, NULL);
    857 	if (rc == SEPOL_EEXIST) {
    858 		struct cil_complex_symtab_datum *datum = NULL;
    859 		cil_complex_symtab_search(symtab, &ckey, &datum);
    860 		if (datum == NULL) {
    861 			cil_tree_log(node, CIL_ERR, "Duplicate rule defined");
    862 			rc = SEPOL_ERR;
    863 			goto exit;
    864 		}
    865 	}
    866 
    867 	return SEPOL_OK;
    868 exit:
    869 	cil_tree_log(node, CIL_ERR, "Invalid rule");
    870 	return rc;
    871 }
    872 
    873 int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
    874 {
    875 	int rc = SEPOL_ERR;
    876 	struct cil_tree_node *rule_node = node;
    877 	struct cil_booleanif *bif = node->parent->parent->data;
    878 
    879 	switch (rule_node->flavor) {
    880 	case CIL_AVRULE: {
    881 		struct cil_avrule *avrule = NULL;
    882 		avrule = rule_node->data;
    883 		if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) {
    884 			if (bif->preserved_tunable) {
    885 				cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)");
    886 			} else {
    887 				cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block");
    888 			}
    889 			rc = SEPOL_ERR;
    890 			goto exit;
    891 		}
    892 		break;
    893 	}
    894 	case CIL_TYPE_RULE: /*
    895 	struct cil_type_rule *typerule = NULL;
    896 	struct cil_tree_node *temp_node = NULL;
    897 	struct cil_complex_symtab *symtab = extra_args;
    898 	struct cil_complex_symtab_key ckey;
    899 	struct cil_complex_symtab_datum datum;
    900 		typerule = rule_node->data;
    901 
    902 		ckey.key1 = (intptr_t)typerule->src;
    903 		ckey.key2 = (intptr_t)typerule->tgt;
    904 		ckey.key3 = (intptr_t)typerule->obj;
    905 		ckey.key4 = (intptr_t)typerule->rule_kind;
    906 
    907 		datum.data = node;
    908 
    909 		rc = cil_complex_symtab_insert(symtab, &ckey, &datum);
    910 		if (rc != SEPOL_OK) {
    911 			goto exit;
    912 		}
    913 
    914 		for (temp_node = rule_node->next;
    915 			temp_node != NULL;
    916 			temp_node = temp_node->next) {
    917 
    918 			if (temp_node->flavor == CIL_TYPE_RULE) {
    919 				typerule = temp_node->data;
    920 				if ((intptr_t)typerule->src == ckey.key1 &&
    921 					(intptr_t)typerule->tgt == ckey.key2 &&
    922 					(intptr_t)typerule->obj == ckey.key3 &&
    923 					(intptr_t)typerule->rule_kind == ckey.key4) {
    924 					cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line);
    925 					rc = SEPOL_ERR;
    926 					goto exit;
    927 				}
    928 			}
    929 		}
    930 		break;*/
    931 
    932 		//TODO Fix duplicate type_rule detection
    933 		break;
    934 	case CIL_CALL:
    935 		//Fall through to check content of call
    936 		break;
    937 	case CIL_TUNABLEIF:
    938 		//Fall through
    939 		break;
    940 	case CIL_NAMETYPETRANSITION:
    941 		/* While type transitions with file component are not allowed in
    942 		   booleanif statements if they don't have "*" as the file. We
    943 		   can't check that here. Or at least we won't right now. */
    944 		break;
    945 	default: {
    946 		const char * flavor = cil_node_to_string(node);
    947 		if (bif->preserved_tunable) {
    948 			cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor);
    949 		} else {
    950 			cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor);
    951 		}
    952 		goto exit;
    953 	}
    954 	}
    955 
    956 	rc = SEPOL_OK;
    957 exit:
    958 	return rc;
    959 }
    960 
    961 int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
    962 {
    963 	int rc = SEPOL_ERR;
    964 	struct cil_booleanif *bif = (struct cil_booleanif*)node->data;
    965 	struct cil_tree_node *cond_block = node->cl_head;
    966 
    967 	while (cond_block != NULL) {
    968 		rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab);
    969 		if (rc != SEPOL_OK) {
    970 			goto exit;
    971 		}
    972 		cond_block = cond_block->next;
    973 	}
    974 
    975 	return SEPOL_OK;
    976 exit:
    977 	if (bif->preserved_tunable) {
    978 		cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)");
    979 	} else {
    980 		cil_tree_log(node, CIL_ERR, "Invalid booleanif");
    981 	}
    982 	return rc;
    983 }
    984 
    985 int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node)
    986 {
    987 	int rc = SEPOL_ERR;
    988 	struct cil_netifcon *netif = node->data;
    989 	struct cil_context *if_ctx = netif->if_context;
    990 	struct cil_context *pkt_ctx = netif->packet_context;
    991 
    992 	/* Verify only when anonymous */
    993 	if (if_ctx->datum.name == NULL) {
    994 		rc = __cil_verify_context(db, if_ctx);
    995 		if (rc != SEPOL_OK) {
    996 			goto exit;
    997 		}
    998 	}
    999 
   1000 	/* Verify only when anonymous */
   1001 	if (pkt_ctx->datum.name == NULL) {
   1002 		rc = __cil_verify_context(db, pkt_ctx);
   1003 		if (rc != SEPOL_OK) {
   1004 			goto exit;
   1005 		}
   1006 	}
   1007 
   1008 	return SEPOL_OK;
   1009 
   1010 exit:
   1011 	cil_tree_log(node, CIL_ERR, "Invalid netifcon");
   1012 	return rc;
   1013 }
   1014 
   1015 int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node)
   1016 {
   1017 	int rc = SEPOL_ERR;
   1018 	struct cil_ibendportcon *ib_end_port = node->data;
   1019 	struct cil_context *ctx = ib_end_port->context;
   1020 
   1021 	/* Verify only when anonymous */
   1022 	if (!ctx->datum.name) {
   1023 		rc = __cil_verify_context(db, ctx);
   1024 		if (rc != SEPOL_OK)
   1025 			goto exit;
   1026 	}
   1027 
   1028 	return SEPOL_OK;
   1029 
   1030 exit:
   1031 	cil_tree_log(node, CIL_ERR, "Invalid ibendportcon");
   1032 	return rc;
   1033 }
   1034 
   1035 int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node)
   1036 {
   1037 	int rc = SEPOL_ERR;
   1038 	struct cil_genfscon *genfs = node->data;
   1039 	struct cil_context *ctx = genfs->context;
   1040 
   1041 	/* Verify only when anonymous */
   1042 	if (ctx->datum.name == NULL) {
   1043 		rc = __cil_verify_context(db, ctx);
   1044 		if (rc != SEPOL_OK) {
   1045 			goto exit;
   1046 		}
   1047 	}
   1048 
   1049 	return SEPOL_OK;
   1050 
   1051 exit:
   1052 	cil_tree_log(node, CIL_ERR, "Invalid genfscon");
   1053 	return rc;
   1054 }
   1055 
   1056 int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node)
   1057 {
   1058 	int rc = SEPOL_ERR;
   1059 	struct cil_filecon *file = node->data;
   1060 	struct cil_context *ctx = file->context;
   1061 
   1062 	if (ctx == NULL) {
   1063 		rc = SEPOL_OK;
   1064 		goto exit;
   1065 	}
   1066 
   1067 	/* Verify only when anonymous */
   1068 	if (ctx->datum.name == NULL) {
   1069 		rc = __cil_verify_context(db, ctx);
   1070 		if (rc != SEPOL_OK) {
   1071 			cil_tree_log(node, CIL_ERR, "Invalid filecon");
   1072 			goto exit;
   1073 		}
   1074 	}
   1075 
   1076 	return SEPOL_OK;
   1077 
   1078 exit:
   1079 	return rc;
   1080 }
   1081 
   1082 int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node)
   1083 {
   1084 	int rc = SEPOL_ERR;
   1085 	struct cil_nodecon *nodecon = node->data;
   1086 	struct cil_context *ctx = nodecon->context;
   1087 
   1088 	/* Verify only when anonymous */
   1089 	if (ctx->datum.name == NULL) {
   1090 		rc = __cil_verify_context(db, ctx);
   1091 		if (rc != SEPOL_OK) {
   1092 			goto exit;
   1093 		}
   1094 	}
   1095 
   1096 	return SEPOL_OK;
   1097 
   1098 exit:
   1099 	cil_tree_log(node, CIL_ERR, "Invalid nodecon");
   1100 	return rc;
   1101 }
   1102 
   1103 int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node)
   1104 {
   1105 	int rc = SEPOL_ERR;
   1106 	struct cil_ibpkeycon *pkey = node->data;
   1107 	struct cil_context *ctx = pkey->context;
   1108 
   1109 	/* Verify only when anonymous */
   1110 	if (!ctx->datum.name) {
   1111 		rc = __cil_verify_context(db, ctx);
   1112 		if (rc != SEPOL_OK)
   1113 			goto exit;
   1114 	}
   1115 
   1116 	return SEPOL_OK;
   1117 
   1118 exit:
   1119 	cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon");
   1120 	return rc;
   1121 }
   1122 
   1123 int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node)
   1124 {
   1125 	int rc = SEPOL_ERR;
   1126 	struct cil_portcon *port = node->data;
   1127 	struct cil_context *ctx = port->context;
   1128 
   1129 	/* Verify only when anonymous */
   1130 	if (ctx->datum.name == NULL) {
   1131 		rc = __cil_verify_context(db, ctx);
   1132 		if (rc != SEPOL_OK) {
   1133 			goto exit;
   1134 		}
   1135 	}
   1136 
   1137 	return SEPOL_OK;
   1138 
   1139 exit:
   1140 	cil_tree_log(node, CIL_ERR, "Invalid portcon");
   1141 	return rc;
   1142 }
   1143 
   1144 int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node)
   1145 {
   1146 	int rc = SEPOL_ERR;
   1147 	struct cil_pirqcon *pirq = node->data;
   1148 	struct cil_context *ctx = pirq->context;
   1149 
   1150 	/* Verify only when anonymous */
   1151 	if (ctx->datum.name == NULL) {
   1152 		rc = __cil_verify_context(db, ctx);
   1153 		if (rc != SEPOL_OK) {
   1154 			goto exit;
   1155 		}
   1156 	}
   1157 
   1158 	return SEPOL_OK;
   1159 
   1160 exit:
   1161 	cil_tree_log(node, CIL_ERR, "Invalid pirqcon");
   1162 	return rc;
   1163 }
   1164 
   1165 int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node)
   1166 {
   1167 	int rc = SEPOL_ERR;
   1168 	struct cil_iomemcon *iomem = node->data;
   1169 	struct cil_context *ctx = iomem->context;
   1170 
   1171 	/* Verify only when anonymous */
   1172 	if (ctx->datum.name == NULL) {
   1173 		rc = __cil_verify_context(db, ctx);
   1174 		if (rc != SEPOL_OK) {
   1175 			goto exit;
   1176 		}
   1177 	}
   1178 
   1179 	return SEPOL_OK;
   1180 
   1181 exit:
   1182 	cil_tree_log(node, CIL_ERR, "Invalid iomemcon");
   1183 	return rc;
   1184 }
   1185 
   1186 int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node)
   1187 {
   1188 	int rc = SEPOL_ERR;
   1189 	struct cil_ioportcon *ioport = node->data;
   1190 	struct cil_context *ctx = ioport->context;
   1191 
   1192 	/* Verify only when anonymous */
   1193 	if (ctx->datum.name == NULL) {
   1194 		rc = __cil_verify_context(db, ctx);
   1195 		if (rc != SEPOL_OK) {
   1196 			goto exit;
   1197 		}
   1198 	}
   1199 
   1200 	return SEPOL_OK;
   1201 
   1202 exit:
   1203 	cil_tree_log(node, CIL_ERR, "Invalid ioportcon");
   1204 	return rc;
   1205 }
   1206 
   1207 int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node)
   1208 {
   1209 	int rc = SEPOL_ERR;
   1210 	struct cil_pcidevicecon *pcidev = node->data;
   1211 	struct cil_context *ctx = pcidev->context;
   1212 
   1213 	/* Verify only when anonymous */
   1214 	if (ctx->datum.name == NULL) {
   1215 		rc = __cil_verify_context(db, ctx);
   1216 		if (rc != SEPOL_OK) {
   1217 			goto exit;
   1218 		}
   1219 	}
   1220 
   1221 	return SEPOL_OK;
   1222 
   1223 exit:
   1224 	cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon");
   1225 	return rc;
   1226 }
   1227 
   1228 int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node)
   1229 {
   1230 	int rc = SEPOL_ERR;
   1231 	struct cil_devicetreecon *dt = node->data;
   1232 	struct cil_context *ctx = dt->context;
   1233 
   1234 	/* Verify only when anonymous */
   1235 	if (ctx->datum.name == NULL) {
   1236 		rc = __cil_verify_context(db, ctx);
   1237 		if (rc != SEPOL_OK) {
   1238 			goto exit;
   1239 		}
   1240 	}
   1241 
   1242 	return SEPOL_OK;
   1243 
   1244 exit:
   1245 	cil_tree_log(node, CIL_ERR, "Invalid devicetreecon");
   1246 	return rc;
   1247 }
   1248 
   1249 int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node)
   1250 {
   1251 	int rc = SEPOL_ERR;
   1252 	struct cil_fsuse *fsuse = node->data;
   1253 	struct cil_context *ctx = fsuse->context;
   1254 
   1255 	/* Verify only when anonymous */
   1256 	if (ctx->datum.name == NULL) {
   1257 		rc = __cil_verify_context(db, ctx);
   1258 		if (rc != SEPOL_OK) {
   1259 			goto exit;
   1260 		}
   1261 	}
   1262 
   1263 	return SEPOL_OK;
   1264 
   1265 exit:
   1266 	cil_tree_log(node, CIL_ERR, "Invalid fsuse");
   1267 	return rc;
   1268 }
   1269 
   1270 int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node *node)
   1271 {
   1272 	int rc;
   1273 	struct cil_list *classes = NULL;
   1274 	struct cil_list_item *item;
   1275 	struct cil_class *class;
   1276 	struct cil_symtab_datum *perm_datum;
   1277 	char *kind_str;
   1278 
   1279 	switch (permx->kind) {
   1280 		case CIL_PERMX_KIND_IOCTL:
   1281 			kind_str = CIL_KEY_IOCTL;
   1282 			break;
   1283 		default:
   1284 			cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind);
   1285 			rc = SEPOL_ERR;
   1286 			goto exit;
   1287 	}
   1288 
   1289 	classes = cil_expand_class(permx->obj);
   1290 
   1291 	cil_list_for_each(item, classes) {
   1292 		class = item->data;
   1293 		rc = cil_symtab_get_datum(&class->perms, kind_str, &perm_datum);
   1294 		if (rc == SEPOL_ENOENT) {
   1295 			if (class->common != NULL) {
   1296 				rc = cil_symtab_get_datum(&class->common->perms, kind_str, &perm_datum);
   1297 			}
   1298 
   1299 			if (rc == SEPOL_ENOENT) {
   1300 				cil_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", kind_str, class->datum.name);
   1301 				rc = SEPOL_ERR;
   1302 				goto exit;
   1303 			}
   1304 		}
   1305 	}
   1306 
   1307 	rc = SEPOL_OK;
   1308 
   1309 exit:
   1310 	if (classes != NULL) {
   1311 		cil_list_destroy(&classes, CIL_FALSE);
   1312 	}
   1313 
   1314 	return rc;
   1315 }
   1316 
   1317 int __cil_verify_avrulex(struct cil_tree_node *node)
   1318 {
   1319 	struct cil_avrule *avrulex = node->data;
   1320 	return __cil_verify_permissionx(avrulex->perms.x.permx, node);
   1321 }
   1322 
   1323 int __cil_verify_class(struct cil_tree_node *node)
   1324 {
   1325 	int rc = SEPOL_ERR;
   1326 	struct cil_class *class = node->data;
   1327 
   1328 	if (class->common != NULL) {
   1329 		struct cil_class *common = class->common;
   1330 		struct cil_tree_node *common_node = common->datum.nodes->head->data;
   1331 		struct cil_tree_node *curr_com_perm = NULL;
   1332 
   1333 		for (curr_com_perm = common_node->cl_head;
   1334 			curr_com_perm != NULL;
   1335 			curr_com_perm = curr_com_perm->next) {
   1336 			struct cil_perm *com_perm = curr_com_perm->data;
   1337 			struct cil_tree_node *curr_class_perm = NULL;
   1338 
   1339 			for (curr_class_perm = node->cl_head;
   1340 				curr_class_perm != NULL;
   1341 				curr_class_perm = curr_class_perm->next) {
   1342 				struct cil_perm *class_perm = curr_class_perm->data;
   1343 
   1344 				if (com_perm->datum.name == class_perm->datum.name) {
   1345 					cil_log(CIL_ERR, "Duplicate permissions between %s common and class declarations\n", class_perm->datum.name);
   1346 					goto exit;
   1347 				}
   1348 			}
   1349 		}
   1350 	}
   1351 
   1352 	return SEPOL_OK;
   1353 
   1354 exit:
   1355 	cil_tree_log(node, CIL_ERR, "Invalid class");
   1356 	return rc;
   1357 }
   1358 
   1359 int __cil_verify_policycap(struct cil_tree_node *node)
   1360 {
   1361 	int rc;
   1362 	struct cil_policycap *polcap = node->data;
   1363 
   1364 	rc = sepol_polcap_getnum((const char*)polcap->datum.name);
   1365 	if (rc == SEPOL_ERR) {
   1366 		goto exit;
   1367 	}
   1368 
   1369 	return SEPOL_OK;
   1370 
   1371 exit:
   1372 	cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name);
   1373 	return rc;
   1374 }
   1375 
   1376 int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   1377 {
   1378 	int rc = SEPOL_ERR;
   1379 	int *avrule_cnt = 0;
   1380 	int *handleunknown;
   1381 	int *mls;
   1382 	int *nseuserdflt = 0;
   1383 	int *pass = 0;
   1384 	struct cil_args_verify *args = extra_args;
   1385 	struct cil_complex_symtab *csymtab = NULL;
   1386 	struct cil_db *db = NULL;
   1387 
   1388 	if (node == NULL || extra_args == NULL) {
   1389 		goto exit;
   1390 	}
   1391 
   1392 	db = args->db;
   1393 	avrule_cnt = args->avrule_cnt;
   1394 	handleunknown = args->handleunknown;
   1395 	mls = args->mls;
   1396 	nseuserdflt = args->nseuserdflt;
   1397 	csymtab = args->csymtab;
   1398 	pass = args->pass;
   1399 
   1400 	if (node->flavor == CIL_MACRO) {
   1401 		*finished = CIL_TREE_SKIP_HEAD;
   1402 		rc = SEPOL_OK;
   1403 		goto exit;
   1404 	} else if (node->flavor == CIL_BLOCK) {
   1405 		struct cil_block *blk = node->data;
   1406 		if (blk->is_abstract == CIL_TRUE) {
   1407 			*finished = CIL_TREE_SKIP_HEAD;
   1408 		}
   1409 		rc = SEPOL_OK;
   1410 		goto exit;
   1411 	}
   1412 
   1413 	switch (*pass) {
   1414 	case 0: {
   1415 		switch (node->flavor) {
   1416 		case CIL_USER:
   1417 			rc = __cil_verify_user_post_eval(db, node);
   1418 			break;
   1419 		case CIL_SELINUXUSERDEFAULT:
   1420 			(*nseuserdflt)++;
   1421 			rc = SEPOL_OK;
   1422 			break;
   1423 		case CIL_ROLE:
   1424 			rc = __cil_verify_role(node);
   1425 			break;
   1426 		case CIL_TYPE:
   1427 			rc = __cil_verify_type(node);
   1428 			break;
   1429 		case CIL_AVRULE:
   1430 			(*avrule_cnt)++;
   1431 			rc = SEPOL_OK;
   1432 			break;
   1433 		case CIL_HANDLEUNKNOWN:
   1434 			if (*handleunknown != -1) {
   1435 				cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n");
   1436 				rc = SEPOL_ERR;
   1437 			} else {
   1438 				*handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown;
   1439 				rc = SEPOL_OK;
   1440 			}
   1441 			break;
   1442 		case CIL_MLS:
   1443 			if (*mls != -1) {
   1444 				cil_log(CIL_ERR, "Policy can not have more than one mls\n");
   1445 				rc = SEPOL_ERR;
   1446 			} else {
   1447 				*mls = ((struct cil_mls*)node->data)->value;
   1448 				rc = SEPOL_OK;
   1449 			}
   1450 			break;
   1451 		case CIL_ROLETRANSITION:
   1452 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
   1453 			//rc = __cil_verify_rule(node, csymtab);
   1454 			break;
   1455 		case CIL_TYPE_RULE:
   1456 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
   1457 			//rc = __cil_verify_rule(node, csymtab);
   1458 			break;
   1459 		case CIL_BOOLEANIF:
   1460 			rc = __cil_verify_booleanif(node, csymtab);
   1461 			*finished = CIL_TREE_SKIP_HEAD;
   1462 			break;
   1463 		case CIL_LEVELRANGE:
   1464 			rc = __cil_verify_named_levelrange(db, node);
   1465 			break;
   1466 		case CIL_CLASS:
   1467 			rc = __cil_verify_class(node);
   1468 			break;
   1469 		case CIL_POLICYCAP:
   1470 			rc = __cil_verify_policycap(node);
   1471 			break;
   1472 		default:
   1473 			rc = SEPOL_OK;
   1474 			break;
   1475 		}
   1476 		break;
   1477 	}
   1478 	case 1:	{
   1479 		switch (node->flavor) {
   1480 		case CIL_CONTEXT:
   1481 			rc = __cil_verify_named_context(db, node);
   1482 			break;
   1483 		case CIL_NETIFCON:
   1484 			rc = __cil_verify_netifcon(db, node);
   1485 			break;
   1486 		case CIL_GENFSCON:
   1487 			rc = __cil_verify_genfscon(db, node);
   1488 			break;
   1489 		case CIL_FILECON:
   1490 			rc = __cil_verify_filecon(db, node);
   1491 			break;
   1492 		case CIL_NODECON:
   1493 			rc = __cil_verify_nodecon(db, node);
   1494 			break;
   1495 		case CIL_IBPKEYCON:
   1496 			rc = __cil_verify_ibpkeycon(db, node);
   1497 			break;
   1498 		case CIL_IBENDPORTCON:
   1499 			rc = __cil_verify_ibendportcon(db, node);
   1500 			break;
   1501 		case CIL_PORTCON:
   1502 			rc = __cil_verify_portcon(db, node);
   1503 			break;
   1504 		case CIL_PIRQCON:
   1505 			rc = __cil_verify_pirqcon(db, node);
   1506 			break;
   1507 		case CIL_IOMEMCON:
   1508 			rc = __cil_verify_iomemcon(db, node);
   1509 			break;
   1510 		case CIL_IOPORTCON:
   1511 			rc = __cil_verify_ioportcon(db, node);
   1512 			break;
   1513 		case CIL_PCIDEVICECON:
   1514 			rc = __cil_verify_pcidevicecon(db, node);
   1515 			break;
   1516 		case CIL_DEVICETREECON:
   1517 			rc = __cil_verify_devicetreecon(db, node);
   1518 			break;
   1519 		case CIL_FSUSE:
   1520 			rc = __cil_verify_fsuse(db, node);
   1521 			break;
   1522 		case CIL_AVRULEX:
   1523 			rc = __cil_verify_avrulex(node);
   1524 			break;
   1525 		case CIL_PERMISSIONX:
   1526 			rc = __cil_verify_permissionx(node->data, node);
   1527 			break;
   1528 		case CIL_RANGETRANSITION:
   1529 			rc = SEPOL_OK;
   1530 			break;
   1531 		default:
   1532 			rc = SEPOL_OK;
   1533 			break;
   1534 		}
   1535 		break;
   1536 	}
   1537 	default:
   1538 		rc = SEPOL_ERR;
   1539 	}
   1540 
   1541 exit:
   1542 	return rc;
   1543 }
   1544 
   1545 static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig)
   1546 {
   1547 	int rc = SEPOL_ERR;
   1548 	struct cil_list_item *curr;
   1549 
   1550 	cil_list_for_each(curr, classperms) {
   1551 		if (curr->flavor == CIL_CLASSPERMS) {
   1552 			struct cil_classperms *cp = curr->data;
   1553 			if (FLAVOR(cp->class) == CIL_CLASS) {
   1554 				return SEPOL_OK;
   1555 			} else { /* MAP */
   1556 				struct cil_list_item *i = NULL;
   1557 				cil_list_for_each(i, cp->perms) {
   1558 					struct cil_perm *cmp = i->data;
   1559 					if (&cmp->datum == orig) {
   1560 						rc = SEPOL_ERR;
   1561 						goto exit;
   1562 					}
   1563 					rc = __cil_verify_classperms(cmp->classperms, orig);
   1564 					if (rc != SEPOL_OK) {
   1565 						goto exit;
   1566 					}
   1567 				}
   1568 			}
   1569 		} else { /* SET */
   1570 			struct cil_classperms_set *cp_set = curr->data;
   1571 			struct cil_classpermission *cp = cp_set->set;
   1572 			if (&cp->datum == orig) {
   1573 				rc = SEPOL_ERR;
   1574 				goto exit;
   1575 			}
   1576 			rc = __cil_verify_classperms(cp->classperms, orig);
   1577 			if (rc != SEPOL_OK) {
   1578 				goto exit;
   1579 			}
   1580 		}
   1581 	}
   1582 
   1583 	return SEPOL_OK;
   1584 
   1585 exit:
   1586 	return rc;
   1587 }
   1588 
   1589 static int __cil_verify_classpermission(struct cil_tree_node *node)
   1590 {
   1591 	int rc = SEPOL_ERR;
   1592 	struct cil_classpermission *cp = node->data;
   1593 
   1594 	if (cp->classperms == NULL) {
   1595 		cil_tree_log(node, CIL_ERR, "Classpermission %s does not have a classpermissionset", cp->datum.name);
   1596 		rc = SEPOL_ERR;
   1597 		goto exit;
   1598 	}
   1599 
   1600 	rc = __cil_verify_classperms(cp->classperms, &cp->datum);
   1601 	if (rc != SEPOL_OK) {
   1602 		cil_tree_log(node, CIL_ERR, "Found circular class permissions involving the set %s",cp->datum.name);
   1603 		goto exit;
   1604 	}
   1605 
   1606 	rc = SEPOL_OK;
   1607 
   1608 exit:
   1609 	return rc;
   1610 }
   1611 
   1612 struct cil_verify_map_args {
   1613 	struct cil_class *class;
   1614 	struct cil_tree_node *node;
   1615 	int rc;
   1616 };
   1617 
   1618 static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
   1619 {
   1620 	int rc = SEPOL_ERR;
   1621 	struct cil_verify_map_args *map_args = args;
   1622 	struct cil_perm *cmp = (struct cil_perm *)d;
   1623 
   1624 	if (cmp->classperms == NULL) {
   1625 		cil_tree_log(map_args->node, CIL_ERR, "Map class %s does not have a classmapping for %s", map_args->class->datum.name, cmp->datum.name);
   1626 		map_args->rc = SEPOL_ERR;
   1627 		goto exit;
   1628 	}
   1629 
   1630 	rc = __cil_verify_classperms(cmp->classperms, &cmp->datum);
   1631 	if (rc != SEPOL_OK) {
   1632 		cil_tree_log(map_args->node, CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", map_args->class->datum.name, cmp->datum.name);
   1633 		map_args->rc = SEPOL_ERR;
   1634 		goto exit;
   1635 	}
   1636 
   1637 exit:
   1638 	return SEPOL_OK;
   1639 }
   1640 
   1641 static int __cil_verify_map_class(struct cil_tree_node *node)
   1642 {
   1643 	struct cil_class *mc = node->data;
   1644 	struct cil_verify_map_args map_args;
   1645 
   1646 	map_args.class = mc;
   1647 	map_args.node = node;
   1648 	map_args.rc = SEPOL_OK;
   1649 
   1650 	cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args);
   1651 
   1652 	if (map_args.rc != SEPOL_OK) {
   1653 		return SEPOL_ERR;
   1654 	}
   1655 
   1656 	return SEPOL_OK;
   1657 }
   1658 
   1659 int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
   1660 {
   1661 	int rc = SEPOL_ERR;
   1662 
   1663 	if (node->flavor == CIL_MACRO) {
   1664 		*finished = CIL_TREE_SKIP_HEAD;
   1665 		rc = SEPOL_OK;
   1666 		goto exit;
   1667 	} else if (node->flavor == CIL_BLOCK) {
   1668 		struct cil_block *blk = node->data;
   1669 		if (blk->is_abstract == CIL_TRUE) {
   1670 			*finished = CIL_TREE_SKIP_HEAD;
   1671 		}
   1672 		rc = SEPOL_OK;
   1673 		goto exit;
   1674 	}
   1675 
   1676 	switch (node->flavor) {
   1677 	case CIL_USER:
   1678 		rc = __cil_verify_user_pre_eval(node);
   1679 		if (rc != SEPOL_OK) {
   1680 			goto exit;
   1681 		}
   1682 		break;
   1683 	case CIL_MAP_CLASS:
   1684 		rc = __cil_verify_map_class(node);
   1685 		break;
   1686 	case CIL_CLASSPERMISSION:
   1687 		rc = __cil_verify_classpermission(node);
   1688 		break;
   1689 	default:
   1690 		rc = SEPOL_OK;
   1691 		break;
   1692 	}
   1693 
   1694 exit:
   1695 	return rc;
   1696 }
   1697