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