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