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