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
50struct 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
65static 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
107static 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
143exit:
144	return rc;
145}
146
147int 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
174exit:
175	return rc;
176}
177
178int 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
199exit:
200	return rc;
201}
202
203int 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
224exit:
225	return rc;
226}
227
228int 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
258exit:
259	return rc;
260}
261
262int 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
274int 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
317exit:
318	return rc;
319}
320
321int 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
367exit:
368	return rc;
369}
370
371int 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
412exit:
413	return rc;
414}
415
416int 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
451exit:
452	return rc;
453}
454
455int 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
499int 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
523exit:
524	return rc;
525}
526
527int 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
584exit:
585	return rc;
586}
587
588int 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
640exit:
641	return rc;
642}
643
644int __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
653int 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
688exit:
689	return rc;
690}
691
692int 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
729exit:
730	return rc;
731}
732
733int 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
760exit:
761	return rc;
762}
763
764int 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
803exit:
804	return rc;
805}
806
807int 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
846exit:
847	return rc;
848}
849
850int 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
862exit:
863	return rc;
864}
865
866int 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;
902exit:
903	return rc;
904}
905
906int 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
928exit:
929	return rc;
930}
931
932int 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
976exit:
977	return rc;
978}
979
980int 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
1001exit:
1002	return rc;
1003}
1004
1005int 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
1044exit:
1045	return rc;
1046}
1047
1048struct cil_ordered_list {
1049	int merged;
1050	struct cil_list *list;
1051	struct cil_tree_node *node;
1052};
1053
1054void __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
1063void __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
1071void __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
1091void __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
1097struct 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
1132int __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
1145struct 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
1156int __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
1250struct 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
1291exit:
1292	cil_list_destroy(&composite, CIL_FALSE);
1293	return NULL;
1294}
1295
1296int 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
1325exit:
1326	return rc;
1327}
1328
1329int 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
1358exit:
1359	return rc;
1360}
1361
1362void 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
1376int 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
1414exit:
1415	return rc;
1416}
1417
1418int 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
1447exit:
1448	return rc;
1449}
1450
1451int 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
1463exit:
1464	return rc;
1465}
1466
1467
1468int 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
1483exit:
1484	return rc;
1485}
1486
1487int 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
1515exit:
1516	return rc;
1517}
1518
1519int 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
1541exit:
1542	return rc;
1543}
1544
1545int 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
1595exit:
1596	return rc;
1597}
1598
1599int 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
1616exit:
1617	return rc;
1618}
1619
1620int 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
1640exit:
1641	return rc;
1642}
1643
1644int 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
1707exit:
1708	return rc;
1709}
1710
1711int 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
1733int 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
1754exit:
1755	return rc;
1756}
1757
1758int 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
1779exit:
1780	return rc;
1781}
1782
1783int 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
1829exit:
1830	return rc;
1831}
1832
1833int 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
1868exit:
1869	return rc;
1870}
1871
1872int 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
1893exit:
1894	return rc;
1895}
1896
1897int 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
1918exit:
1919	return rc;
1920}
1921
1922int 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
1943exit:
1944	return rc;
1945}
1946
1947int 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
1968exit:
1969	return rc;
1970}
1971
1972int 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
1993exit:
1994	return rc;
1995}
1996
1997int 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
2018exit:
2019	return rc;
2020}
2021
2022int 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
2060exit:
2061	return rc;
2062}
2063
2064int 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
2093exit:
2094	return rc;
2095}
2096
2097int 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
2129exit:
2130	return rc;
2131}
2132
2133int 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
2155exit:
2156	return rc;
2157}
2158
2159int 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
2191exit:
2192	return rc;
2193}
2194
2195int 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
2246exit:
2247	return rc;
2248}
2249
2250
2251int 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
2336exit:
2337	cil_log(CIL_ERR, "Bad bounds statement at line %u of %s\n", current->line, current->path);
2338	return rc;
2339}
2340
2341int 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
2361exit:
2362	return rc;
2363}
2364
2365int 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
2385exit:
2386	return rc;
2387}
2388
2389int 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
2634exit:
2635	return rc;
2636}
2637
2638int 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
2742exit:
2743	return rc;
2744}
2745
2746int 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
2774exit:
2775	return rc;
2776}
2777
2778int 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
2841exit:
2842	return rc;
2843}
2844
2845int 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
2857exit:
2858	return rc;
2859}
2860
2861static int __cil_evaluate_tunable_expr(struct cil_list_item *curr);
2862
2863static 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
2878static 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
2910int 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
2972exit:
2973	return rc;
2974}
2975
2976
2977int __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
3240exit:
3241	return rc;
3242}
3243
3244int __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
3310exit:
3311	return rc;
3312}
3313
3314int __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
3370exit:
3371	return rc;
3372
3373}
3374
3375int __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
3418exit:
3419	return rc;
3420}
3421
3422int 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;
3547exit:
3548	return rc;
3549}
3550
3551static 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
3558static 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
3608exit:
3609	return rc;
3610}
3611
3612static 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
3623int 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
3700exit:
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