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