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