• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <unistd.h>
35 #include <ctype.h>
36 
37 #include <sepol/policydb/polcaps.h>
38 #include <sepol/errcodes.h>
39 
40 #include "cil_internal.h"
41 #include "cil_flavor.h"
42 #include "cil_log.h"
43 #include "cil_mem.h"
44 #include "cil_tree.h"
45 #include "cil_list.h"
46 #include "cil_find.h"
47 #include "cil_stack.h"
48 
49 #include "cil_verify.h"
50 
__cil_is_reserved_name(const char * name,enum cil_flavor flavor)51 static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
52 {
53 	switch (flavor) {
54 	case CIL_BOOL:
55 	case CIL_TUNABLE:
56 		if ((name == CIL_KEY_EQ) || (name == CIL_KEY_NEQ))
57 			return CIL_TRUE;
58 		break;
59 	case CIL_PERM:
60 	case CIL_MAP_PERM:
61 	case CIL_USER:
62 	case CIL_USERATTRIBUTE:
63 	case CIL_ROLE:
64 	case CIL_ROLEATTRIBUTE:
65 		if (name == CIL_KEY_ALL)
66 			return CIL_TRUE;
67 		break;
68 	case CIL_TYPE:
69 	case CIL_TYPEATTRIBUTE:
70 	case CIL_TYPEALIAS:
71 		if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
72 			return CIL_TRUE;
73 		break;
74 	case CIL_CAT:
75 	case CIL_CATSET:
76 	case CIL_CATALIAS:
77 	case CIL_PERMISSIONX:
78 		if ((name == CIL_KEY_ALL) || (name == CIL_KEY_RANGE))
79 			return CIL_TRUE;
80 		break;
81 	default:
82 		/* All of these are not used in expressions */
83 		return CIL_FALSE;
84 		break;
85 	}
86 
87 	/* Everything not under the default case is also checked for these */
88 	if ((name == CIL_KEY_AND) || (name == CIL_KEY_OR) || (name == CIL_KEY_NOT) || (name == CIL_KEY_XOR)) {
89 		return CIL_TRUE;
90 	}
91 
92 	return CIL_FALSE;
93 }
94 
cil_verify_name(const struct cil_db * db,const char * name,enum cil_flavor flavor)95 int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor)
96 {
97 	int rc = SEPOL_ERR;
98 	int len;
99 	int i = 0;
100 
101 	if (name == NULL) {
102 		cil_log(CIL_ERR, "Name is NULL\n");
103 		goto exit;
104 	}
105 
106 	len = strlen(name);
107 	if (len >= CIL_MAX_NAME_LENGTH) {
108 		cil_log(CIL_ERR, "Name length greater than max name length of %d",
109 			CIL_MAX_NAME_LENGTH);
110 		rc = SEPOL_ERR;
111 		goto exit;
112 	}
113 
114 	if (!isalpha(name[0])) {
115 			cil_log(CIL_ERR, "First character in %s is not a letter\n", name);
116 			goto exit;
117 	}
118 
119 	if (db->qualified_names == CIL_FALSE) {
120 		for (i = 1; i < len; i++) {
121 			if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
122 				cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
123 				goto exit;
124 			}
125 		}
126 	} else {
127 		for (i = 1; i < len; i++) {
128 			if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.') {
129 				cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
130 				goto exit;
131 			}
132 		}
133 	}
134 
135 	if (__cil_is_reserved_name(name, flavor)) {
136 		cil_log(CIL_ERR, "Name %s is a reserved word\n", name);
137 		goto exit;
138 	}
139 
140 	return SEPOL_OK;
141 
142 exit:
143 	cil_log(CIL_ERR, "Invalid name\n");
144 	return rc;
145 }
146 
__cil_verify_syntax(struct cil_tree_node * parse_current,enum cil_syntax s[],size_t len)147 int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len)
148 {
149 	struct cil_tree_node *c = parse_current;
150 	size_t i = 0;
151 
152 	while (i < len && c != NULL) {
153 		if ((s[i] & CIL_SYN_STRING) && c->data != NULL && c->cl_head == NULL) {
154 			c = c->next;
155 			i++;
156 		} else if ((s[i] & CIL_SYN_LIST) && c->data == NULL && c->cl_head != NULL) {
157 			c = c->next;
158 			i++;
159 		} else if ((s[i] & CIL_SYN_EMPTY_LIST) && c->data == NULL && c->cl_head == NULL) {
160 			c = c->next;
161 			i++;
162 		} else if ((s[i] & CIL_SYN_N_LISTS) || (s[i] & CIL_SYN_N_STRINGS)) {
163 			while (c != NULL) {
164 				if ((s[i] & CIL_SYN_N_LISTS) && c->data == NULL && c->cl_head != NULL) {
165 					c = c->next;
166 				} else if ((s[i] & CIL_SYN_N_STRINGS) && c->data != NULL && c->cl_head == NULL) {
167 					c = c->next;
168 				} else {
169 					goto exit;
170 				}
171 			}
172 			i++;
173 			break; /* Only CIL_SYN_END allowed after these */
174 		} else {
175 			goto exit;
176 		}
177 	}
178 
179 	if (i < len && (s[i] & CIL_SYN_END) && c == NULL) {
180 		return SEPOL_OK;
181 	}
182 
183 exit:
184 	cil_log(CIL_ERR, "Invalid syntax\n");
185 	return SEPOL_ERR;
186 }
187 
cil_verify_expr_syntax(struct cil_tree_node * current,enum cil_flavor op,enum cil_flavor expr_flavor)188 int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor)
189 {
190 	int rc;
191 	enum cil_syntax syntax[] = {
192 		CIL_SYN_STRING,
193 		CIL_SYN_STRING | CIL_SYN_LIST,
194 		CIL_SYN_STRING | CIL_SYN_LIST,
195 		CIL_SYN_END
196 	};
197 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
198 
199 	switch (op) {
200 	case CIL_NOT:
201 		syntax[2] = CIL_SYN_END;
202 		syntax_len = 3;
203 		break;
204 	case CIL_AND:
205 	case CIL_OR:
206 	case CIL_XOR:
207 		break;
208 	case CIL_EQ:
209 	case CIL_NEQ:
210 		if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) {
211 			cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data);
212 			goto exit;
213 		}
214 		break;
215 	case CIL_ALL:
216 		if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) {
217 			cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data);
218 			goto exit;
219 		}
220 		syntax[1] = CIL_SYN_END;
221 		syntax_len = 2;
222 		break;
223 	case CIL_RANGE:
224 		if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) {
225 			cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data);
226 			goto exit;
227 		}
228 		syntax[1] = CIL_SYN_STRING;
229 		syntax[2] = CIL_SYN_STRING;
230 		break;
231 	case CIL_NONE: /* String or List */
232 		syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS;
233 		syntax[1] = CIL_SYN_END;
234 		syntax_len = 2;
235 		break;
236 	default:
237 		cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data);
238 		goto exit;
239 	}
240 
241 	rc = __cil_verify_syntax(current, syntax, syntax_len);
242 	if (rc != SEPOL_OK) {
243 		goto exit;
244 	}
245 
246 	return SEPOL_OK;
247 
248 exit:
249 	return SEPOL_ERR;
250 }
251 
cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor,enum cil_flavor r_flavor,enum cil_flavor op,enum cil_flavor expr_flavor)252 int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor)
253 {
254 	if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) {
255 		if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) {
256 			cil_log(CIL_ERR, "l1, l2, h1, and h2 cannot be used on the left side with a string or list on the right side\n");
257 			goto exit;
258 		} else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) {
259 			if (expr_flavor != CIL_VALIDATETRANS && expr_flavor != CIL_MLSVALIDATETRANS) {
260 				cil_log(CIL_ERR, "u3, r3, and t3 can only be used with (mls)validatetrans rules\n");
261 				goto exit;
262 			}
263 		}
264 	} else {
265 		if (r_flavor == CIL_CONS_U1 || r_flavor == CIL_CONS_R1 || r_flavor == CIL_CONS_T1) {
266 			cil_log(CIL_ERR, "u1, r1, and t1 are not allowed on the right side\n");
267 			goto exit;
268 		} else if (r_flavor == CIL_CONS_U3 || r_flavor == CIL_CONS_R3 || r_flavor == CIL_CONS_T3) {
269 			cil_log(CIL_ERR, "u3, r3, and t3 are not allowed on the right side\n");
270 			goto exit;
271 		} else if (r_flavor == CIL_CONS_U2) {
272 			if (op != CIL_EQ && op != CIL_NEQ) {
273 				cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
274 				goto exit;
275 			} else if (l_flavor != CIL_CONS_U1) {
276 				cil_log(CIL_ERR, "u2 on the right side must be used with u1 on the left\n");
277 				goto exit;
278 			}
279 		} else if (r_flavor == CIL_CONS_R2) {
280 			if (l_flavor != CIL_CONS_R1) {
281 				cil_log(CIL_ERR, "r2 on the right side must be used with r1 on the left\n");
282 				goto exit;
283 			}
284 		} else if (r_flavor == CIL_CONS_T2) {
285 			if (op != CIL_EQ && op != CIL_NEQ) {
286 				cil_log(CIL_ERR, "t2 on the right side must be used with eq or neq as the operator\n");
287 				goto exit;
288 			} else if (l_flavor != CIL_CONS_T1) {
289 				cil_log(CIL_ERR, "t2 on the right side must be used with t1 on the left\n");
290 				goto exit;
291 			}
292 		} else if (r_flavor == CIL_CONS_L2) {
293 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_H1) {
294 				cil_log(CIL_ERR, "l2 on the right side must be used with l1 or h1 on the left\n");
295 				goto exit;
296 			}
297 		} else if (r_flavor == CIL_CONS_H2) {
298 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_L2 && l_flavor != CIL_CONS_H1 ) {
299 				cil_log(CIL_ERR, "h2 on the right side must be used with l1, l2, or h1 on the left\n");
300 				goto exit;
301 			}
302 		} else if (r_flavor == CIL_CONS_H1) {
303 			if (l_flavor != CIL_CONS_L1) {
304 				cil_log(CIL_ERR, "h1 on the right side must be used with l1 on the left\n");
305 				goto exit;
306 			}
307 		}
308 	}
309 
310 	return SEPOL_OK;
311 
312 exit:
313 	return SEPOL_ERR;
314 }
315 
cil_verify_constraint_expr_syntax(struct cil_tree_node * current,enum cil_flavor op)316 int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op)
317 {
318 	int rc;
319 	enum cil_syntax syntax[] = {
320 		CIL_SYN_STRING,
321 		CIL_SYN_END,
322 		CIL_SYN_END,
323 		CIL_SYN_END
324 	};
325 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
326 
327 	switch (op) {
328 	case CIL_NOT:
329 		syntax[1] = CIL_SYN_LIST;
330 		syntax_len--;
331 		break;
332 	case CIL_AND:
333 	case CIL_OR:
334 		syntax[1] = CIL_SYN_LIST;
335 		syntax[2] = CIL_SYN_LIST;
336 		break;
337 	case CIL_EQ:
338 	case CIL_NEQ:
339 		syntax[1] = CIL_SYN_STRING;
340 		syntax[2] = CIL_SYN_STRING | CIL_SYN_LIST;
341 		break;
342 	case CIL_CONS_DOM:
343 	case CIL_CONS_DOMBY:
344 	case CIL_CONS_INCOMP:
345 		syntax[1] = CIL_SYN_STRING;
346 		syntax[2] = CIL_SYN_STRING;
347 		break;
348 	default:
349 		cil_log(CIL_ERR, "Invalid operator (%s) for constraint expression\n", (char*)current->data);
350 		goto exit;
351 	}
352 
353 	rc = __cil_verify_syntax(current, syntax, syntax_len);
354 	if (rc != SEPOL_OK) {
355 		cil_log(CIL_ERR, "Invalid constraint syntax\n");
356 		goto exit;
357 	}
358 
359 	return SEPOL_OK;
360 
361 exit:
362 	return SEPOL_ERR;
363 }
364 
cil_verify_conditional_blocks(struct cil_tree_node * current)365 int cil_verify_conditional_blocks(struct cil_tree_node *current)
366 {
367 	int found_true = CIL_FALSE;
368 	int found_false = CIL_FALSE;
369 
370 	if (current->cl_head->data == CIL_KEY_CONDTRUE) {
371 		found_true = CIL_TRUE;
372 	} else if (current->cl_head->data == CIL_KEY_CONDFALSE) {
373 		found_false = CIL_TRUE;
374 	} else {
375 		cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional");
376 		return SEPOL_ERR;
377 	}
378 
379 	current = current->next;
380 	if (current != NULL) {
381 		if (current->cl_head->data == CIL_KEY_CONDTRUE) {
382 			if (found_true) {
383 				cil_tree_log(current, CIL_ERR, "More than one true block in conditional");
384 				return SEPOL_ERR;
385 			}
386 		} else if (current->cl_head->data == CIL_KEY_CONDFALSE) {
387 			if (found_false) {
388 				cil_tree_log(current, CIL_ERR, "More than one false block in conditional");
389 				return SEPOL_ERR;
390 			}
391 		} else {
392 			cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional");
393 			return SEPOL_ERR;
394 		}
395 	}
396 
397 	return SEPOL_OK;
398 }
399 
cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro * macro,struct cil_tree_node * node,const char * name)400 int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name)
401 {
402 	struct cil_list_item *item;
403 	struct cil_list *param_list = macro->params;
404 	if (param_list != NULL) {
405 		cil_list_for_each(item, param_list) {
406 			struct cil_param *param = item->data;
407 			if (param->flavor == node->flavor) {
408 				if (param->str == name) {
409 					cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(node), name);
410 					return SEPOL_ERR;
411 				}
412 			}
413 		}
414 	}
415 	return SEPOL_OK;
416 }
417 
418 static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack);
419 
__verify_no_self_reference_in_expr(struct cil_list * expr,struct cil_stack * stack)420 static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack)
421 {
422 	struct cil_list_item *item;
423 	int rc = SEPOL_OK;
424 
425 	if (!expr) {
426 		return SEPOL_OK;
427 	}
428 
429 	cil_list_for_each(item, expr) {
430 		if (item->flavor == CIL_DATUM) {
431 			struct cil_symtab_datum* datum = item->data;
432 			rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack);
433 		} else if (item->flavor == CIL_LIST) {
434 			rc = __verify_no_self_reference_in_expr(item->data, stack);
435 		}
436 		if (rc != SEPOL_OK) {
437 			return SEPOL_ERR;
438 		}
439 	}
440 
441 	return SEPOL_OK;
442 }
443 
cil_verify_no_self_reference(enum cil_flavor flavor,struct cil_symtab_datum * datum,struct cil_stack * stack)444 static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack)
445 {
446 	struct cil_stack_item *item;
447 	int i = 0;
448 	int rc = SEPOL_OK;
449 
450 	cil_stack_for_each(stack, i, item) {
451 		struct cil_symtab_datum *prev = item->data;
452 		if (datum == prev) {
453 			cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name);
454 			return SEPOL_ERR;
455 		}
456 	}
457 
458 	switch (flavor) {
459 	case CIL_USERATTRIBUTE: {
460 		struct cil_userattribute *attr = (struct cil_userattribute *)datum;
461 		cil_stack_push(stack, CIL_DATUM, datum);
462 		rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
463 		cil_stack_pop(stack);
464 		break;
465 	}
466 	case CIL_ROLEATTRIBUTE: {
467 		struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
468 		cil_stack_push(stack, CIL_DATUM, datum);
469 		rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
470 		cil_stack_pop(stack);
471 		break;
472 	}
473 	case CIL_TYPEATTRIBUTE: {
474 		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
475 		cil_stack_push(stack, CIL_DATUM, datum);
476 		rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
477 		cil_stack_pop(stack);
478 		break;
479 	}
480 	case CIL_CATSET: {
481 		struct cil_catset *set = (struct cil_catset *)datum;
482 		cil_stack_push(stack, CIL_DATUM, datum);
483 		rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack);
484 		cil_stack_pop(stack);
485 		break;
486 	}
487 	default:
488 		break;
489 	}
490 
491 	return rc;
492 }
493 
__cil_verify_ranges(struct cil_list * list)494 int __cil_verify_ranges(struct cil_list *list)
495 {
496 	int rc = SEPOL_ERR;
497 	struct cil_list_item *curr;
498 	struct cil_list_item *range = NULL;
499 
500 	if (list == NULL || list->head == NULL) {
501 		goto exit;
502 	}
503 
504 	cil_list_for_each(curr, list) {
505 		/* range */
506 		if (curr->flavor == CIL_LIST) {
507 			range = ((struct cil_list*)curr->data)->head;
508 			if (range == NULL || range->next == NULL || range->next->next != NULL) {
509 				goto exit;
510 			}
511 		}
512 	}
513 
514 	return SEPOL_OK;
515 
516 exit:
517 	cil_log(CIL_ERR,"Invalid Range syntax\n");
518 	return rc;
519 }
520 
521 struct cil_args_verify_order {
522 	uint32_t *flavor;
523 };
524 
__cil_verify_ordered_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)525 int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
526 {
527 	struct cil_args_verify_order *args = extra_args;
528 	uint32_t *flavor = args->flavor;
529 
530 	if (node->flavor == *flavor) {
531 		if (node->flavor == CIL_SID) {
532 			struct cil_sid *sid = node->data;
533 			if (sid->ordered == CIL_FALSE) {
534 				cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name);
535 				return SEPOL_ERR;
536 			}
537 		} else if (node->flavor == CIL_CLASS) {
538 			struct cil_class *class = node->data;
539 			if (class->ordered == CIL_FALSE) {
540 				cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name);
541 				return SEPOL_ERR;
542 			}
543 		} else if (node->flavor == CIL_CAT) {
544 			struct cil_cat *cat = node->data;
545 			if (cat->ordered == CIL_FALSE) {
546 				cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name);
547 				return SEPOL_ERR;
548 			}
549 		} else if (node->flavor == CIL_SENS) {
550 			struct cil_sens *sens = node->data;
551 			if (sens->ordered == CIL_FALSE) {
552 				cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name);
553 				return SEPOL_ERR;
554 			}
555 		}
556 	}
557 
558 	return SEPOL_OK;
559 }
560 
__cil_verify_ordered(struct cil_tree_node * current,enum cil_flavor flavor)561 int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor)
562 {
563 	struct cil_args_verify_order extra_args;
564 	int rc = SEPOL_ERR;
565 
566 	extra_args.flavor = &flavor;
567 
568 	rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args);
569 
570 	return rc;
571 }
572 
__cil_verify_initsids(struct cil_list * sids)573 int __cil_verify_initsids(struct cil_list *sids)
574 {
575 	int rc = SEPOL_OK;
576 	struct cil_list_item *i;
577 
578 	if (sids->head == NULL) {
579 		cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n");
580 		return SEPOL_ERR;
581 	}
582 
583 	cil_list_for_each(i, sids) {
584 		struct cil_sid *sid = i->data;
585 		if (sid->context == NULL) {
586 			struct cil_tree_node *node = sid->datum.nodes->head->data;
587 			cil_tree_log(node, CIL_INFO, "No context assigned to SID %s, omitting from policy",sid->datum.name);
588 		}
589 	}
590 
591 	return rc;
592 }
593 
__cil_is_cat_in_cats(struct cil_cat * cat,struct cil_cats * cats)594 static int __cil_is_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
595 {
596 	struct cil_list_item *i;
597 
598 	cil_list_for_each(i, cats->datum_expr) {
599 		struct cil_cat *c = i->data;
600 		if (c == cat) {
601 			return CIL_TRUE;
602 		}
603 	}
604 
605 	return CIL_FALSE;
606 }
607 
608 
__cil_verify_cat_in_cats(struct cil_cat * cat,struct cil_cats * cats)609 static int __cil_verify_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
610 {
611 	if (__cil_is_cat_in_cats(cat, cats) != CIL_TRUE) {
612 		cil_log(CIL_ERR, "Failed to find category %s in category list\n", cat->datum.name);
613 		return SEPOL_ERR;
614 	}
615 
616 	return SEPOL_OK;
617 }
618 
__cil_verify_cats_associated_with_sens(struct cil_sens * sens,struct cil_cats * cats)619 static int __cil_verify_cats_associated_with_sens(struct cil_sens *sens, struct cil_cats *cats)
620 {
621 	int rc = SEPOL_OK;
622 	struct cil_list_item *i, *j;
623 
624 	if (!cats) {
625 		return SEPOL_OK;
626 	}
627 
628 	if (!sens->cats_list) {
629 		cil_log(CIL_ERR, "No categories can be used with sensitivity %s\n", sens->datum.name);
630 		return SEPOL_ERR;
631 	}
632 
633 	cil_list_for_each(i, cats->datum_expr) {
634 		struct cil_cat *cat = i->data;
635 		int ok = CIL_FALSE;
636 		cil_list_for_each(j, sens->cats_list) {
637 			if (__cil_is_cat_in_cats(cat, j->data) == CIL_TRUE) {
638 				ok = CIL_TRUE;
639 				break;
640 			}
641 		}
642 
643 		if (ok != CIL_TRUE) {
644 			cil_log(CIL_ERR, "Category %s cannot be used with sensitivity %s\n",
645 					cat->datum.name, sens->datum.name);
646 			rc = SEPOL_ERR;
647 		}
648 	}
649 
650 	return rc;
651 }
652 
__cil_verify_levelrange_sensitivity(struct cil_db * db,struct cil_sens * low,struct cil_sens * high)653 static int __cil_verify_levelrange_sensitivity(struct cil_db *db, struct cil_sens *low, struct cil_sens *high)
654 {
655 	struct cil_list_item *curr;
656 	int found = CIL_FALSE;
657 	int rc = SEPOL_ERR;
658 
659 	cil_list_for_each(curr, db->sensitivityorder) {
660 		if (curr->data == low) {
661 			found = CIL_TRUE;
662 		}
663 
664 		if ((found == CIL_TRUE) && (curr->data == high)) {
665 			break;
666 		}
667 	}
668 
669 	if (found != CIL_TRUE || curr == NULL) {
670 		goto exit;
671 	}
672 
673 	return SEPOL_OK;
674 
675 exit:
676 	cil_log(CIL_ERR, "Sensitivity %s does not dominate %s\n",
677 		high->datum.name, low->datum.name);
678 	return rc;
679 
680 }
681 
__cil_verify_levelrange_cats(struct cil_cats * low,struct cil_cats * high)682 static int __cil_verify_levelrange_cats(struct cil_cats *low, struct cil_cats *high)
683 {
684 	int rc = SEPOL_ERR;
685 	struct cil_list_item *item;
686 
687 	if (low == NULL || (low == NULL && high == NULL)) {
688 		return SEPOL_OK;
689 	}
690 
691 	if (high == NULL) {
692 		rc = SEPOL_ERR;
693 		goto exit;
694 	}
695 
696 	cil_list_for_each(item, low->datum_expr) {
697 		rc = __cil_verify_cat_in_cats(item->data, high);
698 		if (rc != SEPOL_OK) {
699 			goto exit;
700 		}
701 	}
702 
703 	return SEPOL_OK;
704 
705 exit:
706 	cil_log(CIL_ERR, "Low level category set must be a subset of the high level category set\n");
707 	return rc;
708 }
709 
__cil_verify_levelrange(struct cil_db * db,struct cil_levelrange * lr)710 static int __cil_verify_levelrange(struct cil_db *db, struct cil_levelrange *lr)
711 {
712 	int rc = SEPOL_ERR;
713 
714 	rc = __cil_verify_levelrange_sensitivity(db, lr->low->sens, lr->high->sens);
715 	if (rc != SEPOL_OK) {
716 		goto exit;
717 	}
718 
719 	rc = __cil_verify_levelrange_cats(lr->low->cats, lr->high->cats);
720 	if (rc != SEPOL_OK) {
721 		goto exit;
722 	}
723 
724 	rc = __cil_verify_cats_associated_with_sens(lr->low->sens, lr->low->cats);
725 	if (rc != SEPOL_OK) {
726 		cil_log(CIL_ERR, "Low level sensitivity and categories are not associated\n");
727 		goto exit;
728 	}
729 
730 	rc = __cil_verify_cats_associated_with_sens(lr->high->sens, lr->high->cats);
731 	if (rc != SEPOL_OK) {
732 		cil_log(CIL_ERR, "High level sensitivity and categories are not associated\n");
733 		goto exit;
734 	}
735 
736 	return SEPOL_OK;
737 
738 exit:
739 	return rc;
740 }
741 
__cil_verify_named_levelrange(struct cil_db * db,struct cil_tree_node * node)742 static int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node)
743 {
744 	int rc = SEPOL_ERR;
745 	struct cil_levelrange *lr = node->data;
746 
747 	rc = __cil_verify_levelrange(db, lr);
748 	if (rc != SEPOL_OK) {
749 		goto exit;
750 	}
751 
752 	return SEPOL_OK;
753 exit:
754 	cil_tree_log(node, CIL_ERR, "Invalid named range");
755 	return rc;
756 }
757 
__cil_verify_user_pre_eval(struct cil_tree_node * node)758 static int __cil_verify_user_pre_eval(struct cil_tree_node *node)
759 {
760 	int rc = SEPOL_ERR;
761 	struct cil_user *user = node->data;
762 
763 	if (user->dftlevel == NULL) {
764 		cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name);
765 		goto exit;
766 	} else if (user->range == NULL) {
767 		cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name);
768 		goto exit;
769 	} else if (user->bounds != NULL) {
770 		int steps = 0;
771 		int limit = 2;
772 		struct cil_user *u1 = user;
773 		struct cil_user *u2 = user->bounds;
774 
775 		while (u2 != NULL) {
776 			if (u1 == u2) {
777 				cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name);
778 				goto exit;
779 			}
780 
781 			if (steps == limit) {
782 				steps = 0;
783 				limit *= 2;
784 				u1 = u2;
785 			}
786 
787 			u2 = u2->bounds;
788 			steps++;
789 		}
790 	}
791 
792 	return SEPOL_OK;
793 exit:
794 	cil_tree_log(node, CIL_ERR, "Invalid user");
795 	return rc;
796 }
797 
__cil_verify_user_post_eval(struct cil_db * db,struct cil_tree_node * node)798 static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node)
799 {
800 	int rc = SEPOL_ERR;
801 	struct cil_user *user = node->data;
802 
803 	/* Verify user range only if anonymous */
804 	if (user->range->datum.name == NULL) {
805 		rc = __cil_verify_levelrange(db, user->range);
806 		if (rc != SEPOL_OK) {
807 			goto exit;
808 		}
809 	}
810 
811 	return SEPOL_OK;
812 exit:
813 	cil_tree_log(node, CIL_ERR, "Invalid user");
814 	return rc;
815 }
816 
__cil_verify_role(struct cil_tree_node * node)817 static int __cil_verify_role(struct cil_tree_node *node)
818 {
819 	int rc = SEPOL_ERR;
820 	struct cil_role *role = node->data;
821 	int steps = 0;
822 	int limit = 2;
823 	struct cil_role *r1 = role;
824 	struct cil_role *r2 = role->bounds;
825 
826 	while (r2 != NULL) {
827 		if (r1 == r2) {
828 			cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name);
829 			goto exit;
830 		}
831 
832 		if (steps == limit) {
833 			steps = 0;
834 			limit *= 2;
835 			r1 = r2;
836 		}
837 
838 		r2 = r2->bounds;
839 		steps++;
840 	}
841 
842 	return SEPOL_OK;
843 exit:
844 	cil_tree_log(node, CIL_ERR, "Invalid role");
845 	return rc;
846 }
847 
__cil_verify_type(struct cil_tree_node * node)848 static int __cil_verify_type(struct cil_tree_node *node)
849 {
850 	int rc = SEPOL_ERR;
851 	struct cil_type *type = node->data;
852 	int steps = 0;
853 	int limit = 2;
854 	struct cil_type *t1 = type;
855 	struct cil_type *t2 = type->bounds;
856 
857 	while (t2 != NULL) {
858 		if (t1 == t2) {
859 			cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name);
860 			goto exit;
861 		}
862 
863 		if (steps == limit) {
864 			steps = 0;
865 			limit *= 2;
866 			t1 = t2;
867 		}
868 
869 		t2 = t2->bounds;
870 		steps++;
871 	}
872 
873 	return SEPOL_OK;
874 exit:
875 	cil_tree_log(node, CIL_ERR, "Invalid type");
876 	return rc;
877 }
878 
__cil_verify_context(struct cil_db * db,struct cil_context * ctx)879 static int __cil_verify_context(struct cil_db *db, struct cil_context *ctx)
880 {
881 	int rc = SEPOL_ERR;
882 	struct cil_user *user = ctx->user;
883 	struct cil_role *role = ctx->role;
884 	struct cil_type *type = ctx->type;
885 	struct cil_level *user_low = user->range->low;
886 	struct cil_level *user_high = user->range->high;
887 	struct cil_level *ctx_low = ctx->range->low;
888 	struct cil_level *ctx_high = ctx->range->high;
889 	struct cil_list *sensitivityorder = db->sensitivityorder;
890 	struct cil_list_item *curr;
891 	int found = CIL_FALSE;
892 
893 	if (user->roles != NULL) {
894 		if (!ebitmap_get_bit(user->roles, role->value)) {
895 			cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str);
896 			rc = SEPOL_ERR;
897 			goto exit;
898 		}
899 	} else {
900 		cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str);
901 		rc = SEPOL_ERR;
902 		goto exit;
903 	}
904 
905 	if (role->types != NULL) {
906 		if (!ebitmap_get_bit(role->types, type->value)) {
907 			cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str);
908 			rc = SEPOL_ERR;
909 			goto exit;
910 		}
911 	} else {
912 		cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str);
913 		rc = SEPOL_ERR;
914 		goto exit;
915 	}
916 
917 	/* Verify range only when anonymous */
918 	if (ctx->range->datum.name == NULL) {
919 		rc = __cil_verify_levelrange(db, ctx->range);
920 		if (rc != SEPOL_OK) {
921 			goto exit;
922 		}
923 	}
924 
925 	for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) {
926 		struct cil_sens *sens = curr->data;
927 
928 		if (found == CIL_FALSE) {
929 			if (sens == user_low->sens) {
930 				found = CIL_TRUE;
931 			} else if (sens == ctx_low->sens) {
932 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
933 					ctx->range_str, ctx->user_str);
934 				rc = SEPOL_ERR;
935 				goto exit;
936 			}
937 		}
938 
939 		if (found == CIL_TRUE) {
940 			if (sens == ctx_high->sens) {
941 				break;
942 			} else if (sens == user_high->sens) {
943 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
944 					ctx->range_str, ctx->user_str);
945 				rc = SEPOL_ERR;
946 				goto exit;
947 			}
948 		}
949 	}
950 
951 	return SEPOL_OK;
952 exit:
953 	cil_log(CIL_ERR, "Invalid context\n");
954 	return rc;
955 }
956 
__cil_verify_named_context(struct cil_db * db,struct cil_tree_node * node)957 static int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node)
958 {
959 	int rc = SEPOL_ERR;
960 	struct cil_context *ctx = node->data;
961 
962 	rc = __cil_verify_context(db, ctx);
963 	if (rc != SEPOL_OK) {
964 		goto exit;
965 	}
966 
967 	return SEPOL_OK;
968 exit:
969 	cil_tree_log(node, CIL_ERR, "Invalid named context");
970 	return rc;
971 }
972 
973 /*
974 static int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
975 {
976 
977 	int rc = SEPOL_ERR;
978 	struct cil_type_rule *typerule = NULL;
979 	struct cil_roletransition *roletrans = NULL;
980 	struct cil_complex_symtab_key ckey;
981 
982 	switch (node->flavor) {
983 	case CIL_ROLETRANSITION: {
984 		roletrans = node->data;
985 		ckey.key1 = (intptr_t)roletrans->src;
986 		ckey.key2 = (intptr_t)roletrans->tgt;
987 		ckey.key3 = (intptr_t)roletrans->obj;
988 		ckey.key4 = CIL_ROLETRANSITION;
989 		break;
990 	}
991 	case CIL_TYPE_RULE: {
992 		typerule = node->data;
993 		ckey.key1 = (intptr_t)typerule->src;
994 		ckey.key2 = (intptr_t)typerule->tgt;
995 		ckey.key3 = (intptr_t)typerule->obj;
996 		ckey.key4 = (intptr_t)typerule->rule_kind;
997 		break;
998 	}
999 	default:
1000 		break;
1001 	}
1002 
1003 
1004 	rc = cil_complex_symtab_insert(symtab, &ckey, NULL);
1005 	if (rc == SEPOL_EEXIST) {
1006 		struct cil_complex_symtab_datum *datum = NULL;
1007 		cil_complex_symtab_search(symtab, &ckey, &datum);
1008 		if (datum == NULL) {
1009 			cil_tree_log(node, CIL_ERR, "Duplicate rule defined");
1010 			rc = SEPOL_ERR;
1011 			goto exit;
1012 		}
1013 	}
1014 
1015 	return SEPOL_OK;
1016 exit:
1017 	cil_tree_log(node, CIL_ERR, "Invalid rule");
1018 	return rc;
1019 }
1020 */
1021 
__cil_verify_booleanif_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1022 static int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
1023 {
1024 	int rc = SEPOL_ERR;
1025 	struct cil_tree_node *rule_node = node;
1026 	struct cil_booleanif *bif = node->parent->parent->data;
1027 
1028 	switch (rule_node->flavor) {
1029 	case CIL_AVRULE: {
1030 		struct cil_avrule *avrule = NULL;
1031 		avrule = rule_node->data;
1032 		if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) {
1033 			if (bif->preserved_tunable) {
1034 				cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)");
1035 			} else {
1036 				cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block");
1037 			}
1038 			rc = SEPOL_ERR;
1039 			goto exit;
1040 		}
1041 		break;
1042 	}
1043 	case CIL_TYPE_RULE: /*
1044 	struct cil_type_rule *typerule = NULL;
1045 	struct cil_tree_node *temp_node = NULL;
1046 	struct cil_complex_symtab *symtab = extra_args;
1047 	struct cil_complex_symtab_key ckey;
1048 	struct cil_complex_symtab_datum datum;
1049 		typerule = rule_node->data;
1050 
1051 		ckey.key1 = (intptr_t)typerule->src;
1052 		ckey.key2 = (intptr_t)typerule->tgt;
1053 		ckey.key3 = (intptr_t)typerule->obj;
1054 		ckey.key4 = (intptr_t)typerule->rule_kind;
1055 
1056 		datum.data = node;
1057 
1058 		rc = cil_complex_symtab_insert(symtab, &ckey, &datum);
1059 		if (rc != SEPOL_OK) {
1060 			goto exit;
1061 		}
1062 
1063 		for (temp_node = rule_node->next;
1064 			temp_node != NULL;
1065 			temp_node = temp_node->next) {
1066 
1067 			if (temp_node->flavor == CIL_TYPE_RULE) {
1068 				typerule = temp_node->data;
1069 				if ((intptr_t)typerule->src == ckey.key1 &&
1070 					(intptr_t)typerule->tgt == ckey.key2 &&
1071 					(intptr_t)typerule->obj == ckey.key3 &&
1072 					(intptr_t)typerule->rule_kind == ckey.key4) {
1073 					cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line);
1074 					rc = SEPOL_ERR;
1075 					goto exit;
1076 				}
1077 			}
1078 		}
1079 		break;*/
1080 
1081 		//TODO Fix duplicate type_rule detection
1082 		break;
1083 	case CIL_CALL:
1084 		//Fall through to check content of call
1085 		break;
1086 	case CIL_TUNABLEIF:
1087 		//Fall through
1088 		break;
1089 	case CIL_NAMETYPETRANSITION:
1090 		/* While type transitions with file component are not allowed in
1091 		   booleanif statements if they don't have "*" as the file. We
1092 		   can't check that here. Or at least we won't right now. */
1093 		break;
1094 	default: {
1095 		const char * flavor = cil_node_to_string(node);
1096 		if (bif->preserved_tunable) {
1097 			cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor);
1098 		} else {
1099 			cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor);
1100 		}
1101 		goto exit;
1102 	}
1103 	}
1104 
1105 	rc = SEPOL_OK;
1106 exit:
1107 	return rc;
1108 }
1109 
__cil_verify_booleanif(struct cil_tree_node * node,struct cil_complex_symtab * symtab)1110 static int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
1111 {
1112 	int rc = SEPOL_ERR;
1113 	struct cil_booleanif *bif = (struct cil_booleanif*)node->data;
1114 	struct cil_tree_node *cond_block = node->cl_head;
1115 
1116 	while (cond_block != NULL) {
1117 		rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab);
1118 		if (rc != SEPOL_OK) {
1119 			goto exit;
1120 		}
1121 		cond_block = cond_block->next;
1122 	}
1123 
1124 	return SEPOL_OK;
1125 exit:
1126 	if (bif->preserved_tunable) {
1127 		cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)");
1128 	} else {
1129 		cil_tree_log(node, CIL_ERR, "Invalid booleanif");
1130 	}
1131 	return rc;
1132 }
1133 
__cil_verify_netifcon(struct cil_db * db,struct cil_tree_node * node)1134 static int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node)
1135 {
1136 	int rc = SEPOL_ERR;
1137 	struct cil_netifcon *netif = node->data;
1138 	struct cil_context *if_ctx = netif->if_context;
1139 	struct cil_context *pkt_ctx = netif->packet_context;
1140 
1141 	/* Verify only when anonymous */
1142 	if (if_ctx->datum.name == NULL) {
1143 		rc = __cil_verify_context(db, if_ctx);
1144 		if (rc != SEPOL_OK) {
1145 			goto exit;
1146 		}
1147 	}
1148 
1149 	/* Verify only when anonymous */
1150 	if (pkt_ctx->datum.name == NULL) {
1151 		rc = __cil_verify_context(db, pkt_ctx);
1152 		if (rc != SEPOL_OK) {
1153 			goto exit;
1154 		}
1155 	}
1156 
1157 	return SEPOL_OK;
1158 
1159 exit:
1160 	cil_tree_log(node, CIL_ERR, "Invalid netifcon");
1161 	return rc;
1162 }
1163 
__cil_verify_ibendportcon(struct cil_db * db,struct cil_tree_node * node)1164 static int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node)
1165 {
1166 	int rc = SEPOL_ERR;
1167 	struct cil_ibendportcon *ib_end_port = node->data;
1168 	struct cil_context *ctx = ib_end_port->context;
1169 
1170 	/* Verify only when anonymous */
1171 	if (!ctx->datum.name) {
1172 		rc = __cil_verify_context(db, ctx);
1173 		if (rc != SEPOL_OK)
1174 			goto exit;
1175 	}
1176 
1177 	return SEPOL_OK;
1178 
1179 exit:
1180 	cil_tree_log(node, CIL_ERR, "Invalid ibendportcon");
1181 	return rc;
1182 }
1183 
__cil_verify_genfscon(struct cil_db * db,struct cil_tree_node * node)1184 static int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node)
1185 {
1186 	int rc = SEPOL_ERR;
1187 	struct cil_genfscon *genfs = node->data;
1188 	struct cil_context *ctx = genfs->context;
1189 
1190 	/* Verify only when anonymous */
1191 	if (ctx->datum.name == NULL) {
1192 		rc = __cil_verify_context(db, ctx);
1193 		if (rc != SEPOL_OK) {
1194 			goto exit;
1195 		}
1196 	}
1197 
1198 	return SEPOL_OK;
1199 
1200 exit:
1201 	cil_tree_log(node, CIL_ERR, "Invalid genfscon");
1202 	return rc;
1203 }
1204 
__cil_verify_filecon(struct cil_db * db,struct cil_tree_node * node)1205 static int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node)
1206 {
1207 	int rc = SEPOL_ERR;
1208 	struct cil_filecon *file = node->data;
1209 	struct cil_context *ctx = file->context;
1210 
1211 	if (ctx == NULL) {
1212 		rc = SEPOL_OK;
1213 		goto exit;
1214 	}
1215 
1216 	/* Verify only when anonymous */
1217 	if (ctx->datum.name == NULL) {
1218 		rc = __cil_verify_context(db, ctx);
1219 		if (rc != SEPOL_OK) {
1220 			cil_tree_log(node, CIL_ERR, "Invalid filecon");
1221 			goto exit;
1222 		}
1223 	}
1224 
1225 	return SEPOL_OK;
1226 
1227 exit:
1228 	return rc;
1229 }
1230 
__cil_verify_nodecon(struct cil_db * db,struct cil_tree_node * node)1231 static int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node)
1232 {
1233 	int rc = SEPOL_ERR;
1234 	struct cil_nodecon *nodecon = node->data;
1235 	struct cil_context *ctx = nodecon->context;
1236 
1237 	/* Verify only when anonymous */
1238 	if (ctx->datum.name == NULL) {
1239 		rc = __cil_verify_context(db, ctx);
1240 		if (rc != SEPOL_OK) {
1241 			goto exit;
1242 		}
1243 	}
1244 
1245 	return SEPOL_OK;
1246 
1247 exit:
1248 	cil_tree_log(node, CIL_ERR, "Invalid nodecon");
1249 	return rc;
1250 }
1251 
__cil_verify_ibpkeycon(struct cil_db * db,struct cil_tree_node * node)1252 static int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node)
1253 {
1254 	int rc = SEPOL_ERR;
1255 	struct cil_ibpkeycon *pkey = node->data;
1256 	struct cil_context *ctx = pkey->context;
1257 
1258 	/* Verify only when anonymous */
1259 	if (!ctx->datum.name) {
1260 		rc = __cil_verify_context(db, ctx);
1261 		if (rc != SEPOL_OK)
1262 			goto exit;
1263 	}
1264 
1265 	return SEPOL_OK;
1266 
1267 exit:
1268 	cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon");
1269 	return rc;
1270 }
1271 
__cil_verify_portcon(struct cil_db * db,struct cil_tree_node * node)1272 static int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node)
1273 {
1274 	int rc = SEPOL_ERR;
1275 	struct cil_portcon *port = node->data;
1276 	struct cil_context *ctx = port->context;
1277 
1278 	/* Verify only when anonymous */
1279 	if (ctx->datum.name == NULL) {
1280 		rc = __cil_verify_context(db, ctx);
1281 		if (rc != SEPOL_OK) {
1282 			goto exit;
1283 		}
1284 	}
1285 
1286 	return SEPOL_OK;
1287 
1288 exit:
1289 	cil_tree_log(node, CIL_ERR, "Invalid portcon");
1290 	return rc;
1291 }
1292 
__cil_verify_pirqcon(struct cil_db * db,struct cil_tree_node * node)1293 static int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node)
1294 {
1295 	int rc = SEPOL_ERR;
1296 	struct cil_pirqcon *pirq = node->data;
1297 	struct cil_context *ctx = pirq->context;
1298 
1299 	/* Verify only when anonymous */
1300 	if (ctx->datum.name == NULL) {
1301 		rc = __cil_verify_context(db, ctx);
1302 		if (rc != SEPOL_OK) {
1303 			goto exit;
1304 		}
1305 	}
1306 
1307 	return SEPOL_OK;
1308 
1309 exit:
1310 	cil_tree_log(node, CIL_ERR, "Invalid pirqcon");
1311 	return rc;
1312 }
1313 
__cil_verify_iomemcon(struct cil_db * db,struct cil_tree_node * node)1314 static int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node)
1315 {
1316 	int rc = SEPOL_ERR;
1317 	struct cil_iomemcon *iomem = node->data;
1318 	struct cil_context *ctx = iomem->context;
1319 
1320 	/* Verify only when anonymous */
1321 	if (ctx->datum.name == NULL) {
1322 		rc = __cil_verify_context(db, ctx);
1323 		if (rc != SEPOL_OK) {
1324 			goto exit;
1325 		}
1326 	}
1327 
1328 	return SEPOL_OK;
1329 
1330 exit:
1331 	cil_tree_log(node, CIL_ERR, "Invalid iomemcon");
1332 	return rc;
1333 }
1334 
__cil_verify_ioportcon(struct cil_db * db,struct cil_tree_node * node)1335 static int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node)
1336 {
1337 	int rc = SEPOL_ERR;
1338 	struct cil_ioportcon *ioport = node->data;
1339 	struct cil_context *ctx = ioport->context;
1340 
1341 	/* Verify only when anonymous */
1342 	if (ctx->datum.name == NULL) {
1343 		rc = __cil_verify_context(db, ctx);
1344 		if (rc != SEPOL_OK) {
1345 			goto exit;
1346 		}
1347 	}
1348 
1349 	return SEPOL_OK;
1350 
1351 exit:
1352 	cil_tree_log(node, CIL_ERR, "Invalid ioportcon");
1353 	return rc;
1354 }
1355 
__cil_verify_pcidevicecon(struct cil_db * db,struct cil_tree_node * node)1356 static int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node)
1357 {
1358 	int rc = SEPOL_ERR;
1359 	struct cil_pcidevicecon *pcidev = node->data;
1360 	struct cil_context *ctx = pcidev->context;
1361 
1362 	/* Verify only when anonymous */
1363 	if (ctx->datum.name == NULL) {
1364 		rc = __cil_verify_context(db, ctx);
1365 		if (rc != SEPOL_OK) {
1366 			goto exit;
1367 		}
1368 	}
1369 
1370 	return SEPOL_OK;
1371 
1372 exit:
1373 	cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon");
1374 	return rc;
1375 }
1376 
__cil_verify_devicetreecon(struct cil_db * db,struct cil_tree_node * node)1377 static int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node)
1378 {
1379 	int rc = SEPOL_ERR;
1380 	struct cil_devicetreecon *dt = node->data;
1381 	struct cil_context *ctx = dt->context;
1382 
1383 	/* Verify only when anonymous */
1384 	if (ctx->datum.name == NULL) {
1385 		rc = __cil_verify_context(db, ctx);
1386 		if (rc != SEPOL_OK) {
1387 			goto exit;
1388 		}
1389 	}
1390 
1391 	return SEPOL_OK;
1392 
1393 exit:
1394 	cil_tree_log(node, CIL_ERR, "Invalid devicetreecon");
1395 	return rc;
1396 }
1397 
__cil_verify_fsuse(struct cil_db * db,struct cil_tree_node * node)1398 static int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node)
1399 {
1400 	int rc = SEPOL_ERR;
1401 	struct cil_fsuse *fsuse = node->data;
1402 	struct cil_context *ctx = fsuse->context;
1403 
1404 	/* Verify only when anonymous */
1405 	if (ctx->datum.name == NULL) {
1406 		rc = __cil_verify_context(db, ctx);
1407 		if (rc != SEPOL_OK) {
1408 			goto exit;
1409 		}
1410 	}
1411 
1412 	return SEPOL_OK;
1413 
1414 exit:
1415 	cil_tree_log(node, CIL_ERR, "Invalid fsuse");
1416 	return rc;
1417 }
1418 
__cil_verify_permissionx(struct cil_permissionx * permx,struct cil_tree_node * node)1419 static int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node *node)
1420 {
1421 	int rc;
1422 	struct cil_list *classes = NULL;
1423 	struct cil_list_item *item;
1424 	struct cil_class *class;
1425 	struct cil_symtab_datum *perm_datum;
1426 	char *kind_str;
1427 
1428 	switch (permx->kind) {
1429 		case CIL_PERMX_KIND_IOCTL:
1430 			kind_str = CIL_KEY_IOCTL;
1431 			break;
1432 		default:
1433 			cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind);
1434 			rc = SEPOL_ERR;
1435 			goto exit;
1436 	}
1437 
1438 	classes = cil_expand_class(permx->obj);
1439 
1440 	cil_list_for_each(item, classes) {
1441 		class = item->data;
1442 		rc = cil_symtab_get_datum(&class->perms, kind_str, &perm_datum);
1443 		if (rc == SEPOL_ENOENT) {
1444 			if (class->common != NULL) {
1445 				rc = cil_symtab_get_datum(&class->common->perms, kind_str, &perm_datum);
1446 			}
1447 
1448 			if (rc == SEPOL_ENOENT) {
1449 				cil_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", kind_str, class->datum.name);
1450 				rc = SEPOL_ERR;
1451 				goto exit;
1452 			}
1453 		}
1454 	}
1455 
1456 	rc = SEPOL_OK;
1457 
1458 exit:
1459 	if (classes != NULL) {
1460 		cil_list_destroy(&classes, CIL_FALSE);
1461 	}
1462 
1463 	return rc;
1464 }
1465 
__cil_verify_avrulex(struct cil_tree_node * node)1466 static int __cil_verify_avrulex(struct cil_tree_node *node)
1467 {
1468 	struct cil_avrule *avrulex = node->data;
1469 	return __cil_verify_permissionx(avrulex->perms.x.permx, node);
1470 }
1471 
__cil_verify_class(struct cil_tree_node * node)1472 static int __cil_verify_class(struct cil_tree_node *node)
1473 {
1474 	int rc = SEPOL_ERR;
1475 	struct cil_class *class = node->data;
1476 
1477 	if (class->common != NULL) {
1478 		struct cil_class *common = class->common;
1479 		struct cil_tree_node *common_node = common->datum.nodes->head->data;
1480 		struct cil_tree_node *curr_com_perm = NULL;
1481 
1482 		for (curr_com_perm = common_node->cl_head;
1483 			curr_com_perm != NULL;
1484 			curr_com_perm = curr_com_perm->next) {
1485 			struct cil_perm *com_perm = curr_com_perm->data;
1486 			struct cil_tree_node *curr_class_perm = NULL;
1487 
1488 			for (curr_class_perm = node->cl_head;
1489 				curr_class_perm != NULL;
1490 				curr_class_perm = curr_class_perm->next) {
1491 				struct cil_perm *class_perm = curr_class_perm->data;
1492 
1493 				if (com_perm->datum.name == class_perm->datum.name) {
1494 					cil_log(CIL_ERR, "Duplicate permissions between %s common and class declarations\n", class_perm->datum.name);
1495 					goto exit;
1496 				}
1497 			}
1498 		}
1499 	}
1500 
1501 	return SEPOL_OK;
1502 
1503 exit:
1504 	cil_tree_log(node, CIL_ERR, "Invalid class");
1505 	return rc;
1506 }
1507 
__cil_verify_policycap(struct cil_tree_node * node)1508 static int __cil_verify_policycap(struct cil_tree_node *node)
1509 {
1510 	int rc;
1511 	struct cil_policycap *polcap = node->data;
1512 
1513 	rc = sepol_polcap_getnum((const char*)polcap->datum.name);
1514 	if (rc == SEPOL_ERR) {
1515 		goto exit;
1516 	}
1517 
1518 	return SEPOL_OK;
1519 
1520 exit:
1521 	cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name);
1522 	return rc;
1523 }
1524 
__cil_verify_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1525 int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1526 {
1527 	int rc = SEPOL_ERR;
1528 	int *avrule_cnt = 0;
1529 	int *handleunknown;
1530 	int *mls;
1531 	int *nseuserdflt = 0;
1532 	int *pass = 0;
1533 	struct cil_args_verify *args = extra_args;
1534 	struct cil_complex_symtab *csymtab = NULL;
1535 	struct cil_db *db = NULL;
1536 
1537 	if (node == NULL || extra_args == NULL) {
1538 		goto exit;
1539 	}
1540 
1541 	db = args->db;
1542 	avrule_cnt = args->avrule_cnt;
1543 	handleunknown = args->handleunknown;
1544 	mls = args->mls;
1545 	nseuserdflt = args->nseuserdflt;
1546 	csymtab = args->csymtab;
1547 	pass = args->pass;
1548 
1549 	if (node->flavor == CIL_MACRO) {
1550 		*finished = CIL_TREE_SKIP_HEAD;
1551 		rc = SEPOL_OK;
1552 		goto exit;
1553 	} else if (node->flavor == CIL_BLOCK) {
1554 		struct cil_block *blk = node->data;
1555 		if (blk->is_abstract == CIL_TRUE) {
1556 			*finished = CIL_TREE_SKIP_HEAD;
1557 		}
1558 		rc = SEPOL_OK;
1559 		goto exit;
1560 	}
1561 
1562 	switch (*pass) {
1563 	case 0: {
1564 		switch (node->flavor) {
1565 		case CIL_USER:
1566 			rc = __cil_verify_user_post_eval(db, node);
1567 			break;
1568 		case CIL_SELINUXUSERDEFAULT:
1569 			(*nseuserdflt)++;
1570 			rc = SEPOL_OK;
1571 			break;
1572 		case CIL_ROLE:
1573 			rc = __cil_verify_role(node);
1574 			break;
1575 		case CIL_TYPE:
1576 			rc = __cil_verify_type(node);
1577 			break;
1578 		case CIL_AVRULE:
1579 			(*avrule_cnt)++;
1580 			rc = SEPOL_OK;
1581 			break;
1582 		case CIL_HANDLEUNKNOWN:
1583 			if (*handleunknown != -1) {
1584 				cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n");
1585 				rc = SEPOL_ERR;
1586 			} else {
1587 				*handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown;
1588 				rc = SEPOL_OK;
1589 			}
1590 			break;
1591 		case CIL_MLS:
1592 			if (*mls != -1) {
1593 				cil_log(CIL_ERR, "Policy can not have more than one mls\n");
1594 				rc = SEPOL_ERR;
1595 			} else {
1596 				*mls = ((struct cil_mls*)node->data)->value;
1597 				rc = SEPOL_OK;
1598 			}
1599 			break;
1600 		case CIL_ROLETRANSITION:
1601 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1602 			//rc = __cil_verify_rule(node, csymtab);
1603 			break;
1604 		case CIL_TYPE_RULE:
1605 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1606 			//rc = __cil_verify_rule(node, csymtab);
1607 			break;
1608 		case CIL_BOOLEANIF:
1609 			rc = __cil_verify_booleanif(node, csymtab);
1610 			*finished = CIL_TREE_SKIP_HEAD;
1611 			break;
1612 		case CIL_LEVELRANGE:
1613 			rc = __cil_verify_named_levelrange(db, node);
1614 			break;
1615 		case CIL_CLASS:
1616 			rc = __cil_verify_class(node);
1617 			break;
1618 		case CIL_POLICYCAP:
1619 			rc = __cil_verify_policycap(node);
1620 			break;
1621 		default:
1622 			rc = SEPOL_OK;
1623 			break;
1624 		}
1625 		break;
1626 	}
1627 	case 1:	{
1628 		switch (node->flavor) {
1629 		case CIL_CONTEXT:
1630 			rc = __cil_verify_named_context(db, node);
1631 			break;
1632 		case CIL_NETIFCON:
1633 			rc = __cil_verify_netifcon(db, node);
1634 			break;
1635 		case CIL_GENFSCON:
1636 			rc = __cil_verify_genfscon(db, node);
1637 			break;
1638 		case CIL_FILECON:
1639 			rc = __cil_verify_filecon(db, node);
1640 			break;
1641 		case CIL_NODECON:
1642 			rc = __cil_verify_nodecon(db, node);
1643 			break;
1644 		case CIL_IBPKEYCON:
1645 			rc = __cil_verify_ibpkeycon(db, node);
1646 			break;
1647 		case CIL_IBENDPORTCON:
1648 			rc = __cil_verify_ibendportcon(db, node);
1649 			break;
1650 		case CIL_PORTCON:
1651 			rc = __cil_verify_portcon(db, node);
1652 			break;
1653 		case CIL_PIRQCON:
1654 			rc = __cil_verify_pirqcon(db, node);
1655 			break;
1656 		case CIL_IOMEMCON:
1657 			rc = __cil_verify_iomemcon(db, node);
1658 			break;
1659 		case CIL_IOPORTCON:
1660 			rc = __cil_verify_ioportcon(db, node);
1661 			break;
1662 		case CIL_PCIDEVICECON:
1663 			rc = __cil_verify_pcidevicecon(db, node);
1664 			break;
1665 		case CIL_DEVICETREECON:
1666 			rc = __cil_verify_devicetreecon(db, node);
1667 			break;
1668 		case CIL_FSUSE:
1669 			rc = __cil_verify_fsuse(db, node);
1670 			break;
1671 		case CIL_AVRULEX:
1672 			rc = __cil_verify_avrulex(node);
1673 			break;
1674 		case CIL_PERMISSIONX:
1675 			rc = __cil_verify_permissionx(node->data, node);
1676 			break;
1677 		case CIL_RANGETRANSITION:
1678 			rc = SEPOL_OK;
1679 			break;
1680 		default:
1681 			rc = SEPOL_OK;
1682 			break;
1683 		}
1684 		break;
1685 	}
1686 	default:
1687 		rc = SEPOL_ERR;
1688 	}
1689 
1690 exit:
1691 	return rc;
1692 }
1693 
__add_perm_to_list(hashtab_key_t k,hashtab_datum_t d,void * args)1694 static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1695 {
1696 	struct cil_list *perm_list = (struct cil_list *)args;
1697 
1698 	cil_list_append(perm_list, CIL_DATUM, d);
1699 
1700 	return SEPOL_OK;
1701 }
1702 
__cil_verify_classperms(struct cil_list * classperms,struct cil_symtab_datum * orig,struct cil_symtab_datum * parent,struct cil_symtab_datum * cur,enum cil_flavor flavor,unsigned steps,unsigned limit)1703 static int __cil_verify_classperms(struct cil_list *classperms,
1704 				   struct cil_symtab_datum *orig,
1705 				   struct cil_symtab_datum *parent,
1706 				   struct cil_symtab_datum *cur,
1707 				   enum cil_flavor flavor,
1708 				   unsigned steps, unsigned limit)
1709 {
1710 	int rc = SEPOL_ERR;
1711 	struct cil_list_item *curr;
1712 
1713 	if (classperms == NULL) {
1714 		if (flavor == CIL_MAP_PERM) {
1715 			cil_tree_log(NODE(cur), CIL_ERR, "Map class %s does not have a classmapping for %s", parent->name, cur->name);
1716 		} else {
1717 			cil_tree_log(NODE(cur), CIL_ERR, "Classpermission %s does not have a classpermissionset", cur->name);
1718 		}
1719 		goto exit;
1720 	}
1721 
1722 	if (steps > 0 && orig == cur) {
1723 		if (flavor == CIL_MAP_PERM) {
1724 			cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", parent->name, cur->name);
1725 		} else {
1726 			cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving the set %s", cur->name);
1727 		}
1728 		goto exit;
1729 	} else {
1730 		steps++;
1731 		if (steps > limit) {
1732 			steps = 1;
1733 			limit *= 2;
1734 			orig = cur;
1735 		}
1736 	}
1737 
1738 	cil_list_for_each(curr, classperms) {
1739 		if (curr->flavor == CIL_CLASSPERMS) {
1740 			struct cil_classperms *cp = curr->data;
1741 			if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */
1742 				struct cil_list_item *i = NULL;
1743 				cil_list_for_each(i, cp->perms) {
1744 					if (i->flavor != CIL_OP) {
1745 						struct cil_perm *cmp = i->data;
1746 						rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
1747 						if (rc != SEPOL_OK) {
1748 							goto exit;
1749 						}
1750 					} else {
1751 						enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data;
1752 						if (op == CIL_ALL) {
1753 							struct cil_class *mc = cp->class;
1754 							struct cil_list *perm_list;
1755 							struct cil_list_item *j = NULL;
1756 
1757 							cil_list_init(&perm_list, CIL_MAP_PERM);
1758 							cil_symtab_map(&mc->perms, __add_perm_to_list, perm_list);
1759 							cil_list_for_each(j, perm_list) {
1760 								struct cil_perm *cmp = j->data;
1761 								rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
1762 								if (rc != SEPOL_OK) {
1763 									cil_list_destroy(&perm_list, CIL_FALSE);
1764 									goto exit;
1765 								}
1766 							}
1767 							cil_list_destroy(&perm_list, CIL_FALSE);
1768 						}
1769 					}
1770 				}
1771 			}
1772 		} else { /* SET */
1773 			struct cil_classperms_set *cp_set = curr->data;
1774 			struct cil_classpermission *cp = cp_set->set;
1775 			rc = __cil_verify_classperms(cp->classperms, orig, NULL, &cp->datum, CIL_CLASSPERMISSION, steps, limit);
1776 			if (rc != SEPOL_OK) {
1777 				goto exit;
1778 			}
1779 		}
1780 	}
1781 
1782 	return SEPOL_OK;
1783 
1784 exit:
1785 	return SEPOL_ERR;
1786 }
1787 
__cil_verify_classpermission(struct cil_tree_node * node)1788 static int __cil_verify_classpermission(struct cil_tree_node *node)
1789 {
1790 	struct cil_classpermission *cp = node->data;
1791 
1792 	return __cil_verify_classperms(cp->classperms, &cp->datum, NULL, &cp->datum, CIL_CLASSPERMISSION, 0, 2);
1793 }
1794 
1795 struct cil_verify_map_args {
1796 	struct cil_class *class;
1797 	struct cil_tree_node *node;
1798 	int rc;
1799 };
1800 
__verify_map_perm_classperms(hashtab_key_t k,hashtab_datum_t d,void * args)1801 static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1802 {
1803 	struct cil_verify_map_args *map_args = args;
1804 	struct cil_perm *cmp = (struct cil_perm *)d;
1805 	int rc;
1806 
1807 	rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2);
1808 	if (rc != SEPOL_OK) {
1809 		map_args->rc = rc;
1810 	}
1811 
1812 	return SEPOL_OK;
1813 }
1814 
__cil_verify_map_class(struct cil_tree_node * node)1815 static int __cil_verify_map_class(struct cil_tree_node *node)
1816 {
1817 	struct cil_class *mc = node->data;
1818 	struct cil_verify_map_args map_args;
1819 
1820 	map_args.class = mc;
1821 	map_args.node = node;
1822 	map_args.rc = SEPOL_OK;
1823 
1824 	cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args);
1825 
1826 	if (map_args.rc != SEPOL_OK) {
1827 		return SEPOL_ERR;
1828 	}
1829 
1830 	return SEPOL_OK;
1831 }
1832 
__cil_pre_verify_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1833 int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
1834 {
1835 	int rc = SEPOL_OK;
1836 
1837 	switch (node->flavor) {
1838 	case CIL_MACRO: {
1839 		*finished = CIL_TREE_SKIP_HEAD;
1840 		break;
1841 	}
1842 	case CIL_BLOCK: {
1843 		struct cil_block *blk = node->data;
1844 		if (blk->is_abstract == CIL_TRUE) {
1845 			*finished = CIL_TREE_SKIP_HEAD;
1846 		}
1847 		break;
1848 	}
1849 	case CIL_USER:
1850 		rc = __cil_verify_user_pre_eval(node);
1851 		break;
1852 	case CIL_MAP_CLASS:
1853 		rc = __cil_verify_map_class(node);
1854 		break;
1855 	case CIL_CLASSPERMISSION:
1856 		rc = __cil_verify_classpermission(node);
1857 		break;
1858 	case CIL_USERATTRIBUTE:
1859 	case CIL_ROLEATTRIBUTE:
1860 	case CIL_TYPEATTRIBUTE:
1861 	case CIL_CATSET: {
1862 		struct cil_stack *stack;
1863 		cil_stack_init(&stack);
1864 		rc = cil_verify_no_self_reference(node->flavor, node->data, stack);
1865 		cil_stack_destroy(&stack);
1866 		break;
1867 	}
1868 	default:
1869 		rc = SEPOL_OK;
1870 		break;
1871 	}
1872 
1873 	return rc;
1874 }
1875