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
51static 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
95int 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
142exit:
143	cil_log(CIL_ERR, "Invalid name\n");
144	return rc;
145}
146
147int __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
183exit:
184	cil_log(CIL_ERR, "Invalid syntax\n");
185	return SEPOL_ERR;
186}
187
188int 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
248exit:
249	return SEPOL_ERR;
250}
251
252int 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
312exit:
313	return SEPOL_ERR;
314}
315
316int 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
361exit:
362	return SEPOL_ERR;
363}
364
365int 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
400int 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
418static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack);
419
420static 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
444static 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
494int __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
516exit:
517	cil_log(CIL_ERR,"Invalid Range syntax\n");
518	return rc;
519}
520
521struct cil_args_verify_order {
522	uint32_t *flavor;
523};
524
525int __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
561int __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
573int __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
594static 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
609static 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
619static 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
653static 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
675exit:
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
682static 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
705exit:
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
710static 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
738exit:
739	return rc;
740}
741
742static 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;
753exit:
754	cil_tree_log(node, CIL_ERR, "Invalid named range");
755	return rc;
756}
757
758static 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;
793exit:
794	cil_tree_log(node, CIL_ERR, "Invalid user");
795	return rc;
796}
797
798static 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;
812exit:
813	cil_tree_log(node, CIL_ERR, "Invalid user");
814	return rc;
815}
816
817static 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;
843exit:
844	cil_tree_log(node, CIL_ERR, "Invalid role");
845	return rc;
846}
847
848static 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;
874exit:
875	cil_tree_log(node, CIL_ERR, "Invalid type");
876	return rc;
877}
878
879static 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;
952exit:
953	cil_log(CIL_ERR, "Invalid context\n");
954	return rc;
955}
956
957static 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;
968exit:
969	cil_tree_log(node, CIL_ERR, "Invalid named context");
970	return rc;
971}
972
973/*
974static 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;
1016exit:
1017	cil_tree_log(node, CIL_ERR, "Invalid rule");
1018	return rc;
1019}
1020*/
1021
1022static 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;
1106exit:
1107	return rc;
1108}
1109
1110static 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;
1125exit:
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
1134static 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
1159exit:
1160	cil_tree_log(node, CIL_ERR, "Invalid netifcon");
1161	return rc;
1162}
1163
1164static 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
1179exit:
1180	cil_tree_log(node, CIL_ERR, "Invalid ibendportcon");
1181	return rc;
1182}
1183
1184static 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
1200exit:
1201	cil_tree_log(node, CIL_ERR, "Invalid genfscon");
1202	return rc;
1203}
1204
1205static 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
1227exit:
1228	return rc;
1229}
1230
1231static 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
1247exit:
1248	cil_tree_log(node, CIL_ERR, "Invalid nodecon");
1249	return rc;
1250}
1251
1252static 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
1267exit:
1268	cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon");
1269	return rc;
1270}
1271
1272static 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
1288exit:
1289	cil_tree_log(node, CIL_ERR, "Invalid portcon");
1290	return rc;
1291}
1292
1293static 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
1309exit:
1310	cil_tree_log(node, CIL_ERR, "Invalid pirqcon");
1311	return rc;
1312}
1313
1314static 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
1330exit:
1331	cil_tree_log(node, CIL_ERR, "Invalid iomemcon");
1332	return rc;
1333}
1334
1335static 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
1351exit:
1352	cil_tree_log(node, CIL_ERR, "Invalid ioportcon");
1353	return rc;
1354}
1355
1356static 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
1372exit:
1373	cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon");
1374	return rc;
1375}
1376
1377static 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
1393exit:
1394	cil_tree_log(node, CIL_ERR, "Invalid devicetreecon");
1395	return rc;
1396}
1397
1398static 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
1414exit:
1415	cil_tree_log(node, CIL_ERR, "Invalid fsuse");
1416	return rc;
1417}
1418
1419static 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
1458exit:
1459	if (classes != NULL) {
1460		cil_list_destroy(&classes, CIL_FALSE);
1461	}
1462
1463	return rc;
1464}
1465
1466static 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
1472static 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
1503exit:
1504	cil_tree_log(node, CIL_ERR, "Invalid class");
1505	return rc;
1506}
1507
1508static 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
1520exit:
1521	cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name);
1522	return rc;
1523}
1524
1525int __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
1690exit:
1691	return rc;
1692}
1693
1694static 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
1703static 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
1784exit:
1785	return SEPOL_ERR;
1786}
1787
1788static 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
1795struct cil_verify_map_args {
1796	struct cil_class *class;
1797	struct cil_tree_node *node;
1798	int rc;
1799};
1800
1801static 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
1815static 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
1833int __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