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 
     34 #include <sepol/policydb/conditional.h>
     35 
     36 #include "cil_internal.h"
     37 #include "cil_flavor.h"
     38 #include "cil_log.h"
     39 #include "cil_mem.h"
     40 #include "cil_tree.h"
     41 #include "cil_list.h"
     42 #include "cil_build_ast.h"
     43 #include "cil_resolve_ast.h"
     44 #include "cil_reset_ast.h"
     45 #include "cil_copy_ast.h"
     46 #include "cil_verify.h"
     47 #include "cil_strpool.h"
     48 #include "cil_symtab.h"
     49 
     50 struct cil_args_resolve {
     51 	struct cil_db *db;
     52 	enum cil_pass pass;
     53 	uint32_t *changed;
     54 	struct cil_tree_node *callstack;
     55 	struct cil_tree_node *optstack;
     56 	struct cil_tree_node *boolif;
     57 	struct cil_tree_node *macro;
     58 	struct cil_list *sidorder_lists;
     59 	struct cil_list *classorder_lists;
     60 	struct cil_list *catorder_lists;
     61 	struct cil_list *sensitivityorder_lists;
     62 	struct cil_list *in_list;
     63 };
     64 
     65 static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node)
     66 {
     67 	/* Currently only used for typetransition file names.
     68 	   But could be used for any string that is passed as a parameter.
     69 	*/
     70 	struct cil_tree_node *parent = ast_node->parent;
     71 	struct cil_macro *macro = NULL;
     72 	struct cil_name *name;
     73 	symtab_t *symtab;
     74 	enum cil_sym_index sym_index;
     75 	struct cil_symtab_datum *datum = NULL;
     76 
     77 	cil_flavor_to_symtab_index(CIL_NAME, &sym_index);
     78 	symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
     79 
     80 	cil_symtab_get_datum(symtab, key, &datum);
     81 	if (datum != NULL) {
     82 		return (struct cil_name *)datum;
     83 	}
     84 
     85 	if (parent->flavor == CIL_CALL) {
     86 		struct cil_call *call = parent->data;
     87 		macro = call->macro;
     88 	} else if (parent->flavor == CIL_MACRO) {
     89 		macro = parent->data;
     90 	}
     91 	if (macro != NULL) {
     92 		struct cil_list_item *item;
     93 		cil_list_for_each(item, macro->params) {
     94 			if (((struct cil_param*)item->data)->str == key) {
     95 				return NULL;
     96 			}
     97 		}
     98 	}
     99 
    100 	cil_name_init(&name);
    101 	cil_symtab_insert(symtab, key, (struct cil_symtab_datum *)name, ast_node);
    102 	cil_list_append(db->names, CIL_NAME, name);
    103 
    104 	return name;
    105 }
    106 
    107 static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab, struct cil_list *perm_strs, struct cil_list **perm_datums)
    108 {
    109 	int rc = SEPOL_ERR;
    110 	struct cil_list_item *curr;
    111 
    112 	cil_list_init(perm_datums, perm_strs->flavor);
    113 
    114 	cil_list_for_each(curr, perm_strs) {
    115 		if (curr->flavor == CIL_LIST) {
    116 			struct cil_list *sub_list;
    117 			rc = __cil_resolve_perms(class_symtab, common_symtab, curr->data, &sub_list);
    118 			if (rc != SEPOL_OK) {
    119 				cil_log(CIL_ERR, "Failed to resolve permission list\n");
    120 				goto exit;
    121 			}
    122 			cil_list_append(*perm_datums, CIL_LIST, sub_list);
    123 		} else if (curr->flavor == CIL_STRING) {
    124 			struct cil_symtab_datum *perm_datum = NULL;
    125 			rc = cil_symtab_get_datum(class_symtab, curr->data, &perm_datum);
    126 			if (rc == SEPOL_ENOENT) {
    127 				if (common_symtab) {
    128 					rc = cil_symtab_get_datum(common_symtab, curr->data, &perm_datum);
    129 				}
    130 			}
    131 			if (rc != SEPOL_OK) {
    132 				cil_log(CIL_ERR, "Failed to resolve permission %s\n", (char*)curr->data);
    133 				goto exit;
    134 			}
    135 			cil_list_append(*perm_datums, CIL_DATUM, perm_datum);
    136 		} else {
    137 			cil_list_append(*perm_datums, curr->flavor, curr->data);
    138 		}
    139 	}
    140 
    141 	return SEPOL_OK;
    142 
    143 exit:
    144 	return rc;
    145 }
    146 
    147 int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, void *extra_args)
    148 {
    149 	int rc = SEPOL_ERR;
    150 	struct cil_symtab_datum *datum = NULL;
    151 	symtab_t *common_symtab = NULL;
    152 	struct cil_class *class;
    153 
    154 	rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum);
    155 	if (rc != SEPOL_OK) {
    156 		goto exit;
    157 	}
    158 
    159 	class = (struct cil_class *)datum;
    160 
    161 	if (class->common != NULL) {
    162 		common_symtab = &class->common->perms;
    163 	}
    164 
    165 	cp->class = class;
    166 
    167 	rc = __cil_resolve_perms(&class->perms, common_symtab, cp->perm_strs, &cp->perms);
    168 	if (rc != SEPOL_OK) {
    169 		goto exit;
    170 	}
    171 
    172 	return SEPOL_OK;
    173 
    174 exit:
    175 	return rc;
    176 }
    177 
    178 int cil_resolve_classperms_set(struct cil_tree_node *current, struct cil_classperms_set *cp_set, void *extra_args)
    179 {
    180 	int rc = SEPOL_ERR;
    181 	struct cil_symtab_datum *datum = NULL;
    182 
    183 	rc = cil_resolve_name(current, cp_set->set_str, CIL_SYM_CLASSPERMSETS, extra_args, &datum);
    184 	if (rc != SEPOL_OK) {
    185 		goto exit;
    186 	}
    187 	cp_set->set = (struct cil_classpermission*)datum;
    188 
    189 	/* This could be an anonymous classpermission */
    190 	if (datum->name == NULL) {
    191 		rc = cil_resolve_classperms_list(current, cp_set->set->classperms, extra_args);
    192 		if (rc != SEPOL_OK) {
    193 			goto exit;
    194 		}
    195 	}
    196 
    197 	return SEPOL_OK;
    198 
    199 exit:
    200 	return rc;
    201 }
    202 
    203 int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, void *extra_args)
    204 {
    205 	int rc = SEPOL_ERR;
    206 	struct cil_list_item *curr;
    207 
    208 	cil_list_for_each(curr, cp_list) {
    209 		if (curr->flavor == CIL_CLASSPERMS) {
    210 			rc = cil_resolve_classperms(current, curr->data, extra_args);
    211 			if (rc != SEPOL_OK) {
    212 				goto exit;
    213 			}
    214 		} else {
    215 			rc = cil_resolve_classperms_set(current, curr->data, extra_args);
    216 			if (rc != SEPOL_OK) {
    217 				goto exit;
    218 			}
    219 		}
    220 	}
    221 
    222 	return SEPOL_OK;
    223 
    224 exit:
    225 	return rc;
    226 }
    227 
    228 int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, void *extra_args)
    229 {
    230 	int rc = SEPOL_ERR;
    231 	struct cil_args_resolve *args = extra_args;
    232 	struct cil_list_item *curr;
    233 	struct cil_symtab_datum *datum;
    234 	struct cil_classpermission *cp;
    235 
    236 	rc = cil_resolve_name(current, cps->set_str, CIL_SYM_CLASSPERMSETS, args, &datum);
    237 	if (rc != SEPOL_OK) {
    238 		goto exit;
    239 	}
    240 
    241 	rc = cil_resolve_classperms_list(current, cps->classperms, extra_args);
    242 	if (rc != SEPOL_OK) {
    243 		goto exit;
    244 	}
    245 
    246 	cp = (struct cil_classpermission *)datum;
    247 
    248 	if (cp->classperms == NULL) {
    249 		cil_list_init(&cp->classperms, CIL_CLASSPERMS);
    250 	}
    251 
    252 	cil_list_for_each(curr, cps->classperms) {
    253 		cil_list_append(cp->classperms, curr->flavor, curr->data);
    254 	}
    255 
    256 	return SEPOL_OK;
    257 
    258 exit:
    259 	return rc;
    260 }
    261 
    262 int cil_type_used(struct cil_symtab_datum *datum)
    263 {
    264 	struct cil_typeattribute *attr = NULL;
    265 
    266 	if (FLAVOR(datum) == CIL_TYPEATTRIBUTE) {
    267 		attr = (struct cil_typeattribute*)datum;
    268 		attr->used = CIL_TRUE;
    269 	}
    270 
    271 	return 0;
    272 }
    273 
    274 int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args)
    275 {
    276 	struct cil_args_resolve *args = extra_args;
    277 	struct cil_db *db = NULL;
    278 
    279 	struct cil_avrule *rule = current->data;
    280 	struct cil_symtab_datum *src_datum = NULL;
    281 	struct cil_symtab_datum *tgt_datum = NULL;
    282 	int rc = SEPOL_ERR;
    283 
    284 	if (args != NULL) {
    285 		db = args->db;
    286 	}
    287 
    288 	rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, args, &src_datum);
    289 	if (rc != SEPOL_OK) {
    290 		goto exit;
    291 	}
    292 	rule->src = src_datum;
    293 	if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) {
    294 		cil_type_used(src_datum);
    295 	}
    296 
    297 	if (rule->tgt_str == CIL_KEY_SELF) {
    298 		rule->tgt = db->selftype;
    299 	} else {
    300 		rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum);
    301 		if (rc != SEPOL_OK) {
    302 			goto exit;
    303 		}
    304 		rule->tgt = tgt_datum;
    305 		if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) {
    306 			cil_type_used(tgt_datum);
    307 		}
    308 	}
    309 
    310 	rc = cil_resolve_classperms_list(current, rule->classperms, extra_args);
    311 	if (rc != SEPOL_OK) {
    312 		goto exit;
    313 	}
    314 
    315 	return SEPOL_OK;
    316 
    317 exit:
    318 	return rc;
    319 }
    320 
    321 int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args)
    322 {
    323 	struct cil_type_rule *rule = current->data;
    324 	struct cil_symtab_datum *src_datum = NULL;
    325 	struct cil_symtab_datum *tgt_datum = NULL;
    326 	struct cil_symtab_datum *obj_datum = NULL;
    327 	struct cil_symtab_datum *result_datum = NULL;
    328 	struct cil_tree_node *result_node = NULL;
    329 	int rc = SEPOL_ERR;
    330 
    331 	rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, extra_args, &src_datum);
    332 	if (rc != SEPOL_OK) {
    333 		goto exit;
    334 	}
    335 	rule->src = src_datum;
    336 	cil_type_used(src_datum);
    337 
    338 	rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum);
    339 	if (rc != SEPOL_OK) {
    340 		goto exit;
    341 	}
    342 	rule->tgt = tgt_datum;
    343 	cil_type_used(tgt_datum);
    344 
    345 	rc = cil_resolve_name(current, rule->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
    346 	if (rc != SEPOL_OK) {
    347 		goto exit;
    348 	}
    349 	rule->obj = (struct cil_class*)obj_datum;
    350 
    351 	rc = cil_resolve_name(current, rule->result_str, CIL_SYM_TYPES, extra_args, &result_datum);
    352 	if (rc != SEPOL_OK) {
    353 		goto exit;
    354 	}
    355 
    356 	result_node = result_datum->nodes->head->data;
    357 
    358 	if (result_node->flavor != CIL_TYPE) {
    359 		cil_log(CIL_ERR, "Type rule result must be a type [%d]\n",result_node->flavor);
    360 		rc = SEPOL_ERR;
    361 		goto exit;
    362 	}
    363 	rule->result = result_datum;
    364 
    365 	return SEPOL_OK;
    366 
    367 exit:
    368 	return rc;
    369 }
    370 
    371 int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args)
    372 {
    373 	struct cil_typeattributeset *attrtypes = current->data;
    374 	struct cil_symtab_datum *attr_datum = NULL;
    375 	struct cil_tree_node *attr_node = NULL;
    376 	struct cil_typeattribute *attr = NULL;
    377 	int rc = SEPOL_ERR;
    378 
    379 	rc = cil_resolve_name(current, attrtypes->attr_str, CIL_SYM_TYPES, extra_args, &attr_datum);
    380 	if (rc != SEPOL_OK) {
    381 		goto exit;
    382 	}
    383 
    384 	attr_node = attr_datum->nodes->head->data;
    385 
    386 	if (attr_node->flavor != CIL_TYPEATTRIBUTE) {
    387 		rc = SEPOL_ERR;
    388 		cil_log(CIL_ERR, "Attribute type not an attribute\n");
    389 		goto exit;
    390 	}
    391 
    392 	attr = (struct cil_typeattribute*)attr_datum;
    393 
    394 	rc = cil_resolve_expr(CIL_TYPEATTRIBUTESET, attrtypes->str_expr, &attrtypes->datum_expr, current, extra_args);
    395 	if (rc != SEPOL_OK) {
    396 		goto exit;
    397 	}
    398 
    399 	rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr);
    400 	if (rc != SEPOL_OK) {
    401 		goto exit;
    402 	}
    403 
    404 	if (attr->expr_list == NULL) {
    405 		cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE);
    406 	}
    407 
    408 	cil_list_append(attr->expr_list, CIL_LIST, attrtypes->datum_expr);
    409 
    410 	return SEPOL_OK;
    411 
    412 exit:
    413 	return rc;
    414 }
    415 
    416 int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor)
    417 {
    418 	int rc = SEPOL_ERR;
    419 	enum cil_sym_index sym_index;
    420 	struct cil_aliasactual *aliasactual = current->data;
    421 	struct cil_symtab_datum *alias_datum = NULL;
    422 	struct cil_symtab_datum *actual_datum = NULL;
    423 	struct cil_alias *alias;
    424 
    425 	rc = cil_flavor_to_symtab_index(flavor, &sym_index);
    426 	if (rc != SEPOL_OK) {
    427 		goto exit;
    428 	}
    429 	rc = cil_resolve_name(current, aliasactual->alias_str, sym_index, extra_args, &alias_datum);
    430 	if (rc != SEPOL_OK) {
    431 		goto exit;
    432 	}
    433 
    434 	rc = cil_resolve_name(current, aliasactual->actual_str, sym_index, extra_args, &actual_datum);
    435 	if (rc != SEPOL_OK) {
    436 		goto exit;
    437 	}
    438 
    439 	alias = (struct cil_alias *)alias_datum;
    440 
    441 	if (alias->actual != NULL) {
    442 		cil_log(CIL_ERR, "Alias cannot bind more than one value\n");
    443 		rc = SEPOL_ERR;
    444 		goto exit;
    445 	}
    446 
    447 	alias->actual = actual_datum;
    448 
    449 	return SEPOL_OK;
    450 
    451 exit:
    452 	return rc;
    453 }
    454 
    455 int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_flavor flavor)
    456 {
    457 	struct cil_alias *alias = current->data;
    458 	struct cil_alias *a1 = current->data;
    459 	struct cil_alias *a2 = current->data;
    460 	struct cil_tree_node *a1_node = NULL;
    461 	int steps = 0;
    462 	int limit = 2;
    463 
    464 	if (alias->actual == NULL) {
    465 		cil_log(CIL_ERR, "Alias declared but not used at line %d of %s\n",current->line, current->path);
    466 		return SEPOL_ERR;
    467 	}
    468 
    469 	a1_node = a1->datum.nodes->head->data;
    470 
    471 	while (flavor != a1_node->flavor) {
    472 		a1 = a1->actual;
    473 		a1_node = a1->datum.nodes->head->data;
    474 		steps += 1;
    475 
    476 		if (a1 == a2) {
    477 			cil_log(CIL_ERR, "Circular alias found: %s ", a1->datum.name);
    478 			a1 = a1->actual;
    479 			while (a1 != a2) {
    480 				cil_log(CIL_ERR, "%s ", a1->datum.name);
    481 				a1 = a1->actual;
    482 			}
    483 			cil_log(CIL_ERR,"\n");
    484 			return SEPOL_ERR;
    485 		}
    486 
    487 		if (steps == limit) {
    488 			steps = 0;
    489 			limit *= 2;
    490 			a2 = a1;
    491 		}
    492 	}
    493 
    494 	alias->actual = a1;
    495 
    496 	return SEPOL_OK;
    497 }
    498 
    499 int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args)
    500 {
    501 	struct cil_typepermissive *typeperm = current->data;
    502 	struct cil_symtab_datum *type_datum = NULL;
    503 	struct cil_tree_node *type_node = NULL;
    504 	int rc = SEPOL_ERR;
    505 
    506 	rc = cil_resolve_name(current, typeperm->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
    507 	if (rc != SEPOL_OK) {
    508 		goto exit;
    509 	}
    510 
    511 	type_node = type_datum->nodes->head->data;
    512 
    513 	if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) {
    514 		cil_log(CIL_ERR, "Typepermissive must be a type or type alias\n");
    515 		rc = SEPOL_ERR;
    516 		goto exit;
    517 	}
    518 
    519 	typeperm->type = type_datum;
    520 
    521 	return SEPOL_OK;
    522 
    523 exit:
    524 	return rc;
    525 }
    526 
    527 int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_args)
    528 {
    529 	struct cil_args_resolve *args = extra_args;
    530 	struct cil_nametypetransition *nametypetrans = current->data;
    531 	struct cil_symtab_datum *src_datum = NULL;
    532 	struct cil_symtab_datum *tgt_datum = NULL;
    533 	struct cil_symtab_datum *obj_datum = NULL;
    534 	struct cil_symtab_datum *name_datum = NULL;
    535 	struct cil_symtab_datum *result_datum = NULL;
    536 	struct cil_tree_node *result_node = NULL;
    537 	int rc = SEPOL_ERR;
    538 
    539 	rc = cil_resolve_name(current, nametypetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum);
    540 	if (rc != SEPOL_OK) {
    541 		goto exit;
    542 	}
    543 	nametypetrans->src = src_datum;
    544 	cil_type_used(src_datum);
    545 
    546 	rc = cil_resolve_name(current, nametypetrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum);
    547 	if (rc != SEPOL_OK) {
    548 		goto exit;
    549 	}
    550 	nametypetrans->tgt = tgt_datum;
    551 	cil_type_used(tgt_datum);
    552 
    553 	rc = cil_resolve_name(current, nametypetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
    554 	if (rc != SEPOL_OK) {
    555 		goto exit;
    556 	}
    557 	nametypetrans->obj = (struct cil_class*)obj_datum;
    558 
    559 	nametypetrans->name = __cil_insert_name(args->db, nametypetrans->name_str, current);
    560 	if (nametypetrans->name == NULL) {
    561 		rc = cil_resolve_name(current, nametypetrans->name_str, CIL_SYM_NAMES, extra_args, &name_datum);
    562 		if (rc != SEPOL_OK) {
    563 			goto exit;
    564 		}
    565 		nametypetrans->name = (struct cil_name *)name_datum;
    566 	}
    567 
    568 	rc = cil_resolve_name(current, nametypetrans->result_str, CIL_SYM_TYPES, extra_args, &result_datum);
    569 	if (rc != SEPOL_OK) {
    570 		goto exit;
    571 	}
    572 
    573 	result_node = result_datum->nodes->head->data;
    574 
    575 	if (result_node->flavor != CIL_TYPE && result_node->flavor != CIL_TYPEALIAS) {
    576 		cil_log(CIL_ERR, "typetransition result is not a type or type alias\n");
    577 		rc = SEPOL_ERR;
    578 		goto exit;
    579 	}
    580 	nametypetrans->result = result_datum;
    581 
    582 	return SEPOL_OK;
    583 
    584 exit:
    585 	return rc;
    586 }
    587 
    588 int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args)
    589 {
    590 	struct cil_rangetransition *rangetrans = current->data;
    591 	struct cil_symtab_datum *src_datum = NULL;
    592 	struct cil_symtab_datum *exec_datum = NULL;
    593 	struct cil_symtab_datum *obj_datum = NULL;
    594 	struct cil_symtab_datum *range_datum = NULL;
    595 	int rc = SEPOL_ERR;
    596 
    597 	rc = cil_resolve_name(current, rangetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum);
    598 	if (rc != SEPOL_OK) {
    599 		goto exit;
    600 	}
    601 	rangetrans->src = src_datum;
    602 	cil_type_used(src_datum);
    603 
    604 	rc = cil_resolve_name(current, rangetrans->exec_str, CIL_SYM_TYPES, extra_args, &exec_datum);
    605 	if (rc != SEPOL_OK) {
    606 		goto exit;
    607 	}
    608 	rangetrans->exec = exec_datum;
    609 	cil_type_used(exec_datum);
    610 
    611 	rc = cil_resolve_name(current, rangetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
    612 	if (rc != SEPOL_OK) {
    613 		goto exit;
    614 	}
    615 	rangetrans->obj = (struct cil_class*)obj_datum;
    616 
    617 	if (rangetrans->range_str != NULL) {
    618 		rc = cil_resolve_name(current, rangetrans->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum);
    619 		if (rc != SEPOL_OK) {
    620 			goto exit;
    621 		}
    622 		rangetrans->range = (struct cil_levelrange*)range_datum;
    623 
    624 		/* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/
    625 		if (rangetrans->range->datum.name == NULL) {
    626 			rc = cil_resolve_levelrange(current, rangetrans->range, extra_args);
    627 			if (rc != SEPOL_OK) {
    628 				goto exit;
    629 			}
    630 		}
    631 	} else {
    632 		rc = cil_resolve_levelrange(current, rangetrans->range, extra_args);
    633 		if (rc != SEPOL_OK) {
    634 			goto exit;
    635 		}
    636 	}
    637 
    638 	return SEPOL_OK;
    639 
    640 exit:
    641 	return rc;
    642 }
    643 
    644 int __class_update_perm_values(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
    645 {
    646 	struct cil_perm *perm = (struct cil_perm *)d;
    647 
    648 	perm->value += *((int *)args);
    649 
    650 	return SEPOL_OK;
    651 }
    652 
    653 int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args)
    654 {
    655 	struct cil_class *class = NULL;
    656 	struct cil_class *common = NULL;
    657 	struct cil_classcommon *clscom = current->data;
    658 	struct cil_symtab_datum *class_datum = NULL;
    659 	struct cil_symtab_datum *common_datum = NULL;
    660 	int rc = SEPOL_ERR;
    661 
    662 	rc = cil_resolve_name(current, clscom->class_str, CIL_SYM_CLASSES, extra_args, &class_datum);
    663 	if (rc != SEPOL_OK) {
    664 		goto exit;
    665 	}
    666 
    667 	rc = cil_resolve_name(current, clscom->common_str, CIL_SYM_COMMONS, extra_args, &common_datum);
    668 	if (rc != SEPOL_OK) {
    669 		goto exit;
    670 	}
    671 
    672 	class = (struct cil_class *)class_datum;
    673 	common = (struct cil_class *)common_datum;
    674 	if (class->common != NULL) {
    675 		cil_log(CIL_ERR, "class cannot be associeated with more than one common\n");
    676 		rc = SEPOL_ERR;
    677 		goto exit;
    678 	}
    679 
    680 	class->common = common;
    681 
    682 	cil_symtab_map(&class->perms, __class_update_perm_values, &common->num_perms);
    683 
    684 	class->num_perms += common->num_perms;
    685 
    686 	return SEPOL_OK;
    687 
    688 exit:
    689 	return rc;
    690 }
    691 
    692 int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args)
    693 {
    694 	int rc = SEPOL_ERR;
    695 	struct cil_classmapping *mapping = current->data;
    696 	struct cil_class *map = NULL;
    697 	struct cil_perm *mp = NULL;
    698 	struct cil_symtab_datum *datum = NULL;
    699 	struct cil_list_item *curr;
    700 
    701 	rc = cil_resolve_name(current, mapping->map_class_str, CIL_SYM_CLASSES, extra_args, &datum);
    702 	if (rc != SEPOL_OK) {
    703 		goto exit;
    704 	}
    705 	map = (struct cil_class*)datum;
    706 
    707 	rc = cil_symtab_get_datum(&map->perms, mapping->map_perm_str, &datum);
    708 	if (rc != SEPOL_OK) {
    709 		goto exit;
    710 	}
    711 
    712 	mp = (struct cil_perm*)datum;
    713 
    714 	rc = cil_resolve_classperms_list(current, mapping->classperms, extra_args);
    715 	if (rc != SEPOL_OK) {
    716 		goto exit;
    717 	}
    718 
    719 	if (mp->classperms == NULL) {
    720 		cil_list_init(&mp->classperms, CIL_CLASSPERMS);
    721 	}
    722 
    723 	cil_list_for_each(curr, mapping->classperms) {
    724 		cil_list_append(mp->classperms, curr->flavor, curr->data);
    725 	}
    726 
    727 	return SEPOL_OK;
    728 
    729 exit:
    730 	return rc;
    731 }
    732 
    733 int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args)
    734 {
    735 	struct cil_userrole *userrole = current->data;
    736 	struct cil_symtab_datum *user_datum = NULL;
    737 	struct cil_symtab_datum *role_datum = NULL;
    738 	int rc = SEPOL_ERR;
    739 
    740 	rc = cil_resolve_name(current, userrole->user_str, CIL_SYM_USERS, extra_args, &user_datum);
    741 	if (rc != SEPOL_OK) {
    742 		goto exit;
    743 	}
    744 	userrole->user = (struct cil_user*)user_datum;
    745 
    746 	rc = cil_resolve_name(current, userrole->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
    747 	if (rc != SEPOL_OK) {
    748 		goto exit;
    749 	}
    750 	userrole->role = role_datum;
    751 
    752 	if (userrole->user->roles == NULL) {
    753 		cil_list_init(&userrole->user->roles, CIL_LIST_ITEM);
    754 	}
    755 
    756 	cil_list_append(userrole->user->roles, CIL_ROLE, userrole->role);
    757 
    758 	return SEPOL_OK;
    759 
    760 exit:
    761 	return rc;
    762 }
    763 
    764 int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args)
    765 {
    766 	struct cil_userlevel *usrlvl = current->data;
    767 	struct cil_symtab_datum *user_datum = NULL;
    768 	struct cil_symtab_datum *lvl_datum = NULL;
    769 	struct cil_user *user = NULL;
    770 	int rc = SEPOL_ERR;
    771 
    772 	rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, extra_args, &user_datum);
    773 	if (rc != SEPOL_OK) {
    774 		goto exit;
    775 	}
    776 	user = (struct cil_user*)user_datum;
    777 
    778 	if (usrlvl->level_str != NULL) {
    779 		rc = cil_resolve_name(current, usrlvl->level_str, CIL_SYM_LEVELS, extra_args, &lvl_datum);
    780 		if (rc != SEPOL_OK) {
    781 			goto exit;
    782 		}
    783 		usrlvl->level = (struct cil_level*)lvl_datum;
    784 		user->dftlevel = usrlvl->level;
    785 
    786 		/* This could still be an anonymous level even if level_str is set, if level_str is a param_str*/
    787 		if (user->dftlevel->datum.name == NULL) {
    788 			rc = cil_resolve_level(current, user->dftlevel, extra_args);
    789 			if (rc != SEPOL_OK) {
    790 				goto exit;
    791 			}
    792 		}
    793 	} else if (usrlvl->level != NULL) {
    794 		rc = cil_resolve_level(current, usrlvl->level, extra_args);
    795 		if (rc != SEPOL_OK) {
    796 			goto exit;
    797 		}
    798 		user->dftlevel = usrlvl->level;
    799 	}
    800 
    801 	return SEPOL_OK;
    802 
    803 exit:
    804 	return rc;
    805 }
    806 
    807 int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args)
    808 {
    809 	struct cil_userrange *userrange = current->data;
    810 	struct cil_symtab_datum *user_datum = NULL;
    811 	struct cil_symtab_datum *range_datum = NULL;
    812 	struct cil_user *user = NULL;
    813 	int rc = SEPOL_ERR;
    814 
    815 	rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, extra_args, &user_datum);
    816 	if (rc != SEPOL_OK) {
    817 		goto exit;
    818 	}
    819 	user = (struct cil_user*)user_datum;
    820 
    821 	if (userrange->range_str != NULL) {
    822 		rc = cil_resolve_name(current, userrange->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum);
    823 		if (rc != SEPOL_OK) {
    824 			goto exit;
    825 		}
    826 		userrange->range = (struct cil_levelrange*)range_datum;
    827 		user->range = userrange->range;
    828 
    829 		/* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/
    830 		if (user->range->datum.name == NULL) {
    831 			rc = cil_resolve_levelrange(current, user->range, extra_args);
    832 			if (rc != SEPOL_OK) {
    833 				goto exit;
    834 			}
    835 		}
    836 	} else if (userrange->range != NULL) {
    837 		rc = cil_resolve_levelrange(current, userrange->range, extra_args);
    838 		if (rc != SEPOL_OK) {
    839 			goto exit;
    840 		}
    841 		user->range = userrange->range;
    842 	}
    843 
    844 	return SEPOL_OK;
    845 
    846 exit:
    847 	return rc;
    848 }
    849 
    850 int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args)
    851 {
    852 	struct cil_userprefix *userprefix = current->data;
    853 	struct cil_symtab_datum *user_datum = NULL;
    854 	int rc = SEPOL_ERR;
    855 
    856 	rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, extra_args, &user_datum);
    857 	if (rc != SEPOL_OK) {
    858 		goto exit;
    859 	}
    860 	userprefix->user = (struct cil_user*)user_datum;
    861 
    862 exit:
    863 	return rc;
    864 }
    865 
    866 int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args)
    867 {
    868 	struct cil_selinuxuser *selinuxuser = current->data;
    869 	struct cil_symtab_datum *user_datum = NULL;
    870 	struct cil_symtab_datum *lvlrange_datum = NULL;
    871 	int rc = SEPOL_ERR;
    872 
    873 	rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, extra_args, &user_datum);
    874 	if (rc != SEPOL_OK) {
    875 		goto exit;
    876 	}
    877 	selinuxuser->user = (struct cil_user*)user_datum;
    878 
    879 	if (selinuxuser->range_str != NULL) {
    880 		rc = cil_resolve_name(current, selinuxuser->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
    881 		if (rc != SEPOL_OK) {
    882 			cil_log(CIL_ERR, "Unable to resolve name: %s\n", selinuxuser->range_str);
    883 			goto exit;
    884 		}
    885 		selinuxuser->range = (struct cil_levelrange*)lvlrange_datum;
    886 
    887 		/* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/
    888 		if (selinuxuser->range->datum.name == NULL) {
    889 			rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args);
    890 			if (rc != SEPOL_OK) {
    891 				goto exit;
    892 			}
    893 		}
    894 	} else if (selinuxuser->range != NULL) {
    895 		rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args);
    896 		if (rc != SEPOL_OK) {
    897 			goto exit;
    898 		}
    899 	}
    900 
    901 	rc = SEPOL_OK;
    902 exit:
    903 	return rc;
    904 }
    905 
    906 int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args)
    907 {
    908 	struct cil_roletype *roletype = current->data;
    909 	struct cil_symtab_datum *role_datum = NULL;
    910 	struct cil_symtab_datum *type_datum = NULL;
    911 	int rc = SEPOL_ERR;
    912 
    913 	rc = cil_resolve_name(current, roletype->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
    914 	if (rc != SEPOL_OK) {
    915 		goto exit;
    916 	}
    917 	roletype->role = (struct cil_role*)role_datum;
    918 
    919 	rc = cil_resolve_name(current, roletype->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
    920 	if (rc != SEPOL_OK) {
    921 		goto exit;
    922 	}
    923 	roletype->type = (struct cil_type*)type_datum;
    924 	cil_type_used(type_datum);
    925 
    926 	return SEPOL_OK;
    927 
    928 exit:
    929 	return rc;
    930 }
    931 
    932 int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args)
    933 {
    934 	struct cil_roletransition *roletrans = current->data;
    935 	struct cil_symtab_datum *src_datum = NULL;
    936 	struct cil_symtab_datum *tgt_datum = NULL;
    937 	struct cil_symtab_datum *obj_datum = NULL;
    938 	struct cil_symtab_datum *result_datum = NULL;
    939 	struct cil_tree_node *node = NULL;
    940 	int rc = SEPOL_ERR;
    941 
    942 	rc = cil_resolve_name(current, roletrans->src_str, CIL_SYM_ROLES, extra_args, &src_datum);
    943 	if (rc != SEPOL_OK) {
    944 		goto exit;
    945 	}
    946 	roletrans->src = (struct cil_role*)src_datum;
    947 
    948 	rc = cil_resolve_name(current, roletrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum);
    949 	if (rc != SEPOL_OK) {
    950 		goto exit;
    951 	}
    952 	roletrans->tgt = tgt_datum;
    953 	cil_type_used(tgt_datum);
    954 
    955 	rc = cil_resolve_name(current, roletrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
    956 	if (rc != SEPOL_OK) {
    957 		goto exit;
    958 	}
    959 	roletrans->obj = (struct cil_class*)obj_datum;
    960 
    961 	rc = cil_resolve_name(current, roletrans->result_str, CIL_SYM_ROLES, extra_args, &result_datum);
    962 	if (rc != SEPOL_OK) {
    963 		goto exit;
    964 	}
    965 	node = result_datum->nodes->head->data;
    966 	if (node->flavor != CIL_ROLE) {
    967 		rc = SEPOL_ERR;
    968 		printf("%i\n", node->flavor);
    969 		cil_log(CIL_ERR, "roletransition must result in a role, but %s is a %s\n", roletrans->result_str, cil_node_to_string(node));
    970 		goto exit;
    971 	}
    972 	roletrans->result = (struct cil_role*)result_datum;
    973 
    974 	return SEPOL_OK;
    975 
    976 exit:
    977 	return rc;
    978 }
    979 
    980 int cil_resolve_roleallow(struct cil_tree_node *current, void *extra_args)
    981 {
    982 	struct cil_roleallow *roleallow = current->data;
    983 	struct cil_symtab_datum *src_datum = NULL;
    984 	struct cil_symtab_datum *tgt_datum = NULL;
    985 	int rc = SEPOL_ERR;
    986 
    987 	rc = cil_resolve_name(current, roleallow->src_str, CIL_SYM_ROLES, extra_args, &src_datum);
    988 	if (rc != SEPOL_OK) {
    989 		goto exit;
    990 	}
    991 	roleallow->src = (struct cil_role*)src_datum;
    992 
    993 	rc = cil_resolve_name(current, roleallow->tgt_str, CIL_SYM_ROLES, extra_args, &tgt_datum);
    994 	if (rc != SEPOL_OK) {
    995 		goto exit;
    996 	}
    997 	roleallow->tgt = (struct cil_role*)tgt_datum;
    998 
    999 	return SEPOL_OK;
   1000 
   1001 exit:
   1002 	return rc;
   1003 }
   1004 
   1005 int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args)
   1006 {
   1007 	int rc = SEPOL_ERR;
   1008 	struct cil_roleattributeset *attrroles = current->data;
   1009 	struct cil_symtab_datum *attr_datum = NULL;
   1010 	struct cil_tree_node *attr_node = NULL;
   1011 	struct cil_roleattribute *attr = NULL;
   1012 
   1013 	rc = cil_resolve_name(current, attrroles->attr_str, CIL_SYM_ROLES, extra_args, &attr_datum);
   1014 	if (rc != SEPOL_OK) {
   1015 		goto exit;
   1016 	}
   1017 	attr_node = attr_datum->nodes->head->data;
   1018 
   1019 	if (attr_node->flavor != CIL_ROLEATTRIBUTE) {
   1020 		rc = SEPOL_ERR;
   1021 		cil_log(CIL_ERR, "Attribute role not an attribute\n");
   1022 		goto exit;
   1023 	}
   1024 	attr = (struct cil_roleattribute*)attr_datum;
   1025 
   1026 	rc = cil_resolve_expr(CIL_ROLEATTRIBUTESET, attrroles->str_expr, &attrroles->datum_expr, current, extra_args);
   1027 	if (rc != SEPOL_OK) {
   1028 		goto exit;
   1029 	}
   1030 
   1031 	rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr);
   1032 	if (rc != SEPOL_OK) {
   1033 		goto exit;
   1034 	}
   1035 
   1036 	if (attr->expr_list == NULL) {
   1037 		cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE);
   1038 	}
   1039 
   1040 	cil_list_append(attr->expr_list, CIL_LIST, attrroles->datum_expr);
   1041 
   1042 	return SEPOL_OK;
   1043 
   1044 exit:
   1045 	return rc;
   1046 }
   1047 
   1048 struct cil_ordered_list {
   1049 	int merged;
   1050 	struct cil_list *list;
   1051 	struct cil_tree_node *node;
   1052 };
   1053 
   1054 void __cil_ordered_list_init(struct cil_ordered_list **ordered)
   1055 {
   1056 	*ordered = cil_malloc(sizeof(**ordered));
   1057 
   1058 	(*ordered)->merged = CIL_FALSE;
   1059 	(*ordered)->list = NULL;
   1060 	(*ordered)->node = NULL;
   1061 }
   1062 
   1063 void __cil_ordered_list_destroy(struct cil_ordered_list **ordered)
   1064 {
   1065 	cil_list_destroy(&(*ordered)->list, CIL_FALSE);
   1066 	(*ordered)->node = NULL;
   1067 	free(*ordered);
   1068 	*ordered = NULL;
   1069 }
   1070 
   1071 void __cil_ordered_lists_destroy(struct cil_list **ordered_lists)
   1072 {
   1073 	struct cil_list_item *item = NULL;
   1074 
   1075 	if (*ordered_lists == NULL) {
   1076 		return;
   1077 	}
   1078 
   1079 	item = (*ordered_lists)->head;
   1080 	while (item != NULL) {
   1081 		struct cil_list_item *next = item->next;
   1082 		struct cil_ordered_list *ordered = item->data;
   1083 		__cil_ordered_list_destroy(&ordered);
   1084 		free(item);
   1085 		item = next;
   1086 	}
   1087 	free(*ordered_lists);
   1088 	*ordered_lists = NULL;
   1089 }
   1090 
   1091 void __cil_ordered_lists_reset(struct cil_list **ordered_lists)
   1092 {
   1093 	__cil_ordered_lists_destroy(ordered_lists);
   1094 	cil_list_init(ordered_lists, CIL_LIST_ITEM);
   1095 }
   1096 
   1097 struct cil_list_item *__cil_ordered_item_insert(struct cil_list *old, struct cil_list_item *curr, struct cil_list_item *item)
   1098 {
   1099 	if (item->flavor == CIL_SID) {
   1100 		struct cil_sid *sid = item->data;
   1101 		if (sid->ordered == CIL_TRUE) {
   1102 			cil_log(CIL_ERR, "SID %s has already been merged into the ordered list\n", sid->datum.name);
   1103 			return NULL;
   1104 		}
   1105 		sid->ordered = CIL_TRUE;
   1106 	} else if (item->flavor == CIL_CLASS) {
   1107 		struct cil_class *class = item->data;
   1108 		if (class->ordered == CIL_TRUE) {
   1109 			cil_log(CIL_ERR, "Class %s has already been merged into the ordered list\n", class->datum.name);
   1110 			return NULL;
   1111 		}
   1112 		class->ordered = CIL_TRUE;
   1113 	} else if (item->flavor == CIL_CAT) {
   1114 		struct cil_cat *cat = item->data;
   1115 		if (cat->ordered == CIL_TRUE) {
   1116 			cil_log(CIL_ERR, "Category %s has already been merged into the ordered list\n", cat->datum.name);
   1117 			return NULL;
   1118 		}
   1119 		cat->ordered = CIL_TRUE;
   1120 	} else if (item->flavor == CIL_SENS) {
   1121 		struct cil_sens *sens = item->data;
   1122 		if (sens->ordered == CIL_TRUE) {
   1123 			cil_log(CIL_ERR, "Sensitivity %s has already been merged into the ordered list\n", sens->datum.name);
   1124 			return NULL;
   1125 		}
   1126 		sens->ordered = CIL_TRUE;
   1127 	}
   1128 
   1129 	return cil_list_insert(old, curr, item->flavor, item->data);
   1130 }
   1131 
   1132 int __cil_ordered_list_insert(struct cil_list *old, struct cil_list_item *ocurr, struct cil_list_item *nstart, struct cil_list_item *nstop)
   1133 {
   1134 	struct cil_list_item *ncurr = NULL;
   1135 
   1136 	for (ncurr = nstart; ncurr != nstop; ncurr = ncurr->next) {
   1137 		ocurr = __cil_ordered_item_insert(old, ocurr, ncurr);
   1138 		if (ocurr == NULL) {
   1139 			return SEPOL_ERR;
   1140 		}
   1141 	}
   1142 	return SEPOL_OK;
   1143 }
   1144 
   1145 struct cil_list_item *__cil_ordered_find_match(struct cil_list_item *t, struct cil_list_item *i)
   1146 {
   1147 	while (i) {
   1148 		if (i->data == t->data) {
   1149 			return i;
   1150 		}
   1151 		i = i->next;
   1152 	}
   1153 	return NULL;
   1154 }
   1155 
   1156 int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
   1157 {
   1158 	struct cil_list_item *omatch = NULL;
   1159 	struct cil_list_item *ofirst = old->head;
   1160 	struct cil_list_item *ocurr = NULL;
   1161 	struct cil_list_item *oprev = NULL;
   1162 	struct cil_list_item *nmatch = NULL;
   1163 	struct cil_list_item *nfirst = new->head;
   1164 	struct cil_list_item *ncurr = NULL;
   1165 	int rc = SEPOL_ERR;
   1166 
   1167 	if (nfirst == NULL) {
   1168 		return SEPOL_OK;
   1169 	}
   1170 
   1171 	if (ofirst == NULL) {
   1172 		/* First list added */
   1173 		rc = __cil_ordered_list_insert(old, NULL, nfirst, NULL);
   1174 		return rc;
   1175 	}
   1176 
   1177 	/* Find a match between the new list and the old one */
   1178 	for (nmatch = nfirst; nmatch; nmatch = nmatch->next) {
   1179 		omatch = __cil_ordered_find_match(nmatch, ofirst);
   1180 		if (omatch) {
   1181 			break;
   1182 		}
   1183 	}
   1184 
   1185 	if (!nmatch) {
   1186 		/* List cannot be merged yet */
   1187 		return SEPOL_ERR;
   1188 	}
   1189 
   1190 	if (nmatch != nfirst && omatch != ofirst) {
   1191 		/* Potential ordering conflict--try again later */
   1192 		return SEPOL_ERR;
   1193 	}
   1194 
   1195 	if (nmatch != nfirst) {
   1196 		/* Prepend the beginning of the new list up to the first match to the old list */
   1197 		rc = __cil_ordered_list_insert(old, NULL, nfirst, nmatch);
   1198 		if (rc != SEPOL_OK) {
   1199 			return rc;
   1200 		}
   1201 	}
   1202 
   1203 	/* In the overlapping protion, add items from the new list not in the old list */
   1204 	ncurr = nmatch->next;
   1205 	ocurr = omatch->next;
   1206 	oprev = omatch;
   1207 	while (ncurr && ocurr) {
   1208 		if (ncurr->data == ocurr->data) {
   1209 			oprev = ocurr;
   1210 			ocurr = ocurr->next;
   1211 			ncurr = ncurr->next;
   1212 		} else {
   1213 			/* Handle gap in old: old = (A C)  new = (A B C) */
   1214 			nmatch = __cil_ordered_find_match(ocurr, ncurr->next);
   1215 			if (nmatch) {
   1216 				rc = __cil_ordered_list_insert(old, oprev, ncurr, nmatch);
   1217 				if (rc != SEPOL_OK) {
   1218 					return rc;
   1219 				}
   1220 				oprev = ocurr;
   1221 				ocurr = ocurr->next;
   1222 				ncurr = nmatch->next;
   1223 				continue;
   1224 			}
   1225 			/* Handle gap in new: old = (A B C)  new = (A C) */
   1226 			omatch = __cil_ordered_find_match(ncurr, ocurr->next);
   1227 			if (omatch) {
   1228 				/* Nothing to insert, just skip */
   1229 				oprev = omatch;
   1230 				ocurr = omatch->next;
   1231 				ncurr = ncurr->next;
   1232 				continue;
   1233 			} else {
   1234 				return SEPOL_ERR;
   1235 			}
   1236 		}
   1237 	}
   1238 
   1239 	if (ncurr) {
   1240 		/* Add the rest of the items from the new list */
   1241 		rc = __cil_ordered_list_insert(old, old->tail, ncurr, NULL);
   1242 		if (rc != SEPOL_OK) {
   1243 			return rc;
   1244 		}
   1245 	}
   1246 
   1247 	return SEPOL_OK;
   1248 }
   1249 
   1250 struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
   1251 {
   1252 	struct cil_list *composite = NULL;
   1253 	struct cil_list_item *curr = NULL;
   1254 	int changed = CIL_TRUE;
   1255 	int waiting = 1;
   1256 	int rc = SEPOL_ERR;
   1257 
   1258 	cil_list_init(&composite, CIL_LIST_ITEM);
   1259 
   1260 	while (waiting && changed == CIL_TRUE) {
   1261 		changed = CIL_FALSE;
   1262 		waiting = 0;
   1263 		cil_list_for_each(curr, *ordered_lists) {
   1264 			struct cil_ordered_list *ordered_list = curr->data;
   1265 			if (ordered_list->merged == CIL_FALSE) {
   1266 				rc = __cil_ordered_lists_merge(composite, ordered_list->list);
   1267 				if (rc != SEPOL_OK) {
   1268 					/* Can't merge yet */
   1269 					waiting++;
   1270 				} else {
   1271 					ordered_list->merged = CIL_TRUE;
   1272 					changed = CIL_TRUE;
   1273 				}
   1274 			}
   1275 		}
   1276 		if (waiting > 0 && changed == CIL_FALSE) {
   1277 			cil_list_for_each(curr, *ordered_lists) {
   1278 				struct cil_ordered_list *ordered_list = curr->data;
   1279 				if (ordered_list->merged == CIL_FALSE) {
   1280 					cil_log(CIL_ERR, "Unable to merge ordered list at line %d of %s\n",ordered_list->node->line, ordered_list->node->path);
   1281 				}
   1282 			}
   1283 			goto exit;
   1284 		}
   1285 	}
   1286 
   1287 	__cil_ordered_lists_destroy(ordered_lists);
   1288 
   1289 	return composite;
   1290 
   1291 exit:
   1292 	cil_list_destroy(&composite, CIL_FALSE);
   1293 	return NULL;
   1294 }
   1295 
   1296 int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
   1297 {
   1298 	struct cil_args_resolve *args = extra_args;
   1299 	struct cil_list *classorder_list = args->classorder_lists;
   1300 	struct cil_classorder *classorder = current->data;
   1301 	struct cil_list *new = NULL;
   1302 	struct cil_list_item *curr = NULL;
   1303 	struct cil_symtab_datum *datum = NULL;
   1304 	struct cil_ordered_list *ordered = NULL;
   1305 	int rc = SEPOL_ERR;
   1306 
   1307 	cil_list_init(&new, CIL_CLASSORDER);
   1308 
   1309 	cil_list_for_each(curr, classorder->class_list_str) {
   1310 		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
   1311 		if (rc != SEPOL_OK) {
   1312 			cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
   1313 			goto exit;
   1314 		}
   1315 		cil_list_append(new, CIL_CLASS, datum);
   1316 	}
   1317 
   1318 	__cil_ordered_list_init(&ordered);
   1319 	ordered->list = new;
   1320 	ordered->node = current;
   1321 	cil_list_append(classorder_list, CIL_CLASSORDER, ordered);
   1322 
   1323 	return SEPOL_OK;
   1324 
   1325 exit:
   1326 	return rc;
   1327 }
   1328 
   1329 int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args)
   1330 {
   1331 	struct cil_args_resolve *args = extra_args;
   1332 	struct cil_list *sidorder_list = args->sidorder_lists;
   1333 	struct cil_sidorder *sidorder = current->data;
   1334 	struct cil_list *new = NULL;
   1335 	struct cil_list_item *curr = NULL;
   1336 	struct cil_symtab_datum *datum = NULL;
   1337 	struct cil_ordered_list *ordered = NULL;
   1338 	int rc = SEPOL_ERR;
   1339 
   1340 	cil_list_init(&new, CIL_SIDORDER);
   1341 
   1342 	cil_list_for_each(curr, sidorder->sid_list_str) {
   1343 		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SIDS, extra_args, &datum);
   1344 		if (rc != SEPOL_OK) {
   1345 			cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data);
   1346 			goto exit;
   1347 		}
   1348 		cil_list_append(new, CIL_SID, datum);
   1349 	}
   1350 
   1351 	__cil_ordered_list_init(&ordered);
   1352 	ordered->list = new;
   1353 	ordered->node = current;
   1354 	cil_list_append(sidorder_list, CIL_SIDORDER, ordered);
   1355 
   1356 	return SEPOL_OK;
   1357 
   1358 exit:
   1359 	return rc;
   1360 }
   1361 
   1362 void cil_set_cat_values(struct cil_list *ordered_cats, struct cil_db *db)
   1363 {
   1364 	struct cil_list_item *curr;
   1365 	int v = 0;
   1366 
   1367 	cil_list_for_each(curr, ordered_cats) {
   1368 		struct cil_cat *cat = curr->data;
   1369 		cat->value = v;
   1370 		v++;
   1371 	}
   1372 
   1373 	db->num_cats = v;
   1374 }
   1375 
   1376 int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args)
   1377 {
   1378 	struct cil_args_resolve *args = extra_args;
   1379 	struct cil_list *catorder_list = args->catorder_lists;
   1380 	struct cil_catorder *catorder = current->data;
   1381 	struct cil_list *new = NULL;
   1382 	struct cil_list_item *curr = NULL;
   1383 	struct cil_symtab_datum *cat_datum;
   1384 	struct cil_cat *cat = NULL;
   1385 	struct cil_ordered_list *ordered = NULL;
   1386 	int rc = SEPOL_ERR;
   1387 
   1388 	cil_list_init(&new, CIL_CATORDER);
   1389 
   1390 	cil_list_for_each(curr, catorder->cat_list_str) {
   1391 		struct cil_tree_node *node = NULL;
   1392 		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CATS, extra_args, &cat_datum);
   1393 		if (rc != SEPOL_OK) {
   1394 			cil_log(CIL_ERR, "Failed to resolve category %s in categoryorder\n", (char *)curr->data);
   1395 			goto exit;
   1396 		}
   1397 		node = cat_datum->nodes->head->data;
   1398 		if (node->flavor != CIL_CAT) {
   1399 			cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", cat_datum->name);
   1400 			rc = SEPOL_ERR;
   1401 			goto exit;
   1402 		}
   1403 		cat = (struct cil_cat *)cat_datum;
   1404 		cil_list_append(new, CIL_CAT, cat);
   1405 	}
   1406 
   1407 	__cil_ordered_list_init(&ordered);
   1408 	ordered->list = new;
   1409 	ordered->node = current;
   1410 	cil_list_append(catorder_list, CIL_CATORDER, ordered);
   1411 
   1412 	return SEPOL_OK;
   1413 
   1414 exit:
   1415 	return rc;
   1416 }
   1417 
   1418 int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args)
   1419 {
   1420 	struct cil_args_resolve *args = extra_args;
   1421 	struct cil_list *sensitivityorder_list = args->sensitivityorder_lists;
   1422 	struct cil_sensorder *sensorder = current->data;
   1423 	struct cil_list *new = NULL;
   1424 	struct cil_list_item *curr = NULL;
   1425 	struct cil_symtab_datum *datum = NULL;
   1426 	struct cil_ordered_list *ordered = NULL;
   1427 	int rc = SEPOL_ERR;
   1428 
   1429 	cil_list_init(&new, CIL_LIST_ITEM);
   1430 
   1431 	cil_list_for_each(curr, sensorder->sens_list_str) {
   1432 		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum);
   1433 		if (rc != SEPOL_OK) {
   1434 			cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data);
   1435 			goto exit;
   1436 		}
   1437 		cil_list_append(new, CIL_SENS, datum);
   1438 	}
   1439 
   1440 	__cil_ordered_list_init(&ordered);
   1441 	ordered->list = new;
   1442 	ordered->node = current;
   1443 	cil_list_append(sensitivityorder_list, CIL_SENSITIVITYORDER, ordered);
   1444 
   1445 	return SEPOL_OK;
   1446 
   1447 exit:
   1448 	return rc;
   1449 }
   1450 
   1451 int cil_resolve_cats(struct cil_tree_node *current, struct cil_cats *cats, void *extra_args)
   1452 {
   1453 	int rc = SEPOL_ERR;
   1454 
   1455 	rc = cil_resolve_expr(CIL_CATSET, cats->str_expr, &cats->datum_expr, current, extra_args);
   1456 	if (rc != SEPOL_OK) {
   1457 		cil_log(CIL_ERR,"Unable to resolve categories\n");
   1458 		goto exit;
   1459 	}
   1460 
   1461 	return SEPOL_OK;
   1462 
   1463 exit:
   1464 	return rc;
   1465 }
   1466 
   1467 
   1468 int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args)
   1469 {
   1470 	int rc = SEPOL_ERR;
   1471 
   1472 	rc = cil_resolve_cats(current, catset->cats, extra_args);
   1473 	if (rc != SEPOL_OK) {
   1474 		goto exit;
   1475 	}
   1476 
   1477 	rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr);
   1478 	if (rc != SEPOL_OK) {
   1479 		cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE);
   1480 		goto exit;
   1481 	}
   1482 
   1483 exit:
   1484 	return rc;
   1485 }
   1486 
   1487 int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args)
   1488 {
   1489 	int rc = SEPOL_ERR;
   1490 	struct cil_senscat *senscat = current->data;
   1491 	struct cil_symtab_datum *sens_datum;
   1492 	struct cil_sens *sens = NULL;
   1493 
   1494 	rc = cil_resolve_name(current, (char*)senscat->sens_str, CIL_SYM_SENS, extra_args, &sens_datum);
   1495 	if (rc != SEPOL_OK) {
   1496 		cil_log(CIL_ERR, "Failed to find sensitivity\n");
   1497 		goto exit;
   1498 	}
   1499 
   1500 	rc = cil_resolve_cats(current, senscat->cats, extra_args);
   1501 	if (rc != SEPOL_OK) {
   1502 		goto exit;
   1503 	}
   1504 
   1505 	sens = (struct cil_sens *)sens_datum;
   1506 
   1507 	if (sens->cats_list == NULL ) {
   1508 		cil_list_init(&sens->cats_list, CIL_CAT);
   1509 	}
   1510 
   1511 	cil_list_append(sens->cats_list, CIL_CAT, senscat->cats);
   1512 
   1513 	return SEPOL_OK;
   1514 
   1515 exit:
   1516 	return rc;
   1517 }
   1518 
   1519 int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, void *extra_args)
   1520 {
   1521 	struct cil_symtab_datum *sens_datum = NULL;
   1522 	int rc = SEPOL_ERR;
   1523 
   1524 	rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum);
   1525 	if (rc != SEPOL_OK) {
   1526 		cil_log(CIL_ERR, "Failed to find sensitivity\n");
   1527 		goto exit;
   1528 	}
   1529 
   1530 	level->sens = (struct cil_sens *)sens_datum;
   1531 
   1532 	if (level->cats != NULL) {
   1533 		rc = cil_resolve_cats(current, level->cats, extra_args);
   1534 		if (rc != SEPOL_OK) {
   1535 			goto exit;
   1536 		}
   1537 	}
   1538 
   1539 	return SEPOL_OK;
   1540 
   1541 exit:
   1542 	return rc;
   1543 }
   1544 
   1545 int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *lvlrange, void *extra_args)
   1546 {
   1547 	struct cil_symtab_datum *low_datum = NULL;
   1548 	struct cil_symtab_datum *high_datum = NULL;
   1549 	int rc = SEPOL_ERR;
   1550 
   1551 	if (lvlrange->low_str != NULL) {
   1552 		rc = cil_resolve_name(current, lvlrange->low_str, CIL_SYM_LEVELS, extra_args, &low_datum);
   1553 		if (rc != SEPOL_OK) {
   1554 			goto exit;
   1555 		}
   1556 		lvlrange->low = (struct cil_level*)low_datum;
   1557 
   1558 		/* This could still be an anonymous level even if low_str is set, if low_str is a param_str */
   1559 		if (lvlrange->low->datum.name == NULL) {
   1560 			rc = cil_resolve_level(current, lvlrange->low, extra_args);
   1561 			if (rc != SEPOL_OK) {
   1562 				goto exit;
   1563 			}
   1564 		}
   1565 	} else if (lvlrange->low != NULL) {
   1566 		rc = cil_resolve_level(current, lvlrange->low, extra_args);
   1567 		if (rc != SEPOL_OK) {
   1568 			goto exit;
   1569 		}
   1570 	}
   1571 
   1572 	if (lvlrange->high_str != NULL) {
   1573 		rc = cil_resolve_name(current, lvlrange->high_str, CIL_SYM_LEVELS, extra_args, &high_datum);
   1574 		if (rc != SEPOL_OK) {
   1575 			goto exit;
   1576 		}
   1577 		lvlrange->high = (struct cil_level*)high_datum;
   1578 
   1579 		/* This could still be an anonymous level even if high_str is set, if high_str is a param_str */
   1580 		if (lvlrange->high->datum.name == NULL) {
   1581 			rc = cil_resolve_level(current, lvlrange->high, extra_args);
   1582 			if (rc != SEPOL_OK) {
   1583 				goto exit;
   1584 			}
   1585 		}
   1586 	} else if (lvlrange->high != NULL) {
   1587 		rc = cil_resolve_level(current, lvlrange->high, extra_args);
   1588 		if (rc != SEPOL_OK) {
   1589 			goto exit;
   1590 		}
   1591 	}
   1592 
   1593 	return SEPOL_OK;
   1594 
   1595 exit:
   1596 	return rc;
   1597 }
   1598 
   1599 int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args)
   1600 {
   1601 	struct cil_constrain *cons = current->data;
   1602 	int rc = SEPOL_ERR;
   1603 
   1604 	rc = cil_resolve_classperms_list(current, cons->classperms, extra_args);
   1605 	if (rc != SEPOL_OK) {
   1606 		goto exit;
   1607 	}
   1608 
   1609 	rc = cil_resolve_expr(CIL_CONSTRAIN, cons->str_expr, &cons->datum_expr, current, extra_args);
   1610 	if (rc != SEPOL_OK) {
   1611 		goto exit;
   1612 	}
   1613 
   1614 	return SEPOL_OK;
   1615 
   1616 exit:
   1617 	return rc;
   1618 }
   1619 
   1620 int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args)
   1621 {
   1622 	struct cil_validatetrans *validtrans = current->data;
   1623 	struct cil_args_resolve *args = extra_args;
   1624 	struct cil_symtab_datum *class_datum = NULL;
   1625 	int rc = SEPOL_ERR;
   1626 
   1627 	rc = cil_resolve_name(current, validtrans->class_str, CIL_SYM_CLASSES, args, &class_datum);
   1628 	if (rc != SEPOL_OK) {
   1629 		goto exit;
   1630 	}
   1631 	validtrans->class = (struct cil_class*)class_datum;
   1632 
   1633 	rc = cil_resolve_expr(CIL_VALIDATETRANS, validtrans->str_expr, &validtrans->datum_expr, current, extra_args);
   1634 	if (rc != SEPOL_OK) {
   1635 		goto exit;
   1636 	}
   1637 
   1638 	return SEPOL_OK;
   1639 
   1640 exit:
   1641 	return rc;
   1642 }
   1643 
   1644 int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args)
   1645 {
   1646 	struct cil_symtab_datum *user_datum = NULL;
   1647 	struct cil_symtab_datum *role_datum = NULL;
   1648 	struct cil_symtab_datum *type_datum = NULL;
   1649 	struct cil_tree_node *type_node = NULL;
   1650 	struct cil_symtab_datum *lvlrange_datum = NULL;
   1651 
   1652 	int rc = SEPOL_ERR;
   1653 
   1654 	rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, extra_args, &user_datum);
   1655 	if (rc != SEPOL_OK) {
   1656 		cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->user_str);
   1657 		goto exit;
   1658 	}
   1659 	context->user = (struct cil_user*)user_datum;
   1660 
   1661 	rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
   1662 	if (rc != SEPOL_OK) {
   1663 		cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->role_str);
   1664 		goto exit;
   1665 	}
   1666 	context->role = (struct cil_role*)role_datum;
   1667 
   1668 	rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
   1669 	if (rc != SEPOL_OK) {
   1670 		cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->type_str);
   1671 		goto exit;
   1672 	}
   1673 
   1674 	type_node = type_datum->nodes->head->data;
   1675 
   1676 	if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) {
   1677 		rc = SEPOL_ERR;
   1678 		cil_log(CIL_ERR, "Type not a type or type alias\n");
   1679 		goto exit;
   1680 	}
   1681 	context->type = type_datum;
   1682 
   1683 	if (context->range_str != NULL) {
   1684 		rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
   1685 		if (rc != SEPOL_OK) {
   1686 			cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->range_str);
   1687 			goto exit;
   1688 		}
   1689 		context->range = (struct cil_levelrange*)lvlrange_datum;
   1690 
   1691 		/* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/
   1692 		if (context->range->datum.name == NULL) {
   1693 			rc = cil_resolve_levelrange(current, context->range, extra_args);
   1694 			if (rc != SEPOL_OK) {
   1695 				goto exit;
   1696 			}
   1697 		}
   1698 	} else if (context->range != NULL) {
   1699 		rc = cil_resolve_levelrange(current, context->range, extra_args);
   1700 		if (rc != SEPOL_OK) {
   1701 			goto exit;
   1702 		}
   1703 	}
   1704 
   1705 	return SEPOL_OK;
   1706 
   1707 exit:
   1708 	return rc;
   1709 }
   1710 
   1711 int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args)
   1712 {
   1713 	struct cil_filecon *filecon = current->data;
   1714 	struct cil_symtab_datum *context_datum = NULL;
   1715 	int rc = SEPOL_ERR;
   1716 
   1717 	if (filecon->context_str != NULL) {
   1718 		rc = cil_resolve_name(current, filecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1719 		if (rc != SEPOL_OK) {
   1720 			return rc;
   1721 		}
   1722 		filecon->context = (struct cil_context*)context_datum;
   1723 	} else if (filecon->context != NULL) {
   1724 		rc = cil_resolve_context(current, filecon->context, extra_args);
   1725 		if (rc != SEPOL_OK) {
   1726 			return rc;
   1727 		}
   1728 	}
   1729 
   1730 	return SEPOL_OK;
   1731 }
   1732 
   1733 int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args)
   1734 {
   1735 	struct cil_portcon *portcon = current->data;
   1736 	struct cil_symtab_datum *context_datum = NULL;
   1737 	int rc = SEPOL_ERR;
   1738 
   1739 	if (portcon->context_str != NULL) {
   1740 		rc = cil_resolve_name(current, portcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1741 		if (rc != SEPOL_OK) {
   1742 			goto exit;
   1743 		}
   1744 		portcon->context = (struct cil_context*)context_datum;
   1745 	} else {
   1746 		rc = cil_resolve_context(current, portcon->context, extra_args);
   1747 		if (rc != SEPOL_OK) {
   1748 			goto exit;
   1749 		}
   1750 	}
   1751 
   1752 	return SEPOL_OK;
   1753 
   1754 exit:
   1755 	return rc;
   1756 }
   1757 
   1758 int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args)
   1759 {
   1760 	struct cil_genfscon *genfscon = current->data;
   1761 	struct cil_symtab_datum *context_datum = NULL;
   1762 	int rc = SEPOL_ERR;
   1763 
   1764 	if (genfscon->context_str != NULL) {
   1765 		rc = cil_resolve_name(current, genfscon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1766 		if (rc != SEPOL_OK) {
   1767 			goto exit;
   1768 		}
   1769 		genfscon->context = (struct cil_context*)context_datum;
   1770 	} else {
   1771 		rc = cil_resolve_context(current, genfscon->context, extra_args);
   1772 		if (rc != SEPOL_OK) {
   1773 			goto exit;
   1774 		}
   1775 	}
   1776 
   1777 	return SEPOL_OK;
   1778 
   1779 exit:
   1780 	return rc;
   1781 }
   1782 
   1783 int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args)
   1784 {
   1785 	struct cil_nodecon *nodecon = current->data;
   1786 	struct cil_symtab_datum *addr_datum = NULL;
   1787 	struct cil_symtab_datum *mask_datum = NULL;
   1788 	struct cil_symtab_datum *context_datum = NULL;
   1789 	int rc = SEPOL_ERR;
   1790 
   1791 	if (nodecon->addr_str != NULL) {
   1792 		rc = cil_resolve_name(current, nodecon->addr_str, CIL_SYM_IPADDRS, extra_args, &addr_datum);
   1793 		if (rc != SEPOL_OK) {
   1794 			goto exit;
   1795 		}
   1796 		nodecon->addr = (struct cil_ipaddr*)addr_datum;
   1797 	}
   1798 
   1799 	if (nodecon->mask_str != NULL) {
   1800 		rc = cil_resolve_name(current, nodecon->mask_str, CIL_SYM_IPADDRS, extra_args, &mask_datum);
   1801 		if (rc != SEPOL_OK) {
   1802 			goto exit;
   1803 		}
   1804 		nodecon->mask = (struct cil_ipaddr*)mask_datum;
   1805 	}
   1806 
   1807 	if (nodecon->context_str != NULL) {
   1808 		rc = cil_resolve_name(current, nodecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1809 		if (rc != SEPOL_OK) {
   1810 			goto exit;
   1811 		}
   1812 		nodecon->context = (struct cil_context*)context_datum;
   1813 	} else {
   1814 		rc = cil_resolve_context(current, nodecon->context, extra_args);
   1815 		if (rc != SEPOL_OK) {
   1816 			goto exit;
   1817 		}
   1818 	}
   1819 
   1820 	if (nodecon->addr->family != nodecon->mask->family) {
   1821 		cil_log(CIL_ERR, "Nodecon ip address not in the same family\n");
   1822 		rc = SEPOL_ERR;
   1823 		goto exit;
   1824 	}
   1825 
   1826 
   1827 	return SEPOL_OK;
   1828 
   1829 exit:
   1830 	return rc;
   1831 }
   1832 
   1833 int cil_resolve_netifcon(struct cil_tree_node *current, void *extra_args)
   1834 {
   1835 	struct cil_netifcon *netifcon = current->data;
   1836 	struct cil_symtab_datum *ifcon_datum = NULL;
   1837 	struct cil_symtab_datum *packcon_datum = NULL;
   1838 
   1839 	int rc = SEPOL_ERR;
   1840 
   1841 	if (netifcon->if_context_str != NULL) {
   1842 		rc = cil_resolve_name(current, netifcon->if_context_str, CIL_SYM_CONTEXTS, extra_args, &ifcon_datum);
   1843 		if (rc != SEPOL_OK) {
   1844 			goto exit;
   1845 		}
   1846 		netifcon->if_context = (struct cil_context*)ifcon_datum;
   1847 	} else {
   1848 		rc = cil_resolve_context(current, netifcon->if_context, extra_args);
   1849 		if (rc != SEPOL_OK) {
   1850 			goto exit;
   1851 		}
   1852 	}
   1853 
   1854 	if (netifcon->packet_context_str != NULL) {
   1855 		rc = cil_resolve_name(current, netifcon->packet_context_str, CIL_SYM_CONTEXTS, extra_args, &packcon_datum);
   1856 		if (rc != SEPOL_OK) {
   1857 			goto exit;
   1858 		}
   1859 		netifcon->packet_context = (struct cil_context*)packcon_datum;
   1860 	} else {
   1861 		rc = cil_resolve_context(current, netifcon->packet_context, extra_args);
   1862 		if (rc != SEPOL_OK) {
   1863 			goto exit;
   1864 		}
   1865 	}
   1866 	return SEPOL_OK;
   1867 
   1868 exit:
   1869 	return rc;
   1870 }
   1871 
   1872 int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args)
   1873 {
   1874 	struct cil_pirqcon *pirqcon = current->data;
   1875 	struct cil_symtab_datum *context_datum = NULL;
   1876 	int rc = SEPOL_ERR;
   1877 
   1878 	if (pirqcon->context_str != NULL) {
   1879 		rc = cil_resolve_name(current, pirqcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1880 		if (rc != SEPOL_OK) {
   1881 			goto exit;
   1882 		}
   1883 		pirqcon->context = (struct cil_context*)context_datum;
   1884 	} else {
   1885 		rc = cil_resolve_context(current, pirqcon->context, extra_args);
   1886 		if (rc != SEPOL_OK) {
   1887 			goto exit;
   1888 		}
   1889 	}
   1890 
   1891 	return SEPOL_OK;
   1892 
   1893 exit:
   1894 	return rc;
   1895 }
   1896 
   1897 int cil_resolve_iomemcon(struct cil_tree_node *current, void *extra_args)
   1898 {
   1899 	struct cil_iomemcon *iomemcon = current->data;
   1900 	struct cil_symtab_datum *context_datum = NULL;
   1901 	int rc = SEPOL_ERR;
   1902 
   1903 	if (iomemcon->context_str != NULL) {
   1904 		rc = cil_resolve_name(current, iomemcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1905 		if (rc != SEPOL_OK) {
   1906 			goto exit;
   1907 		}
   1908 		iomemcon->context = (struct cil_context*)context_datum;
   1909 	} else {
   1910 		rc = cil_resolve_context(current, iomemcon->context, extra_args);
   1911 		if (rc != SEPOL_OK) {
   1912 			goto exit;
   1913 		}
   1914 	}
   1915 
   1916 	return SEPOL_OK;
   1917 
   1918 exit:
   1919 	return rc;
   1920 }
   1921 
   1922 int cil_resolve_ioportcon(struct cil_tree_node *current, void *extra_args)
   1923 {
   1924 	struct cil_ioportcon *ioportcon = current->data;
   1925 	struct cil_symtab_datum *context_datum = NULL;
   1926 	int rc = SEPOL_ERR;
   1927 
   1928 	if (ioportcon->context_str != NULL) {
   1929 		rc = cil_resolve_name(current, ioportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1930 		if (rc != SEPOL_OK) {
   1931 			goto exit;
   1932 		}
   1933 		ioportcon->context = (struct cil_context*)context_datum;
   1934 	} else {
   1935 		rc = cil_resolve_context(current, ioportcon->context, extra_args);
   1936 		if (rc != SEPOL_OK) {
   1937 			goto exit;
   1938 		}
   1939 	}
   1940 
   1941 	return SEPOL_OK;
   1942 
   1943 exit:
   1944 	return rc;
   1945 }
   1946 
   1947 int cil_resolve_pcidevicecon(struct cil_tree_node *current, void *extra_args)
   1948 {
   1949 	struct cil_pcidevicecon *pcidevicecon = current->data;
   1950 	struct cil_symtab_datum *context_datum = NULL;
   1951 	int rc = SEPOL_ERR;
   1952 
   1953 	if (pcidevicecon->context_str != NULL) {
   1954 		rc = cil_resolve_name(current, pcidevicecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1955 		if (rc != SEPOL_OK) {
   1956 			goto exit;
   1957 		}
   1958 		pcidevicecon->context = (struct cil_context*)context_datum;
   1959 	} else {
   1960 		rc = cil_resolve_context(current, pcidevicecon->context, extra_args);
   1961 		if (rc != SEPOL_OK) {
   1962 			goto exit;
   1963 		}
   1964 	}
   1965 
   1966 	return SEPOL_OK;
   1967 
   1968 exit:
   1969 	return rc;
   1970 }
   1971 
   1972 int cil_resolve_devicetreecon(struct cil_tree_node *current, void *extra_args)
   1973 {
   1974 	struct cil_devicetreecon *devicetreecon = current->data;
   1975 	struct cil_symtab_datum *context_datum = NULL;
   1976 	int rc = SEPOL_ERR;
   1977 
   1978 	if (devicetreecon->context_str != NULL) {
   1979 		rc = cil_resolve_name(current, devicetreecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   1980 		if (rc != SEPOL_OK) {
   1981 			goto exit;
   1982 		}
   1983 		devicetreecon->context = (struct cil_context*)context_datum;
   1984 	} else {
   1985 		rc = cil_resolve_context(current, devicetreecon->context, extra_args);
   1986 		if (rc != SEPOL_OK) {
   1987 			goto exit;
   1988 		}
   1989 	}
   1990 
   1991 	return SEPOL_OK;
   1992 
   1993 exit:
   1994 	return rc;
   1995 }
   1996 
   1997 int cil_resolve_fsuse(struct cil_tree_node *current, void *extra_args)
   1998 {
   1999 	struct cil_fsuse *fsuse = current->data;
   2000 	struct cil_symtab_datum *context_datum = NULL;
   2001 	int rc = SEPOL_ERR;
   2002 
   2003 	if (fsuse->context_str != NULL) {
   2004 		rc = cil_resolve_name(current, fsuse->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   2005 		if (rc != SEPOL_OK) {
   2006 			goto exit;
   2007 		}
   2008 		fsuse->context = (struct cil_context*)context_datum;
   2009 	} else {
   2010 		rc = cil_resolve_context(current, fsuse->context, extra_args);
   2011 		if (rc != SEPOL_OK) {
   2012 			goto exit;
   2013 		}
   2014 	}
   2015 
   2016 	return SEPOL_OK;
   2017 
   2018 exit:
   2019 	return rc;
   2020 }
   2021 
   2022 int cil_resolve_sidcontext(struct cil_tree_node *current, void *extra_args)
   2023 {
   2024 	struct cil_sidcontext *sidcon = current->data;
   2025 	struct cil_symtab_datum *sid_datum = NULL;
   2026 	struct cil_symtab_datum *context_datum = NULL;
   2027 	struct cil_sid *sid = NULL;
   2028 
   2029 	int rc = SEPOL_ERR;
   2030 
   2031 	rc = cil_resolve_name(current, sidcon->sid_str, CIL_SYM_SIDS, extra_args, &sid_datum);
   2032 	if (rc != SEPOL_OK) {
   2033 		goto exit;
   2034 	}
   2035 	sid = (struct cil_sid*)sid_datum;
   2036 
   2037 	if (sidcon->context_str != NULL) {
   2038 		rc = cil_resolve_name(current, sidcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
   2039 		if (rc != SEPOL_OK) {
   2040 			goto exit;
   2041 		}
   2042 		sidcon->context = (struct cil_context*)context_datum;
   2043 	} else if (sidcon->context != NULL) {
   2044 		rc = cil_resolve_context(current, sidcon->context, extra_args);
   2045 		if (rc != SEPOL_OK) {
   2046 			goto exit;
   2047 		}
   2048 	}
   2049 
   2050 	if (sid->context != NULL) {
   2051 		cil_log(CIL_ERR, "sid's cannot be associated with more than one context\n");
   2052 		rc = SEPOL_ERR;
   2053 		goto exit;
   2054 	}
   2055 
   2056 	sid->context = sidcon->context;
   2057 
   2058 	return SEPOL_OK;
   2059 
   2060 exit:
   2061 	return rc;
   2062 }
   2063 
   2064 int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args)
   2065 {
   2066 	struct cil_blockinherit *inherit = current->data;
   2067 	struct cil_symtab_datum *block_datum = NULL;
   2068 	struct cil_tree_node *node = NULL;
   2069 	int rc = SEPOL_ERR;
   2070 
   2071 	rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
   2072 	if (rc != SEPOL_OK) {
   2073 		goto exit;
   2074 	}
   2075 
   2076 	node = block_datum->nodes->head->data;
   2077 
   2078 	if (node->flavor != CIL_BLOCK) {
   2079 		cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node));
   2080 		rc = SEPOL_ERR;
   2081 		goto exit;
   2082 	}
   2083 
   2084 	inherit->block = (struct cil_block *)block_datum;
   2085 
   2086 	if (inherit->block->bi_nodes == NULL) {
   2087 		cil_list_init(&inherit->block->bi_nodes, CIL_NODE);
   2088 	}
   2089 	cil_list_append(inherit->block->bi_nodes, CIL_NODE, current);
   2090 
   2091 	return SEPOL_OK;
   2092 
   2093 exit:
   2094 	return rc;
   2095 }
   2096 
   2097 int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args)
   2098 {
   2099 	struct cil_block *block = current->data;
   2100 	struct cil_args_resolve *args = extra_args;
   2101 	struct cil_db *db = NULL;
   2102 	struct cil_list_item *item = NULL;
   2103 	int rc = SEPOL_ERR;
   2104 
   2105 	// This block is not inherited
   2106 	if (block->bi_nodes == NULL) {
   2107 		rc = SEPOL_OK;
   2108 		goto exit;
   2109 	}
   2110 
   2111 	db = args->db;
   2112 
   2113 	// Make sure this is the original block and not a merged block from a blockinherit
   2114 	if (current != block->datum.nodes->head->data) {
   2115 		rc = SEPOL_OK;
   2116 		goto exit;
   2117 	}
   2118 
   2119 	cil_list_for_each(item, block->bi_nodes) {
   2120 		rc = cil_copy_ast(db, current, item->data);
   2121 		if (rc != SEPOL_OK) {
   2122 			cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n");
   2123 			goto exit;
   2124 		}
   2125 	}
   2126 
   2127 	return SEPOL_OK;
   2128 
   2129 exit:
   2130 	return rc;
   2131 }
   2132 
   2133 int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args)
   2134 {
   2135 	struct cil_blockabstract *abstract = current->data;
   2136 	struct cil_symtab_datum *block_datum = NULL;
   2137 	struct cil_tree_node *block_node = NULL;
   2138 	int rc = SEPOL_ERR;
   2139 
   2140 	rc = cil_resolve_name(current, abstract->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
   2141 	if (rc != SEPOL_OK) {
   2142 		goto exit;
   2143 	}
   2144 
   2145 	block_node = block_datum->nodes->head->data;
   2146 	if (block_node->flavor != CIL_BLOCK) {
   2147 		cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc);
   2148 		goto exit;
   2149 	}
   2150 
   2151 	((struct cil_block*)block_datum)->is_abstract = CIL_TRUE;
   2152 
   2153 	return SEPOL_OK;
   2154 
   2155 exit:
   2156 	return rc;
   2157 }
   2158 
   2159 int cil_resolve_in(struct cil_tree_node *current, void *extra_args)
   2160 {
   2161 	struct cil_in *in = current->data;
   2162 	struct cil_args_resolve *args = extra_args;
   2163 	struct cil_db *db = NULL;
   2164 	struct cil_symtab_datum *block_datum = NULL;
   2165 	struct cil_tree_node *block_node = NULL;
   2166 	int rc = SEPOL_ERR;
   2167 
   2168 	if (args != NULL) {
   2169 		db = args->db;
   2170 	}
   2171 
   2172 	rc = cil_resolve_name(current, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
   2173 	if (rc != SEPOL_OK) {
   2174 		goto exit;
   2175 	}
   2176 
   2177 	block_node = block_datum->nodes->head->data;
   2178 
   2179 	rc = cil_copy_ast(db, current, block_node);
   2180 	if (rc != SEPOL_OK) {
   2181 		printf("Failed to copy in, rc: %d\n", rc);
   2182 		goto exit;
   2183 	}
   2184 
   2185 	cil_tree_children_destroy(current);
   2186 	current->cl_head = NULL;
   2187 	current->cl_tail = NULL;
   2188 
   2189 	return SEPOL_OK;
   2190 
   2191 exit:
   2192 	return rc;
   2193 }
   2194 
   2195 int cil_resolve_in_list(void *extra_args)
   2196 {
   2197 	struct cil_args_resolve *args = extra_args;
   2198 	struct cil_list *ins = args->in_list;
   2199 	struct cil_list_item *curr = NULL;
   2200 	struct cil_tree_node *node = NULL;
   2201 	struct cil_tree_node *last_failed_node = NULL;
   2202 	struct cil_in *in = NULL;
   2203 	struct cil_symtab_datum *block_datum = NULL;
   2204 	int resolved = 0;
   2205 	int unresolved = 0;
   2206 	int rc = SEPOL_ERR;
   2207 
   2208 	do {
   2209 		resolved = 0;
   2210 		unresolved = 0;
   2211 
   2212 		cil_list_for_each(curr, ins) {
   2213 			if (curr->flavor != CIL_NODE) {
   2214 				continue;
   2215 			}
   2216 
   2217 			node = curr->data;
   2218 			in = node->data;
   2219 
   2220 			rc = cil_resolve_name(node, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
   2221 			if (rc != SEPOL_OK) {
   2222 				unresolved++;
   2223 				last_failed_node = node;
   2224 			} else {
   2225 				rc = cil_resolve_in(node, extra_args);
   2226 				if (rc != SEPOL_OK) {
   2227 					goto exit;
   2228 				}
   2229 
   2230 				resolved++;
   2231 				curr->data = NULL;
   2232 				curr->flavor = CIL_NONE;
   2233 			}
   2234 		}
   2235 
   2236 		if (unresolved > 0 && resolved == 0) {
   2237 			cil_log(CIL_ERR, "Failed to resolve in-statement on line %d of %s\n", last_failed_node->line, last_failed_node->path);
   2238 			rc = SEPOL_ERR;
   2239 			goto exit;
   2240 		}
   2241 
   2242 	} while (unresolved > 0);
   2243 
   2244 	rc = SEPOL_OK;
   2245 
   2246 exit:
   2247 	return rc;
   2248 }
   2249 
   2250 
   2251 int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor)
   2252 {
   2253 	int rc = SEPOL_ERR;
   2254 	struct cil_bounds *bounds = current->data;
   2255 	enum cil_sym_index index;
   2256 	struct cil_symtab_datum *parent_datum = NULL;
   2257 	struct cil_symtab_datum *child_datum = NULL;
   2258 
   2259 	rc = cil_flavor_to_symtab_index(flavor, &index);
   2260 	if (rc != SEPOL_OK) {
   2261 		goto exit;
   2262 	}
   2263 
   2264 	rc = cil_resolve_name(current, bounds->parent_str, index, extra_args, &parent_datum);
   2265 	if (rc != SEPOL_OK) {
   2266 		goto exit;
   2267 	}
   2268 
   2269 	rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum);
   2270 	if (rc != SEPOL_OK) {
   2271 		goto exit;
   2272 	}
   2273 
   2274 	switch (flavor) {
   2275 	case CIL_USER: {
   2276 		struct cil_user *user = (struct cil_user *)child_datum;
   2277 
   2278 		if (user->bounds != NULL) {
   2279 			struct cil_tree_node *node = user->bounds->datum.nodes->head->data;
   2280 			cil_log(CIL_ERR, "User %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path);
   2281 			rc = SEPOL_ERR;
   2282 			goto exit;
   2283 		}
   2284 
   2285 		user->bounds = (struct cil_user *)parent_datum;
   2286 		break;
   2287 	}
   2288 	case CIL_ROLE: {
   2289 		struct cil_role *role = (struct cil_role *)child_datum;
   2290 
   2291 		if (role->bounds != NULL) {
   2292 			struct cil_tree_node *node = role->bounds->datum.nodes->head->data;
   2293 			cil_log(CIL_ERR, "Role %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path);
   2294 			rc = SEPOL_ERR;
   2295 			goto exit;
   2296 		}
   2297 
   2298 		role->bounds = (struct cil_role *)parent_datum;
   2299 		break;
   2300 	}
   2301 	case CIL_TYPE: {
   2302 		struct cil_type *type = (struct cil_type *)child_datum;
   2303 		struct cil_tree_node *node = NULL;
   2304 
   2305 		if (type->bounds != NULL) {
   2306 			node = ((struct cil_symtab_datum *)type->bounds)->nodes->head->data;
   2307 			cil_log(CIL_ERR, "Type %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path);
   2308 			cil_log(CIL_ERR, "Now being bound to parent %s at line %u of %s\n", bounds->parent_str, current->line, current->path);
   2309 			rc = SEPOL_ERR;
   2310 			goto exit;
   2311 		}
   2312 
   2313 		node = parent_datum->nodes->head->data;
   2314 		if (node->flavor == CIL_TYPEATTRIBUTE) {
   2315 			cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
   2316 			rc = SEPOL_ERR;
   2317 			goto exit;
   2318 		}
   2319 
   2320 		node = child_datum->nodes->head->data;
   2321 		if (node->flavor == CIL_TYPEATTRIBUTE) {
   2322 			cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
   2323 			rc = SEPOL_ERR;
   2324 			goto exit;
   2325 		}
   2326 
   2327 		type->bounds = (struct cil_type *)parent_datum;
   2328 		break;
   2329 	}
   2330 	default:
   2331 		break;
   2332 	}
   2333 
   2334 	return SEPOL_OK;
   2335 
   2336 exit:
   2337 	cil_log(CIL_ERR, "Bad bounds statement at line %u of %s\n", current->line, current->path);
   2338 	return rc;
   2339 }
   2340 
   2341 int cil_resolve_default(struct cil_tree_node *current, void *extra_args)
   2342 {
   2343 	int rc = SEPOL_ERR;
   2344 	struct cil_default *def = current->data;
   2345 	struct cil_list_item *curr;
   2346 	struct cil_symtab_datum *datum;
   2347 
   2348 	cil_list_init(&def->class_datums, def->flavor);
   2349 
   2350 	cil_list_for_each(curr, def->class_strs) {
   2351 		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
   2352 		if (rc != SEPOL_OK) {
   2353 			cil_log(CIL_ERR, "Failed to resolve class %s in %s\n", (char *)curr->data, cil_node_to_string(current));
   2354 			goto exit;
   2355 		}
   2356 		cil_list_append(def->class_datums, CIL_CLASS, datum);
   2357 	}
   2358 
   2359 	return SEPOL_OK;
   2360 
   2361 exit:
   2362 	return rc;
   2363 }
   2364 
   2365 int cil_resolve_defaultrange(struct cil_tree_node *current, void *extra_args)
   2366 {
   2367 	int rc = SEPOL_ERR;
   2368 	struct cil_defaultrange *def = current->data;
   2369 	struct cil_list_item *curr;
   2370 	struct cil_symtab_datum *datum;
   2371 
   2372 	cil_list_init(&def->class_datums, CIL_DEFAULTRANGE);
   2373 
   2374 	cil_list_for_each(curr, def->class_strs) {
   2375 		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
   2376 		if (rc != SEPOL_OK) {
   2377 			cil_log(CIL_ERR, "Failed to resolve class %s in defaultrange\n", (char *)curr->data);
   2378 			goto exit;
   2379 		}
   2380 		cil_list_append(def->class_datums, CIL_CLASS, datum);
   2381 	}
   2382 
   2383 	return SEPOL_OK;
   2384 
   2385 exit:
   2386 	return rc;
   2387 }
   2388 
   2389 int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
   2390 {
   2391 	struct cil_call *new_call = current->data;
   2392 	struct cil_args_resolve *args = extra_args;
   2393 	struct cil_db *db = NULL;
   2394 	struct cil_tree_node *macro_node = NULL;
   2395 	struct cil_symtab_datum *macro_datum = NULL;
   2396 	int rc = SEPOL_ERR;
   2397 
   2398 	if (args != NULL) {
   2399 		db = args->db;
   2400 	}
   2401 
   2402 	rc = cil_resolve_name(current, new_call->macro_str, CIL_SYM_BLOCKS, extra_args, &macro_datum);
   2403 	if (rc != SEPOL_OK) {
   2404 		goto exit;
   2405 	}
   2406 
   2407 	macro_node = macro_datum->nodes->head->data;
   2408 
   2409 	if (macro_node->flavor != CIL_MACRO) {
   2410 		printf("Failed to resolve macro %s\n", new_call->macro_str);
   2411 		rc = SEPOL_ERR;
   2412 		goto exit;
   2413 	}
   2414 	new_call->macro = (struct cil_macro*)macro_datum;
   2415 
   2416 	if (new_call->macro->params != NULL ) {
   2417 
   2418 		struct cil_list_item *item;
   2419 		struct cil_args *new_arg = NULL;
   2420 		struct cil_tree_node *pc = NULL;
   2421 
   2422 		if (new_call->args_tree == NULL) {
   2423 			cil_log(CIL_ERR, "Missing arguments (%s, line: %d)\n", current->path, current->line);
   2424 			rc = SEPOL_ERR;
   2425 			goto exit;
   2426 		}
   2427 
   2428 		pc = new_call->args_tree->root->cl_head;
   2429 
   2430 		cil_list_init(&new_call->args, CIL_LIST_ITEM);
   2431 
   2432 		cil_list_for_each(item, new_call->macro->params) {
   2433 			enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
   2434 
   2435 			if (pc == NULL) {
   2436 				cil_log(CIL_ERR, "Missing arguments (%s, line: %d)\n", current->path, current->line);
   2437 				rc = SEPOL_ERR;
   2438 				goto exit;
   2439 			}
   2440 			if (item->flavor != CIL_PARAM) {
   2441 				rc = SEPOL_ERR;
   2442 				goto exit;
   2443 			}
   2444 
   2445 			cil_args_init(&new_arg);
   2446 
   2447 			switch (flavor) {
   2448 			case CIL_NAME: {
   2449 				struct cil_name *name;
   2450 				name = __cil_insert_name(args->db, pc->data, current);
   2451 				if (name != NULL) {
   2452 					new_arg->arg = (struct cil_symtab_datum *)name;
   2453 				} else {
   2454 					new_arg->arg_str = pc->data;
   2455 				}
   2456 			}
   2457 				break;
   2458 			case CIL_TYPE:
   2459 				new_arg->arg_str = pc->data;
   2460 				break;
   2461 			case CIL_ROLE:
   2462 				new_arg->arg_str = pc->data;
   2463 				break;
   2464 			case CIL_USER:
   2465 				new_arg->arg_str = pc->data;
   2466 				break;
   2467 			case CIL_SENS:
   2468 				new_arg->arg_str = pc->data;
   2469 				break;
   2470 			case CIL_CAT:
   2471 				new_arg->arg_str = pc->data;
   2472 				break;
   2473 			case CIL_BOOL:
   2474 				new_arg->arg_str = pc->data;
   2475 				break;
   2476 			case CIL_CATSET: {
   2477 				if (pc->cl_head != NULL) {
   2478 					struct cil_catset *catset = NULL;
   2479 					struct cil_tree_node *cat_node = NULL;
   2480 					cil_catset_init(&catset);
   2481 					rc = cil_fill_cats(pc, &catset->cats);
   2482 					if (rc != SEPOL_OK) {
   2483 						cil_destroy_catset(catset);
   2484 						goto exit;
   2485 					}
   2486 					cil_tree_node_init(&cat_node);
   2487 					cat_node->flavor = CIL_CATSET;
   2488 					cat_node->data = catset;
   2489 					cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
   2490 									CIL_LIST_ITEM, cat_node);
   2491 					new_arg->arg = (struct cil_symtab_datum*)catset;
   2492 				} else {
   2493 					new_arg->arg_str = pc->data;
   2494 				}
   2495 
   2496 				break;
   2497 			}
   2498 			case CIL_LEVEL: {
   2499 				if (pc->cl_head != NULL) {
   2500 					struct cil_level *level = NULL;
   2501 					struct cil_tree_node *lvl_node = NULL;
   2502 					cil_level_init(&level);
   2503 
   2504 					rc = cil_fill_level(pc->cl_head, level);
   2505 					if (rc != SEPOL_OK) {
   2506 						cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
   2507 						cil_destroy_level(level);
   2508 						goto exit;
   2509 					}
   2510 					cil_tree_node_init(&lvl_node);
   2511 					lvl_node->flavor = CIL_LEVEL;
   2512 					lvl_node->data = level;
   2513 					cil_list_append(((struct cil_symtab_datum*)level)->nodes,
   2514 									CIL_LIST_ITEM, lvl_node);
   2515 					new_arg->arg = (struct cil_symtab_datum*)level;
   2516 				} else {
   2517 					new_arg->arg_str = pc->data;
   2518 				}
   2519 
   2520 				break;
   2521 			}
   2522 			case CIL_LEVELRANGE: {
   2523 				if (pc->cl_head != NULL) {
   2524 					struct cil_levelrange *range = NULL;
   2525 					struct cil_tree_node *range_node = NULL;
   2526 					cil_levelrange_init(&range);
   2527 
   2528 					rc = cil_fill_levelrange(pc->cl_head, range);
   2529 					if (rc != SEPOL_OK) {
   2530 						cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
   2531 						cil_destroy_levelrange(range);
   2532 						goto exit;
   2533 					}
   2534 					cil_tree_node_init(&range_node);
   2535 					range_node->flavor = CIL_LEVELRANGE;
   2536 					range_node->data = range;
   2537 					cil_list_append(((struct cil_symtab_datum*)range)->nodes,
   2538 									CIL_LIST_ITEM, range_node);
   2539 					new_arg->arg = (struct cil_symtab_datum*)range;
   2540 				} else {
   2541 					new_arg->arg_str = pc->data;
   2542 				}
   2543 
   2544 				break;
   2545 			}
   2546 			case CIL_IPADDR: {
   2547 				if (pc->cl_head != NULL) {
   2548 					struct cil_ipaddr *ipaddr = NULL;
   2549 					struct cil_tree_node *addr_node = NULL;
   2550 					cil_ipaddr_init(&ipaddr);
   2551 
   2552 					rc = cil_fill_ipaddr(pc->cl_head, ipaddr);
   2553 					if (rc != SEPOL_OK) {
   2554 						cil_log(CIL_ERR, "Failed to create anonymous ip address, rc; %d\n", rc);
   2555 						cil_destroy_ipaddr(ipaddr);
   2556 						goto exit;
   2557 					}
   2558 					cil_tree_node_init(&addr_node);
   2559 					addr_node->flavor = CIL_IPADDR;
   2560 					addr_node->data = ipaddr;
   2561 					cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes,
   2562 									CIL_LIST_ITEM, addr_node);
   2563 					new_arg->arg = (struct cil_symtab_datum*)ipaddr;
   2564 				} else {
   2565 					new_arg->arg_str = pc->data;
   2566 				}
   2567 
   2568 				break;
   2569 			}
   2570 			case CIL_CLASS:
   2571 				new_arg->arg_str = pc->data;
   2572 				break;
   2573 			case CIL_MAP_CLASS:
   2574 				new_arg->arg_str = pc->data;
   2575 				break;
   2576 			case CIL_CLASSPERMISSION: {
   2577 				if (pc->cl_head != NULL) {
   2578 					struct cil_classpermission *cp = NULL;
   2579 					struct cil_tree_node *cp_node = NULL;
   2580 
   2581 					cil_classpermission_init(&cp);
   2582 					rc = cil_fill_classperms_list(pc, &cp->classperms);
   2583 					if (rc != SEPOL_OK) {
   2584 						cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
   2585 						cil_destroy_classpermission(cp);
   2586 						goto exit;
   2587 					}
   2588 					cil_tree_node_init(&cp_node);
   2589 					cp_node->flavor = CIL_CLASSPERMISSION;
   2590 					cp_node->data = cp;
   2591 					cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
   2592 					new_arg->arg = (struct cil_symtab_datum*)cp;
   2593 				} else {
   2594 					new_arg->arg_str = pc->data;
   2595 				}
   2596 				break;
   2597 			}
   2598 			default:
   2599 				cil_log(CIL_ERR, "Unexpected flavor: %d\n",
   2600 						(((struct cil_param*)item->data)->flavor));
   2601 				rc = SEPOL_ERR;
   2602 				goto exit;
   2603 			}
   2604 			new_arg->param_str = ((struct cil_param*)item->data)->str;
   2605 			new_arg->flavor = flavor;
   2606 
   2607 			cil_list_append(new_call->args, CIL_ARGS, new_arg);
   2608 
   2609 			pc = pc->next;
   2610 		}
   2611 
   2612 		if (pc != NULL) {
   2613 			cil_log(CIL_ERR, "Unexpected arguments (%s, line: %d)\n", current->path, current->line);
   2614 			rc = SEPOL_ERR;
   2615 			goto exit;
   2616 		}
   2617 	} else if (new_call->args_tree != NULL) {
   2618 		cil_log(CIL_ERR, "Unexpected arguments (%s, line: %d)\n", current->path, current->line);
   2619 		rc = SEPOL_ERR;
   2620 		goto exit;
   2621 	}
   2622 
   2623 	if (new_call->copied == 0) {
   2624 		new_call->copied = 1;
   2625 		rc = cil_copy_ast(db, macro_node, current);
   2626 		if (rc != SEPOL_OK) {
   2627 			cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc);
   2628 			goto exit;
   2629 		}
   2630 	}
   2631 
   2632 	return SEPOL_OK;
   2633 
   2634 exit:
   2635 	return rc;
   2636 }
   2637 
   2638 int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
   2639 {
   2640 	struct cil_call *new_call = current->data;
   2641 	int rc = SEPOL_ERR;
   2642 	enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
   2643 	struct cil_list_item *item;
   2644 
   2645 	if (new_call->args == NULL) {
   2646 		rc = SEPOL_OK;
   2647 		goto exit;
   2648 	}
   2649 
   2650 	cil_list_for_each(item, new_call->args) {
   2651 		struct cil_args *arg = item->data;
   2652 		if (arg->arg == NULL && arg->arg_str == NULL) {
   2653 			cil_log(CIL_ERR, "Arguments not created correctly\n");
   2654 			rc = SEPOL_ERR;
   2655 			goto exit;
   2656 		}
   2657 
   2658 		switch (arg->flavor) {
   2659 		case CIL_NAME:
   2660 			if (arg->arg != NULL) {
   2661 				continue; /* No need to resolve */
   2662 			} else {
   2663 				sym_index = CIL_SYM_NAMES;
   2664 			}
   2665 			break;
   2666 		case CIL_LEVEL:
   2667 			if (arg->arg_str == NULL && arg->arg != NULL) {
   2668 				continue; // anonymous, no need to resolve
   2669 			} else {
   2670 				sym_index = CIL_SYM_LEVELS;
   2671 			}
   2672 			break;
   2673 		case CIL_LEVELRANGE:
   2674 			if (arg->arg_str == NULL && arg->arg != NULL) {
   2675 				continue; // anonymous, no need to resolve
   2676 			} else {
   2677 				sym_index = CIL_SYM_LEVELRANGES;
   2678 			}
   2679 			break;
   2680 		case CIL_CATSET:
   2681 			if (arg->arg_str == NULL && arg->arg != NULL) {
   2682 				continue; // anonymous, no need to resolve
   2683 			} else {
   2684 				sym_index = CIL_SYM_CATS;
   2685 			}
   2686 			break;
   2687 		case CIL_IPADDR:
   2688 			if (arg->arg_str == NULL && arg->arg != NULL) {
   2689 				continue; // anonymous, no need to resolve
   2690 			} else {
   2691 				sym_index = CIL_SYM_IPADDRS;
   2692 			}
   2693 			break;
   2694 		case CIL_CLASSPERMISSION:
   2695 			if (arg->arg_str == NULL && arg->arg != NULL) {
   2696 				continue;
   2697 			} else {
   2698 				sym_index = CIL_SYM_CLASSPERMSETS;
   2699 			}
   2700 			break;
   2701 		case CIL_TYPE:
   2702 			if (arg->arg_str == NULL && arg->arg != NULL) {
   2703 				continue; // anonymous, no need to resolve
   2704 			} else {
   2705 				sym_index = CIL_SYM_TYPES;
   2706 			}
   2707 			break;
   2708 		case CIL_ROLE:
   2709 			sym_index = CIL_SYM_ROLES;
   2710 			break;
   2711 		case CIL_USER:
   2712 			sym_index = CIL_SYM_USERS;
   2713 			break;
   2714 		case CIL_SENS:
   2715 			sym_index = CIL_SYM_SENS;
   2716 			break;
   2717 		case CIL_CAT:
   2718 			sym_index = CIL_SYM_CATS;
   2719 			break;
   2720 		case CIL_CLASS:
   2721 		case CIL_MAP_CLASS:
   2722 			sym_index = CIL_SYM_CLASSES;
   2723 			break;
   2724 		case CIL_BOOL:
   2725 			sym_index = CIL_SYM_BOOLS;
   2726 			break;
   2727 		default:
   2728 			rc = SEPOL_ERR;
   2729 			goto exit;
   2730 		}
   2731 
   2732 		if (sym_index != CIL_SYM_UNKNOWN) {
   2733 			rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
   2734 			if (rc != SEPOL_OK) {
   2735 				goto exit;
   2736 			}
   2737 		}
   2738 	}
   2739 
   2740 	return SEPOL_OK;
   2741 
   2742 exit:
   2743 	return rc;
   2744 }
   2745 
   2746 int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
   2747 {
   2748 	struct cil_list_item *item;
   2749 	enum cil_sym_index param_index = CIL_SYM_UNKNOWN;
   2750 	int rc = SEPOL_ERR;
   2751 
   2752 	if (call == NULL || name == NULL) {
   2753 		goto exit;
   2754 	}
   2755 
   2756 	if (call->args == NULL) {
   2757 		goto exit;
   2758 	}
   2759 
   2760 	cil_list_for_each(item, call->args) {
   2761 		struct cil_args * arg = item->data;
   2762 		rc = cil_flavor_to_symtab_index(arg->flavor, &param_index);
   2763 		if (param_index == sym_index) {
   2764 			if (name == arg->param_str) {
   2765 				*datum = arg->arg;
   2766 				rc = SEPOL_OK;
   2767 				goto exit;
   2768 			}
   2769 		}
   2770 	}
   2771 
   2772 	return SEPOL_ERR;
   2773 
   2774 exit:
   2775 	return rc;
   2776 }
   2777 
   2778 int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, void *extra_args)
   2779 {
   2780 	int rc = SEPOL_ERR;
   2781 	struct cil_list_item *curr;
   2782 	struct cil_symtab_datum *res_datum = NULL;
   2783 	enum cil_sym_index sym_index =  CIL_SYM_UNKNOWN;
   2784 
   2785 	switch (str_expr->flavor) {
   2786 	case CIL_BOOL:
   2787 		sym_index = CIL_SYM_BOOLS;
   2788 		break;
   2789 	case CIL_TUNABLE:
   2790 		sym_index = CIL_SYM_TUNABLES;
   2791 		break;
   2792 	case CIL_TYPE:
   2793 		sym_index = CIL_SYM_TYPES;
   2794 		break;
   2795 	case CIL_ROLE:
   2796 		sym_index = CIL_SYM_ROLES;
   2797 		break;
   2798 	case CIL_USER:
   2799 		sym_index = CIL_SYM_USERS;
   2800 		break;
   2801 	case CIL_CAT:
   2802 		sym_index = CIL_SYM_CATS;
   2803 		break;
   2804 	default:
   2805 		break;
   2806 	}
   2807 
   2808 	cil_list_init(datum_expr, str_expr->flavor);
   2809 
   2810 	cil_list_for_each(curr, str_expr) {
   2811 		switch (curr->flavor) {
   2812 		case CIL_STRING:
   2813 			rc = cil_resolve_name(parent, curr->data, sym_index, extra_args, &res_datum);
   2814 			if (rc != SEPOL_OK) {
   2815 				goto exit;
   2816 			}
   2817 
   2818 			if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
   2819 				cil_type_used(res_datum);
   2820 			}
   2821 
   2822 			cil_list_append(*datum_expr, CIL_DATUM, res_datum);
   2823 			break;
   2824 		case CIL_LIST: {
   2825 			struct cil_list *datum_sub_expr;
   2826 			rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args);
   2827 			if (rc != SEPOL_OK) {
   2828 				cil_list_destroy(&datum_sub_expr, CIL_TRUE);
   2829 				goto exit;
   2830 			}
   2831 			cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
   2832 			break;
   2833 		}
   2834 		default:
   2835 			cil_list_append(*datum_expr, curr->flavor, curr->data);
   2836 			break;
   2837 		}
   2838 	}
   2839 	return SEPOL_OK;
   2840 
   2841 exit:
   2842 	return rc;
   2843 }
   2844 
   2845 int cil_resolve_boolif(struct cil_tree_node *current, void *extra_args)
   2846 {
   2847 	int rc = SEPOL_ERR;
   2848 	struct cil_booleanif *bif = (struct cil_booleanif*)current->data;
   2849 
   2850 	rc = cil_resolve_expr(CIL_BOOLEANIF, bif->str_expr, &bif->datum_expr, current, extra_args);
   2851 	if (rc != SEPOL_OK) {
   2852 		goto exit;
   2853 	}
   2854 
   2855 	return SEPOL_OK;
   2856 
   2857 exit:
   2858 	return rc;
   2859 }
   2860 
   2861 static int __cil_evaluate_tunable_expr(struct cil_list_item *curr);
   2862 
   2863 static int __cil_evaluate_tunable_expr_helper(struct cil_list_item *curr)
   2864 {
   2865 	if (curr == NULL) {
   2866 		return CIL_FALSE;
   2867 	} else if (curr->flavor == CIL_DATUM) {
   2868 		struct cil_tunable *tun = curr->data;
   2869 		return tun->value;
   2870 	} else if (curr->flavor == CIL_LIST) {
   2871 		struct cil_list *l = curr->data;
   2872 		return __cil_evaluate_tunable_expr(l->head);
   2873 	} else {
   2874 		return CIL_FALSE;
   2875 	}
   2876 }
   2877 
   2878 static int __cil_evaluate_tunable_expr(struct cil_list_item *curr)
   2879 {
   2880 	/* Assumes expression is well-formed */
   2881 
   2882 	if (curr == NULL) {
   2883 		return CIL_FALSE;
   2884 	} else if (curr->flavor == CIL_OP) {
   2885 		uint16_t v1, v2;
   2886 		enum cil_flavor op_flavor = (enum cil_flavor)curr->data;
   2887 
   2888 		v1 = __cil_evaluate_tunable_expr_helper(curr->next);
   2889 
   2890 		if (op_flavor == CIL_NOT) return !v1;
   2891 
   2892 		v2 = __cil_evaluate_tunable_expr_helper(curr->next->next);
   2893 
   2894 		if (op_flavor == CIL_AND) return (v1 && v2);
   2895 		else if (op_flavor == CIL_OR) return (v1 || v2);
   2896 		else if (op_flavor == CIL_XOR) return (v1 ^ v2);
   2897 		else if (op_flavor == CIL_EQ) return (v1 == v2);
   2898 		else if (op_flavor == CIL_NEQ) return (v1 != v2);
   2899 		else return CIL_FALSE;
   2900 	} else {
   2901 		uint16_t v;
   2902 		for (;curr; curr = curr->next) {
   2903 			v = __cil_evaluate_tunable_expr_helper(curr);
   2904 			if (v) return v;
   2905 		}
   2906 		return CIL_FALSE;
   2907 	}
   2908 }
   2909 
   2910 int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args)
   2911 {
   2912 	struct cil_args_resolve *args = extra_args;
   2913 	struct cil_db *db = NULL;
   2914 	int rc = SEPOL_ERR;
   2915 	struct cil_tunableif *tif = (struct cil_tunableif*)current->data;
   2916 	uint16_t result = CIL_FALSE;
   2917 	struct cil_tree_node *true_node = NULL;
   2918 	struct cil_tree_node *false_node = NULL;
   2919 	struct cil_condblock *cb = NULL;
   2920 
   2921 	if (args != NULL) {
   2922 		db = args->db;
   2923 	}
   2924 
   2925 	rc = cil_resolve_expr(CIL_TUNABLEIF, tif->str_expr, &tif->datum_expr, current, extra_args);
   2926 	if (rc != SEPOL_OK) {
   2927 		goto exit;
   2928 	}
   2929 
   2930 	result = __cil_evaluate_tunable_expr(tif->datum_expr->head);
   2931 
   2932 	if (current->cl_head != NULL && current->cl_head->flavor == CIL_CONDBLOCK) {
   2933 		cb = current->cl_head->data;
   2934 		if (cb->flavor == CIL_CONDTRUE) {
   2935 			true_node = current->cl_head;
   2936 		} else if (cb->flavor == CIL_CONDFALSE) {
   2937 			false_node = current->cl_head;
   2938 		}
   2939 	}
   2940 
   2941 	if (current->cl_head != NULL && current->cl_head->next != NULL && current->cl_head->next->flavor == CIL_CONDBLOCK) {
   2942 		cb = current->cl_head->next->data;
   2943 		if (cb->flavor == CIL_CONDTRUE) {
   2944 			true_node = current->cl_head->next;
   2945 		} else if (cb->flavor == CIL_CONDFALSE) {
   2946 			false_node = current->cl_head->next;
   2947 		}
   2948 	}
   2949 
   2950 	if (result == CIL_TRUE) {
   2951 		if (true_node != NULL) {
   2952 			rc = cil_copy_ast(db, true_node, current->parent);
   2953 			if (rc != SEPOL_OK) {
   2954 				goto exit;
   2955 			}
   2956 		}
   2957 	} else {
   2958 		if (false_node != NULL) {
   2959 			rc = cil_copy_ast(db, false_node, current->parent);
   2960 			if (rc  != SEPOL_OK) {
   2961 				goto exit;
   2962 			}
   2963 		}
   2964 	}
   2965 
   2966 	cil_tree_children_destroy(current);
   2967 	current->cl_head = NULL;
   2968 	current->cl_tail = NULL;
   2969 
   2970 	return SEPOL_OK;
   2971 
   2972 exit:
   2973 	return rc;
   2974 }
   2975 
   2976 
   2977 int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
   2978 {
   2979 	int rc = SEPOL_OK;
   2980 	struct cil_args_resolve *args = extra_args;
   2981 	enum cil_pass pass = 0;
   2982 	struct cil_list *ins = args->in_list;
   2983 
   2984 	if (node == NULL || args == NULL) {
   2985 		goto exit;
   2986 	}
   2987 
   2988 	pass = args->pass;
   2989 	switch (pass) {
   2990 	case CIL_PASS_TIF:
   2991 		if (node->flavor == CIL_TUNABLEIF) {
   2992 			rc = cil_resolve_tunif(node, args);
   2993 		}
   2994 		break;
   2995 	case CIL_PASS_IN:
   2996 		if (node->flavor == CIL_IN) {
   2997 			// due to ordering issues, in statements are just gathered here and
   2998 			// resolved together in cil_resolve_in_list once all are found
   2999 			cil_list_prepend(ins, CIL_NODE, node);
   3000 		}
   3001 		break;
   3002 	case CIL_PASS_BLKIN_LINK:
   3003 		if (node->flavor == CIL_BLOCKINHERIT) {
   3004 			rc = cil_resolve_blockinherit_link(node, args);
   3005 		}
   3006 		break;
   3007 	case CIL_PASS_BLKIN_COPY:
   3008 		if (node->flavor == CIL_BLOCK) {
   3009 			rc = cil_resolve_blockinherit_copy(node, args);
   3010 		}
   3011 		break;
   3012 	case CIL_PASS_BLKABS:
   3013 		if (node->flavor == CIL_BLOCKABSTRACT) {
   3014 			rc = cil_resolve_blockabstract(node, args);
   3015 		}
   3016 		break;
   3017 	case CIL_PASS_MACRO:
   3018 		if (node->flavor == CIL_CALL && args->macro != NULL) {
   3019 			rc = cil_resolve_call1(node, args);
   3020 		}
   3021 		break;
   3022 	case CIL_PASS_CALL1:
   3023 		if (node->flavor == CIL_CALL) {
   3024 			rc = cil_resolve_call1(node, args);
   3025 		}
   3026 		break;
   3027 	case CIL_PASS_CALL2:
   3028 		if (node->flavor == CIL_CALL) {
   3029 			rc = cil_resolve_call2(node, args);
   3030 		}
   3031 		break;
   3032 	case CIL_PASS_ALIAS1:
   3033 		switch (node->flavor) {
   3034 		case CIL_TYPEALIASACTUAL:
   3035 			rc = cil_resolve_aliasactual(node, args, CIL_TYPE);
   3036 			break;
   3037 		case CIL_SENSALIASACTUAL:
   3038 			rc = cil_resolve_aliasactual(node, args, CIL_SENS);
   3039 			break;
   3040 		case CIL_CATALIASACTUAL:
   3041 			rc = cil_resolve_aliasactual(node, args, CIL_CAT);
   3042 			break;
   3043 		default:
   3044 			break;
   3045 		}
   3046 		break;
   3047 	case CIL_PASS_ALIAS2:
   3048 		switch (node->flavor) {
   3049 		case CIL_TYPEALIAS:
   3050 			rc = cil_resolve_alias_to_actual(node, CIL_TYPE);
   3051 			break;
   3052 		case CIL_SENSALIAS:
   3053 			rc = cil_resolve_alias_to_actual(node, CIL_SENS);
   3054 			break;
   3055 		case CIL_CATALIAS:
   3056 			rc = cil_resolve_alias_to_actual(node, CIL_CAT);
   3057 			break;
   3058 		default:
   3059 			break;
   3060 		}
   3061 		break;
   3062 	case CIL_PASS_MISC1:
   3063 		switch (node->flavor) {
   3064 		case CIL_SIDORDER:
   3065 			rc = cil_resolve_sidorder(node, args);
   3066 			break;
   3067 		case CIL_CLASSORDER:
   3068 			rc = cil_resolve_classorder(node, args);
   3069 			break;
   3070 		case CIL_CATORDER:
   3071 			rc = cil_resolve_catorder(node, args);
   3072 			break;
   3073 		case CIL_SENSITIVITYORDER:
   3074 			rc = cil_resolve_sensitivityorder(node, args);
   3075 			break;
   3076 		case CIL_BOOLEANIF:
   3077 			rc = cil_resolve_boolif(node, args);
   3078 			break;
   3079 		default:
   3080 			break;
   3081 		}
   3082 		break;
   3083 	case CIL_PASS_MLS:
   3084 		switch (node->flavor) {
   3085 		case CIL_CATSET:
   3086 			rc = cil_resolve_catset(node, (struct cil_catset*)node->data, args);
   3087 			break;
   3088 		default:
   3089 			break;
   3090 		}
   3091 		break;
   3092 	case CIL_PASS_MISC2:
   3093 		switch (node->flavor) {
   3094 		case CIL_SENSCAT:
   3095 			rc = cil_resolve_senscat(node, args);
   3096 			break;
   3097 		case CIL_CLASSCOMMON:
   3098 			rc = cil_resolve_classcommon(node, args);
   3099 			break;
   3100 		default:
   3101 			break;
   3102 		}
   3103 		break;
   3104 	case CIL_PASS_MISC3:
   3105 		switch (node->flavor) {
   3106 		case CIL_TYPEATTRIBUTESET:
   3107 			rc = cil_resolve_typeattributeset(node, args);
   3108 			break;
   3109 		case CIL_TYPEBOUNDS:
   3110 			rc = cil_resolve_bounds(node, args, CIL_TYPE);
   3111 			break;
   3112 		case CIL_TYPEPERMISSIVE:
   3113 			rc = cil_resolve_typepermissive(node, args);
   3114 			break;
   3115 		case CIL_NAMETYPETRANSITION:
   3116 			rc = cil_resolve_nametypetransition(node, args);
   3117 			break;
   3118 		case CIL_RANGETRANSITION:
   3119 			rc = cil_resolve_rangetransition(node, args);
   3120 			break;
   3121 		case CIL_CLASSPERMISSIONSET:
   3122 			rc = cil_resolve_classpermissionset(node, (struct cil_classpermissionset*)node->data, args);
   3123 			break;
   3124 		case CIL_CLASSMAPPING:
   3125 			rc = cil_resolve_classmapping(node, args);
   3126 			break;
   3127 		case CIL_AVRULE:
   3128 			rc = cil_resolve_avrule(node, args);
   3129 			break;
   3130 		case CIL_TYPE_RULE:
   3131 			rc = cil_resolve_type_rule(node, args);
   3132 			break;
   3133 		case CIL_USERROLE:
   3134 			rc = cil_resolve_userrole(node, args);
   3135 			break;
   3136 		case CIL_USERLEVEL:
   3137 			rc = cil_resolve_userlevel(node, args);
   3138 			break;
   3139 		case CIL_USERRANGE:
   3140 			rc = cil_resolve_userrange(node, args);
   3141 			break;
   3142 		case CIL_USERBOUNDS:
   3143 			rc = cil_resolve_bounds(node, args, CIL_USER);
   3144 			break;
   3145 		case CIL_USERPREFIX:
   3146 			rc = cil_resolve_userprefix(node, args);
   3147 			break;
   3148 		case CIL_SELINUXUSER:
   3149 		case CIL_SELINUXUSERDEFAULT:
   3150 			rc = cil_resolve_selinuxuser(node, args);
   3151 			break;
   3152 		case CIL_ROLEATTRIBUTESET:
   3153 			rc = cil_resolve_roleattributeset(node, args);
   3154 			break;
   3155 		case CIL_ROLETYPE:
   3156 			rc = cil_resolve_roletype(node, args);
   3157 			break;
   3158 		case CIL_ROLETRANSITION:
   3159 			rc = cil_resolve_roletransition(node, args);
   3160 			break;
   3161 		case CIL_ROLEALLOW:
   3162 			rc = cil_resolve_roleallow(node, args);
   3163 			break;
   3164 		case CIL_ROLEBOUNDS:
   3165 			rc = cil_resolve_bounds(node, args, CIL_ROLE);
   3166 			break;
   3167 		case CIL_LEVEL:
   3168 			rc = cil_resolve_level(node, (struct cil_level*)node->data, args);
   3169 			break;
   3170 		case CIL_LEVELRANGE:
   3171 			rc = cil_resolve_levelrange(node, (struct cil_levelrange*)node->data, args);
   3172 			break;
   3173 		case CIL_CONSTRAIN:
   3174 			rc = cil_resolve_constrain(node, args);
   3175 			break;
   3176 		case CIL_MLSCONSTRAIN:
   3177 			rc = cil_resolve_constrain(node, args);
   3178 			break;
   3179 		case CIL_VALIDATETRANS:
   3180 		case CIL_MLSVALIDATETRANS:
   3181 			rc = cil_resolve_validatetrans(node, args);
   3182 			break;
   3183 		case CIL_CONTEXT:
   3184 			rc = cil_resolve_context(node, (struct cil_context*)node->data, args);
   3185 			break;
   3186 		case CIL_FILECON:
   3187 			rc = cil_resolve_filecon(node, args);
   3188 			break;
   3189 		case CIL_PORTCON:
   3190 			rc = cil_resolve_portcon(node, args);
   3191 			break;
   3192 		case CIL_NODECON:
   3193 			rc = cil_resolve_nodecon(node, args);
   3194 			break;
   3195 		case CIL_GENFSCON:
   3196 			rc = cil_resolve_genfscon(node, args);
   3197 			break;
   3198 		case CIL_NETIFCON:
   3199 			rc = cil_resolve_netifcon(node, args);
   3200 			break;
   3201 		case CIL_PIRQCON:
   3202 			rc = cil_resolve_pirqcon(node, args);
   3203 			break;
   3204 		case CIL_IOMEMCON:
   3205 			rc = cil_resolve_iomemcon(node, args);
   3206 			break;
   3207 		case CIL_IOPORTCON:
   3208 			rc = cil_resolve_ioportcon(node, args);
   3209 			break;
   3210 		case CIL_PCIDEVICECON:
   3211 			rc = cil_resolve_pcidevicecon(node, args);
   3212 			break;
   3213 		case CIL_DEVICETREECON:
   3214 			rc = cil_resolve_devicetreecon(node, args);
   3215 			break;
   3216 		case CIL_FSUSE:
   3217 			rc = cil_resolve_fsuse(node, args);
   3218 			break;
   3219 		case CIL_SIDCONTEXT:
   3220 			rc = cil_resolve_sidcontext(node, args);
   3221 			break;
   3222 		case CIL_DEFAULTUSER:
   3223 		case CIL_DEFAULTROLE:
   3224 		case CIL_DEFAULTTYPE:
   3225 			rc = cil_resolve_default(node, args);
   3226 			break;
   3227 		case CIL_DEFAULTRANGE:
   3228 			rc = cil_resolve_defaultrange(node, args);
   3229 			break;
   3230 		default:
   3231 			break;
   3232 		}
   3233 		break;
   3234 	default:
   3235 		break;
   3236 	}
   3237 
   3238 	return rc;
   3239 
   3240 exit:
   3241 	return rc;
   3242 }
   3243 
   3244 int __cil_resolve_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
   3245 {
   3246 	int rc = SEPOL_ERR;
   3247 	struct cil_args_resolve *args = extra_args;
   3248 	enum cil_pass pass = args->pass;
   3249 	struct cil_tree_node *optstack = args->optstack;
   3250 	struct cil_tree_node *boolif = args->boolif;
   3251 
   3252 	if (node == NULL) {
   3253 		goto exit;
   3254 	}
   3255 
   3256 	if (optstack != NULL) {
   3257 		if (node->flavor == CIL_TUNABLE || node->flavor == CIL_MACRO) {
   3258 			/* tuanbles and macros are not allowed in optionals*/
   3259 			cil_log(CIL_ERR, "%s statement is not allowed in optionals (%s:%d)\n", cil_node_to_string(node), node->path, node->line);
   3260 			rc = SEPOL_ERR;
   3261 			goto exit;
   3262 		}
   3263 	}
   3264 
   3265 	if (boolif != NULL) {
   3266 		if (!(node->flavor == CIL_CONDBLOCK ||
   3267 			node->flavor == CIL_AVRULE ||
   3268 			node->flavor == CIL_TYPE_RULE ||
   3269 			node->flavor == CIL_CALL ||
   3270 			node->flavor == CIL_TUNABLEIF ||
   3271 			node->flavor == CIL_NAMETYPETRANSITION)) {
   3272 			if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
   3273 				cil_log(CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif) (%s:%d)\n", cil_node_to_string(node), node->path, node->line);
   3274 			} else {
   3275 				cil_log(CIL_ERR, "%s statement is not allowed in booleanifs (%s:%d)\n", cil_node_to_string(node), node->path, node->line);
   3276 			}
   3277 			rc = SEPOL_ERR;
   3278 			goto exit;
   3279 		}
   3280 	}
   3281 
   3282 	if (node->flavor == CIL_MACRO) {
   3283 		if (pass != CIL_PASS_TIF && pass != CIL_PASS_MACRO) {
   3284 			*finished = CIL_TREE_SKIP_HEAD;
   3285 			rc = SEPOL_OK;
   3286 			goto exit;
   3287 		}
   3288 	}
   3289 
   3290 	if (node->flavor == CIL_BLOCK && ((((struct cil_block*)node->data)->is_abstract == CIL_TRUE) && (pass > CIL_PASS_BLKABS))) {
   3291 		*finished = CIL_TREE_SKIP_HEAD;
   3292 		rc = SEPOL_OK;
   3293 		goto exit;
   3294 	}
   3295 
   3296 	rc = __cil_resolve_ast_node(node, extra_args);
   3297 	if (rc == SEPOL_ENOENT && optstack != NULL) {
   3298 		struct cil_optional *opt = (struct cil_optional *)optstack->data;
   3299 		cil_log(CIL_WARN, "Disabling optional %s at %d of %s\n", opt->datum.name, node->parent->line, node->parent->path);
   3300 		/* disable an optional if something failed to resolve */
   3301 		opt->enabled = CIL_FALSE;
   3302 		rc = SEPOL_OK;
   3303 	} else if (rc != SEPOL_OK) {
   3304 		cil_log(CIL_ERR, "Failed to resolve %s statement at %d of %s\n", cil_node_to_string(node), node->line, node->path);
   3305 		goto exit;
   3306 	}
   3307 
   3308 	return rc;
   3309 
   3310 exit:
   3311 	return rc;
   3312 }
   3313 
   3314 int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *extra_args)
   3315 {
   3316 	int rc = SEPOL_ERR;
   3317 	struct cil_args_resolve *args = extra_args;
   3318 	struct cil_tree_node *callstack = NULL;
   3319 	struct cil_tree_node *optstack = NULL;
   3320 	struct cil_tree_node *parent = NULL;
   3321 
   3322 	if (current == NULL || extra_args == NULL) {
   3323 		goto exit;
   3324 	}
   3325 
   3326 	callstack = args->callstack;
   3327 	optstack = args->optstack;
   3328 	parent = current->parent;
   3329 
   3330 	if (parent->flavor == CIL_CALL || parent->flavor == CIL_OPTIONAL) {
   3331 		/* push this node onto a stack */
   3332 		struct cil_tree_node *new;
   3333 		cil_tree_node_init(&new);
   3334 
   3335 		new->data = parent->data;
   3336 		new->flavor = parent->flavor;
   3337 
   3338 		if (parent->flavor == CIL_CALL) {
   3339 			if (callstack != NULL) {
   3340 				struct cil_tree_node *curr = NULL;
   3341 				struct cil_call *new_call = new->data;
   3342 				for (curr = callstack->cl_head; curr != NULL;
   3343 					curr = curr->cl_head) {
   3344 					struct cil_call *curr_call = curr->data;
   3345 					if (curr_call->macro == new_call->macro) {
   3346 						cil_log(CIL_ERR, "Recursive macro call found\n");
   3347 						rc = SEPOL_ERR;
   3348 						goto exit;
   3349 					}
   3350 				}
   3351 				callstack->parent = new;
   3352 				new->cl_head = callstack;
   3353 			}
   3354 			args->callstack = new;
   3355 		} else if (parent->flavor == CIL_OPTIONAL) {
   3356 			if (optstack != NULL) {
   3357 				optstack->parent = new;
   3358 				new->cl_head = optstack;
   3359 			}
   3360 			args->optstack = new;
   3361 		}
   3362 	} else if (parent->flavor == CIL_BOOLEANIF) {
   3363 		args->boolif = parent;
   3364 	} else if (parent->flavor == CIL_MACRO) {
   3365 		args->macro = parent;
   3366 	}
   3367 
   3368 	return SEPOL_OK;
   3369 
   3370 exit:
   3371 	return rc;
   3372 
   3373 }
   3374 
   3375 int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *extra_args)
   3376 {
   3377 	int rc = SEPOL_ERR;
   3378 	struct cil_args_resolve *args = extra_args;
   3379 	struct cil_tree_node *parent = NULL;
   3380 
   3381 	if (current == NULL ||  extra_args == NULL) {
   3382 		goto exit;
   3383 	}
   3384 
   3385 	parent = current->parent;
   3386 
   3387 	if (parent->flavor == CIL_CALL) {
   3388 		/* pop off the stack */
   3389 		struct cil_tree_node *callstack = args->callstack;
   3390 		args->callstack = callstack->cl_head;
   3391 		if (callstack->cl_head) {
   3392 			callstack->cl_head->parent = NULL;
   3393 		}
   3394 		free(callstack);
   3395 	} else if (parent->flavor == CIL_MACRO) {
   3396 		args->macro = NULL;
   3397 	} else if (parent->flavor == CIL_OPTIONAL) {
   3398 		struct cil_tree_node *optstack;
   3399 
   3400 		if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) {
   3401 			*(args->changed) = CIL_TRUE;
   3402 			cil_tree_children_destroy(parent);
   3403 		}
   3404 
   3405 		/* pop off the stack */
   3406 		optstack = args->optstack;
   3407 		args->optstack = optstack->cl_head;
   3408 		if (optstack->cl_head) {
   3409 			optstack->cl_head->parent = NULL;
   3410 		}
   3411 		free(optstack);
   3412 	} else if (parent->flavor == CIL_BOOLEANIF) {
   3413 		args->boolif = NULL;
   3414 	}
   3415 
   3416 	return SEPOL_OK;
   3417 
   3418 exit:
   3419 	return rc;
   3420 }
   3421 
   3422 int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
   3423 {
   3424 	int rc = SEPOL_ERR;
   3425 	struct cil_args_resolve extra_args;
   3426 	enum cil_pass pass = CIL_PASS_TIF;
   3427 	uint32_t changed = 0;
   3428 
   3429 	if (db == NULL || current == NULL) {
   3430 		goto exit;
   3431 	}
   3432 
   3433 	extra_args.db = db;
   3434 	extra_args.pass = pass;
   3435 	extra_args.changed = &changed;
   3436 	extra_args.callstack = NULL;
   3437 	extra_args.optstack = NULL;
   3438 	extra_args.boolif= NULL;
   3439 	extra_args.macro = NULL;
   3440 	extra_args.sidorder_lists = NULL;
   3441 	extra_args.classorder_lists = NULL;
   3442 	extra_args.catorder_lists = NULL;
   3443 	extra_args.sensitivityorder_lists = NULL;
   3444 	extra_args.in_list = NULL;
   3445 
   3446 	cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
   3447 	cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
   3448 	cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
   3449 	cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
   3450 	cil_list_init(&extra_args.in_list, CIL_IN);
   3451 	for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) {
   3452 		extra_args.pass = pass;
   3453 		rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args);
   3454 		if (rc != SEPOL_OK) {
   3455 			cil_log(CIL_INFO, "Pass %i of resolution failed\n", pass);
   3456 			goto exit;
   3457 		}
   3458 
   3459 		if (pass == CIL_PASS_IN) {
   3460 			rc = cil_resolve_in_list(&extra_args);
   3461 			if (rc != SEPOL_OK) {
   3462 				goto exit;
   3463 			}
   3464 			cil_list_destroy(&extra_args.in_list, CIL_FALSE);
   3465 		}
   3466 
   3467 		if (pass == CIL_PASS_MISC1) {
   3468 			db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists);
   3469 			db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists);
   3470 			db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists);
   3471 			cil_set_cat_values(db->catorder, db);
   3472 			db->sensitivityorder = __cil_ordered_lists_merge_all(&extra_args.sensitivityorder_lists);
   3473 
   3474 			rc = __cil_verify_ordered(current, CIL_SID);
   3475 			if (rc != SEPOL_OK) {
   3476 				goto exit;
   3477 			}
   3478 
   3479 			rc = __cil_verify_ordered(current, CIL_CLASS);
   3480 			if (rc != SEPOL_OK) {
   3481 				goto exit;
   3482 			}
   3483 
   3484 			rc = __cil_verify_ordered(current, CIL_CAT);
   3485 			if (rc != SEPOL_OK) {
   3486 				goto exit;
   3487 			}
   3488 
   3489 			rc = __cil_verify_ordered(current, CIL_SENS);
   3490 			if (rc != SEPOL_OK) {
   3491 				goto exit;
   3492 			}
   3493 		}
   3494 
   3495 		if (changed && (pass > CIL_PASS_CALL1)) {
   3496 			/* Need to re-resolve because an optional was disabled that contained
   3497 			 * one or more declarations. We only need to reset to the call1 pass
   3498 			 * because things done in the preceeding passes aren't allowed in
   3499 			 * optionals, and thus can't be disabled.
   3500 			 * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment
   3501 			 * it to CIL_PASS_CALL2
   3502 			 */
   3503 			cil_log(CIL_INFO, "Resetting declarations\n");
   3504 
   3505 			if (pass >= CIL_PASS_MISC1) {
   3506 				__cil_ordered_lists_reset(&extra_args.sidorder_lists);
   3507 				__cil_ordered_lists_reset(&extra_args.classorder_lists);
   3508 				__cil_ordered_lists_reset(&extra_args.catorder_lists);
   3509 				__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
   3510 				cil_list_destroy(&db->sidorder, CIL_FALSE);
   3511 				cil_list_destroy(&db->classorder, CIL_FALSE);
   3512 				cil_list_destroy(&db->catorder, CIL_FALSE);
   3513 				cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
   3514 			}
   3515 
   3516 			pass = CIL_PASS_CALL1;
   3517 
   3518 			rc = cil_reset_ast(current);
   3519 			if (rc != SEPOL_OK) {
   3520 				cil_log(CIL_ERR, "Failed to reset declarations\n");
   3521 				goto exit;
   3522 			}
   3523 		}
   3524 
   3525 		/* reset the arguments */
   3526 		changed = 0;
   3527 		while (extra_args.callstack != NULL) {
   3528 			struct cil_tree_node *curr = extra_args.callstack;
   3529 			struct cil_tree_node *next = curr->cl_head;
   3530 			free(curr);
   3531 			extra_args.callstack = next;
   3532 		}
   3533 		while (extra_args.optstack != NULL) {
   3534 			struct cil_tree_node *curr = extra_args.optstack;
   3535 			struct cil_tree_node *next = curr->cl_head;
   3536 			free(curr);
   3537 			extra_args.optstack = next;
   3538 		}
   3539 	}
   3540 
   3541 	rc = __cil_verify_initsids(db->sidorder);
   3542 	if (rc != SEPOL_OK) {
   3543 		goto exit;
   3544 	}
   3545 
   3546 	rc = SEPOL_OK;
   3547 exit:
   3548 	return rc;
   3549 }
   3550 
   3551 static int __cil_resolve_name_with_root(struct cil_db *db, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
   3552 {
   3553 	symtab_t *symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
   3554 
   3555 	return cil_symtab_get_datum(symtab, name, datum);
   3556 }
   3557 
   3558 static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
   3559 {
   3560 	int rc = SEPOL_ERR;
   3561 	symtab_t *symtab = NULL;
   3562 
   3563 	while (node != NULL && rc != SEPOL_OK) {
   3564 		switch (node->flavor) {
   3565 		case CIL_ROOT:
   3566 			goto exit;
   3567 			break;
   3568 		case CIL_BLOCK:
   3569 			symtab = &((struct cil_block*)node->data)->symtab[sym_index];
   3570 			rc = cil_symtab_get_datum(symtab, name, datum);
   3571 			break;
   3572 		case CIL_BLOCKINHERIT: {
   3573 			struct cil_blockinherit *inherit = node->data;
   3574 			rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum);
   3575 			if (rc != SEPOL_OK) {
   3576 				/* Continue search in original block's parent */
   3577 				rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum);
   3578 				goto exit;
   3579 			}
   3580 		}
   3581 			break;
   3582 		case CIL_MACRO: {
   3583 			struct cil_macro *macro = node->data;
   3584 			symtab = &macro->symtab[sym_index];
   3585 			rc = cil_symtab_get_datum(symtab, name, datum);
   3586 		}
   3587 			break;
   3588 		case CIL_CALL: {
   3589 			struct cil_call *call = node->data;
   3590 			rc = cil_resolve_name_call_args(call, name, sym_index, datum);
   3591 			if (rc != SEPOL_OK) {
   3592 				/* Continue search in macro's parent */
   3593 				rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
   3594 			}
   3595 		}
   3596 			break;
   3597 		case CIL_IN:
   3598 			/* In block symtabs only exist before resolving the AST */
   3599 		case CIL_CONDBLOCK:
   3600 			/* Cond block symtabs only exist before resolving the AST */
   3601 		default:
   3602 			break;
   3603 		}
   3604 
   3605 		node = node->parent;
   3606 	}
   3607 
   3608 exit:
   3609 	return rc;
   3610 }
   3611 
   3612 static int __cil_resolve_name_helper(struct cil_db *db, struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
   3613 {
   3614 	int rc = SEPOL_ERR;
   3615 
   3616 	rc = __cil_resolve_name_with_parents(node, name, sym_index, datum);
   3617 	if (rc != SEPOL_OK) {
   3618 		rc = __cil_resolve_name_with_root(db, name, sym_index, datum);
   3619 	}
   3620 	return rc;
   3621 }
   3622 
   3623 int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum)
   3624 {
   3625 	int rc = SEPOL_ERR;
   3626 	struct cil_args_resolve *args = extra_args;
   3627 	struct cil_db *db = args->db;
   3628 	struct cil_tree_node *node = NULL;
   3629 
   3630 	if (name == NULL) {
   3631 		cil_log(CIL_ERR, "Invalid call to cil_resolve_name\n");
   3632 		goto exit;
   3633 	}
   3634 
   3635 	*datum = NULL;
   3636 
   3637 	if (strchr(name,'.') == NULL) {
   3638 		/* No '.' in name */
   3639 		rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum);
   3640 		if (rc != SEPOL_OK) {
   3641 			goto exit;
   3642 		}
   3643 	} else {
   3644 		char *sp = NULL;
   3645 		char *name_dup = cil_strdup(name);
   3646 		char *current = strtok_r(name_dup, ".", &sp);
   3647 		char *next = strtok_r(NULL, ".", &sp);
   3648 		symtab_t *symtab = NULL;
   3649 
   3650 		node = ast_node;
   3651 		if (*name == '.') {
   3652 			/* Leading '.' */
   3653 			symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_BLOCKS];
   3654 		} else {
   3655 			rc = __cil_resolve_name_helper(db, node->parent, current, CIL_SYM_BLOCKS, datum);
   3656 			if (rc != SEPOL_OK) {
   3657 				free(name_dup);
   3658 				goto exit;
   3659 			}
   3660 			symtab = (*datum)->symtab;
   3661 		}
   3662 		/* Keep looking up blocks by name until only last part of name remains */
   3663 		while (next != NULL) {
   3664 			rc = cil_symtab_get_datum(symtab, current, datum);
   3665 			if (rc != SEPOL_OK) {
   3666 				free(name_dup);
   3667 				goto exit;
   3668 			}
   3669 			node = NODE(*datum);
   3670 			if (node->flavor == CIL_BLOCK) {
   3671 				symtab = &((struct cil_block*)node->data)->symtab[CIL_SYM_BLOCKS];
   3672 			} else {
   3673 				if (ast_node->flavor != CIL_IN) {
   3674 					cil_log(CIL_WARN, "Can only use %s name for name resolution in \"in\" blocks\n", cil_node_to_string(node));
   3675 					free(name_dup);
   3676 					rc = SEPOL_ERR;
   3677 					goto exit;
   3678 				}
   3679 				if (node->flavor == CIL_MACRO) {
   3680 					struct cil_macro *macro = node->data;
   3681 					symtab = &macro->symtab[sym_index];
   3682 				} else {
   3683 					/* optional */
   3684 					symtab = (*datum)->symtab;
   3685 				}
   3686 			}
   3687 			current = next;
   3688 			next = strtok_r(NULL, ".", &sp);
   3689 		}
   3690 		symtab = &(symtab[sym_index]);
   3691 		rc = cil_symtab_get_datum(symtab, current, datum);
   3692 		free(name_dup);
   3693 		if (rc != SEPOL_OK) {
   3694 			goto exit;
   3695 		}
   3696 	}
   3697 
   3698 	rc = SEPOL_OK;
   3699 
   3700 exit:
   3701 	if (rc != SEPOL_OK) {
   3702 		*datum = NULL;
   3703 		cil_log(CIL_WARN, "Failed to resolve %s in %s statement on line %d of %s\n",
   3704 			name, cil_node_to_string(ast_node), ast_node->line, ast_node->path);
   3705 	}
   3706 
   3707 	if (*datum != NULL) {
   3708 		/* If this datum is an alias, then return the actual node
   3709 		 * This depends on aliases already being processed
   3710 		 */
   3711 		node = NODE(*datum);
   3712 		if (node->flavor == CIL_TYPEALIAS || node->flavor == CIL_SENSALIAS
   3713 			|| node->flavor == CIL_CATALIAS) {
   3714 			struct cil_alias *alias = (struct cil_alias *)(*datum);
   3715 			if (alias->actual) {
   3716 				*datum = alias->actual;
   3717 			}
   3718 		}
   3719 	}
   3720 
   3721 	return rc;
   3722 }
   3723