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