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