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