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