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