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