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 
47 #include "cil_verify.h"
48 
__cil_verify_name(const char * name)49 int __cil_verify_name(const char *name)
50 {
51 	int rc = SEPOL_ERR;
52 	int len = strlen(name);
53 	int i = 0;
54 
55 	if (len >= CIL_MAX_NAME_LENGTH) {
56 		cil_log(CIL_ERR, "Name length greater than max name length of %d",
57 			CIL_MAX_NAME_LENGTH);
58 		rc = SEPOL_ERR;
59 		goto exit;
60 	}
61 
62 	if (!isalpha(name[0])) {
63 			cil_log(CIL_ERR, "First character in %s is not a letter\n", name);
64 			goto exit;
65 	}
66 
67 	for (i = 1; i < len; i++) {
68 		if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
69 			cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
70 			goto exit;
71 		}
72 	}
73 	return SEPOL_OK;
74 
75 exit:
76 	cil_log(CIL_ERR, "Invalid name\n");
77 	return rc;
78 }
79 
__cil_verify_syntax(struct cil_tree_node * parse_current,enum cil_syntax s[],int len)80 int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len)
81 {
82 	int rc = SEPOL_ERR;
83 	int num_extras = 0;
84 	struct cil_tree_node *c = parse_current;
85 	int i = 0;
86 	while (i < len) {
87 		if ((s[i] & CIL_SYN_END) && c == NULL) {
88 			break;
89 		}
90 
91 		if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) {
92 			if (c == NULL) {
93 				if (num_extras > 0) {
94 					i++;
95 					continue;
96 				} else {
97 					goto exit;
98 				}
99 			} else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) {
100 				c = c->next;
101 				num_extras++;
102 				continue;
103 			} else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) {
104 				c = c->next;
105 				num_extras++;
106 				continue;
107 			}
108 		}
109 
110 		if (c == NULL) {
111 			goto exit;
112 		}
113 
114 		if (s[i] & CIL_SYN_STRING) {
115 			if (c->data != NULL && c->cl_head == NULL) {
116 				c = c->next;
117 				i++;
118 				continue;
119 			}
120 		}
121 
122 		if (s[i] & CIL_SYN_LIST) {
123 			if (c->data == NULL && c->cl_head != NULL) {
124 				c = c->next;
125 				i++;
126 				continue;
127 			}
128 		}
129 
130 		if (s[i] & CIL_SYN_EMPTY_LIST) {
131 			if (c->data == NULL && c->cl_head == NULL) {
132 				c = c->next;
133 				i++;
134 				continue;
135 			}
136 		}
137 		goto exit;
138 	}
139 	return SEPOL_OK;
140 
141 exit:
142 	cil_log(CIL_ERR, "Invalid syntax\n");
143 	return rc;
144 }
145 
cil_verify_expr_syntax(struct cil_tree_node * current,enum cil_flavor op,enum cil_flavor expr_flavor)146 int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor)
147 {
148 	int rc;
149 	enum cil_syntax syntax[] = {
150 		CIL_SYN_STRING,
151 		CIL_SYN_STRING | CIL_SYN_LIST,
152 		CIL_SYN_STRING | CIL_SYN_LIST,
153 		CIL_SYN_END
154 	};
155 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
156 
157 	switch (op) {
158 	case CIL_NOT:
159 		syntax[2] = CIL_SYN_END;
160 		syntax_len = 3;
161 		break;
162 	case CIL_AND:
163 	case CIL_OR:
164 	case CIL_XOR:
165 		break;
166 	case CIL_EQ:
167 	case CIL_NEQ:
168 		if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) {
169 			cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data);
170 			goto exit;
171 		}
172 		break;
173 	case CIL_ALL:
174 		if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) {
175 			cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data);
176 			goto exit;
177 		}
178 		syntax[1] = CIL_SYN_END;
179 		syntax_len = 2;
180 		break;
181 	case CIL_RANGE:
182 		if (expr_flavor != CIL_CAT) {
183 			cil_log(CIL_ERR,"Operator (%s) only valid for catset expression\n", (char*)current->data);
184 			goto exit;
185 		}
186 		syntax[1] = CIL_SYN_STRING;
187 		syntax[2] = CIL_SYN_STRING;
188 		break;
189 	case CIL_NONE: /* String or List */
190 		syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS;
191 		syntax[1] = CIL_SYN_END;
192 		syntax_len = 2;
193 		break;
194 	default:
195 		cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data);
196 		goto exit;
197 	}
198 
199 	rc = __cil_verify_syntax(current, syntax, syntax_len);
200 	if (rc != SEPOL_OK) {
201 		goto exit;
202 	}
203 
204 	return SEPOL_OK;
205 
206 exit:
207 	return SEPOL_ERR;
208 }
209 
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)210 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)
211 {
212 	if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) {
213 		if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) {
214 			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");
215 			goto exit;
216 		} else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) {
217 			if (expr_flavor != CIL_MLSVALIDATETRANS) {
218 				cil_log(CIL_ERR, "u3, r3, and t3 can only be used with mlsvalidatetrans rules\n");
219 				goto exit;
220 			}
221 		}
222 	} else {
223 		if (r_flavor == CIL_CONS_U2) {
224 			if (op != CIL_EQ && op != CIL_NEQ) {
225 				cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
226 				goto exit;
227 			} else if (l_flavor != CIL_CONS_U1) {
228 				cil_log(CIL_ERR, "u2 on the right side must be used with u1 on the left\n");
229 				goto exit;
230 			}
231 		} else if (r_flavor == CIL_CONS_R2) {
232 			if (l_flavor != CIL_CONS_R1) {
233 				cil_log(CIL_ERR, "r2 on the right side must be used with r1 on the left\n");
234 				goto exit;
235 			}
236 		} else if (r_flavor == CIL_CONS_T2) {
237 			if (op != CIL_EQ && op != CIL_NEQ) {
238 				cil_log(CIL_ERR, "t2 on the right side must be used with eq or neq as the operator\n");
239 				goto exit;
240 			} else if (l_flavor != CIL_CONS_T1) {
241 				cil_log(CIL_ERR, "t2 on the right side must be used with t1 on the left\n");
242 				goto exit;
243 			}
244 		} else if (r_flavor == CIL_CONS_L2) {
245 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_H1) {
246 				cil_log(CIL_ERR, "l2 on the right side must be used with l1 or h1 on the left\n");
247 				goto exit;
248 			}
249 		} else if (r_flavor == CIL_CONS_H2) {
250 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_L2 && l_flavor != CIL_CONS_H1 ) {
251 				cil_log(CIL_ERR, "h2 on the right side must be used with l1, l2, or h1 on the left\n");
252 				goto exit;
253 			}
254 		} else if (r_flavor == CIL_CONS_H1) {
255 			if (l_flavor != CIL_CONS_L1) {
256 				cil_log(CIL_ERR, "h1 on the right side must be used with l1 on the left\n");
257 				goto exit;
258 			}
259 		}
260 	}
261 
262 	return SEPOL_OK;
263 
264 exit:
265 	return SEPOL_ERR;
266 }
267 
cil_verify_constraint_expr_syntax(struct cil_tree_node * current,enum cil_flavor op)268 int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op)
269 {
270 	int rc;
271 	enum cil_syntax syntax[] = {
272 		CIL_SYN_STRING,
273 		CIL_SYN_END,
274 		CIL_SYN_END,
275 		CIL_SYN_END
276 	};
277 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
278 
279 	switch (op) {
280 	case CIL_NOT:
281 		syntax[1] = CIL_SYN_LIST;
282 		syntax_len--;
283 		break;
284 	case CIL_AND:
285 	case CIL_OR:
286 		syntax[1] = CIL_SYN_LIST;
287 		syntax[2] = CIL_SYN_LIST;
288 		break;
289 	case CIL_EQ:
290 	case CIL_NEQ:
291 		syntax[1] = CIL_SYN_STRING;
292 		syntax[2] = CIL_SYN_STRING | CIL_SYN_LIST;
293 		break;
294 	case CIL_CONS_DOM:
295 	case CIL_CONS_DOMBY:
296 	case CIL_CONS_INCOMP:
297 		syntax[1] = CIL_SYN_STRING;
298 		syntax[2] = CIL_SYN_STRING;
299 		break;
300 	default:
301 		cil_log(CIL_ERR, "Invalid operator (%s) for constraint expression\n", (char*)current->data);
302 		goto exit;
303 	}
304 
305 	rc = __cil_verify_syntax(current, syntax, syntax_len);
306 	if (rc != SEPOL_OK) {
307 		cil_log(CIL_ERR, "Invalid constraint syntax\n");
308 		goto exit;
309 	}
310 
311 	return SEPOL_OK;
312 
313 exit:
314 	return SEPOL_ERR;
315 }
316 
cil_verify_no_self_reference(struct cil_symtab_datum * datum,struct cil_list * datum_list)317 int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
318 {
319 	struct cil_list_item *i;
320 
321 	cil_list_for_each(i, datum_list) {
322 		if (i->flavor == CIL_DATUM) {
323 			struct cil_symtab_datum *d = i->data;
324 			if (d == datum) {
325 				cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name);
326 				return SEPOL_ERR;
327 			}
328 		} else if (i->flavor == CIL_LIST) {
329 			int rc = cil_verify_no_self_reference(datum, i->data);
330 			if (rc != SEPOL_OK) {
331 				return SEPOL_ERR;
332 			}
333 		}
334 	}
335 
336 	return SEPOL_OK;
337 }
338 
__cil_verify_ranges(struct cil_list * list)339 int __cil_verify_ranges(struct cil_list *list)
340 {
341 	int rc = SEPOL_ERR;
342 	struct cil_list_item *curr;
343 	struct cil_list_item *range = NULL;
344 
345 	if (list == NULL || list->head == NULL) {
346 		goto exit;
347 	}
348 
349 	cil_list_for_each(curr, list) {
350 		/* range */
351 		if (curr->flavor == CIL_LIST) {
352 			range = ((struct cil_list*)curr->data)->head;
353 			if (range == NULL || range->next == NULL || range->next->next != NULL) {
354 				goto exit;
355 			}
356 		}
357 	}
358 
359 	return SEPOL_OK;
360 
361 exit:
362 	cil_log(CIL_ERR,"Invalid Range syntax\n");
363 	return rc;
364 }
365 
366 struct cil_args_verify_order {
367 	uint32_t *flavor;
368 };
369 
__cil_verify_ordered_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)370 int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
371 {
372 	struct cil_args_verify_order *args = extra_args;
373 	uint32_t *flavor = args->flavor;
374 
375 	if (node->flavor == *flavor) {
376 		if (node->flavor == CIL_SID) {
377 			struct cil_sid *sid = node->data;
378 			if (sid->ordered == CIL_FALSE) {
379 				cil_log(CIL_ERR, "SID %s not in sidorder statement at line %d of %s\n", sid->datum.name, node->line, node->path);
380 				return SEPOL_ERR;
381 			}
382 		} else if (node->flavor == CIL_CLASS) {
383 			struct cil_class *class = node->data;
384 			if (class->ordered == CIL_FALSE) {
385 				cil_log(CIL_ERR, "Class %s not in classorder statement at line %d of %s\n", class->datum.name, node->line, node->path);
386 				return SEPOL_ERR;
387 			}
388 		} else if (node->flavor == CIL_CAT) {
389 			struct cil_cat *cat = node->data;
390 			if (cat->ordered == CIL_FALSE) {
391 				cil_log(CIL_ERR, "Category %s not in categoryorder statement at line %d of %s\n", cat->datum.name, node->line, node->path);
392 				return SEPOL_ERR;
393 			}
394 		} else if (node->flavor == CIL_SENS) {
395 			struct cil_sens *sens = node->data;
396 			if (sens->ordered == CIL_FALSE) {
397 				cil_log(CIL_ERR, "Sensitivity %s not in sensitivityorder statement at line %d of %s\n", sens->datum.name, node->line, node->path);
398 				return SEPOL_ERR;
399 			}
400 		}
401 	}
402 
403 	return SEPOL_OK;
404 }
405 
__cil_verify_ordered(struct cil_tree_node * current,enum cil_flavor flavor)406 int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor)
407 {
408 	struct cil_args_verify_order extra_args;
409 	int rc = SEPOL_ERR;
410 
411 	extra_args.flavor = &flavor;
412 
413 	rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args);
414 
415 	return rc;
416 }
417 
__cil_verify_initsids(struct cil_list * sids)418 int __cil_verify_initsids(struct cil_list *sids)
419 {
420 	int rc = SEPOL_OK;
421 	struct cil_list_item *i;
422 
423 	if (sids->head == NULL) {
424 		cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n");
425 		return SEPOL_ERR;
426 	}
427 
428 	cil_list_for_each(i, sids) {
429 		struct cil_sid *sid = i->data;
430 		if (sid->context == NULL) {
431 			struct cil_tree_node *node = sid->datum.nodes->head->data;
432 			cil_log(CIL_ERR, "No context assigned to SID %s declared at line %d in %s\n",sid->datum.name, node->line, node->path);
433 			rc = SEPOL_ERR;
434 		}
435 	}
436 
437 	return rc;
438 }
439 
__cil_is_cat_in_cats(struct cil_cat * cat,struct cil_cats * cats)440 int __cil_is_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
441 {
442 	struct cil_list_item *i;
443 
444 	cil_list_for_each(i, cats->datum_expr) {
445 		struct cil_cat *c = i->data;
446 		if (c == cat) {
447 			return CIL_TRUE;
448 		}
449 	}
450 
451 	return CIL_FALSE;
452 }
453 
454 
__cil_verify_cat_in_cats(struct cil_cat * cat,struct cil_cats * cats)455 int __cil_verify_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
456 {
457 	if (__cil_is_cat_in_cats(cat, cats) != CIL_TRUE) {
458 		cil_log(CIL_ERR, "Failed to find category %s in category list\n", cat->datum.name);
459 		return SEPOL_ERR;
460 	}
461 
462 	return SEPOL_OK;
463 }
464 
__cil_verify_cats_associated_with_sens(struct cil_sens * sens,struct cil_cats * cats)465 int __cil_verify_cats_associated_with_sens(struct cil_sens *sens, struct cil_cats *cats)
466 {
467 	int rc = SEPOL_OK;
468 	struct cil_list_item *i, *j;
469 
470 	if (!cats) {
471 		return SEPOL_OK;
472 	}
473 
474 	if (!sens->cats_list) {
475 		cil_log(CIL_ERR, "No categories can be used with sensitivity %s\n", sens->datum.name);
476 		return SEPOL_ERR;
477 	}
478 
479 	cil_list_for_each(i, cats->datum_expr) {
480 		struct cil_cat *cat = i->data;
481 		int ok = CIL_FALSE;
482 		cil_list_for_each(j, sens->cats_list) {
483 			if (__cil_is_cat_in_cats(cat, j->data) == CIL_TRUE) {
484 				ok = CIL_TRUE;
485 				break;
486 			}
487 		}
488 
489 		if (ok != CIL_TRUE) {
490 			cil_log(CIL_ERR, "Category %s cannot be used with sensitivity %s\n",
491 					cat->datum.name, sens->datum.name);
492 			rc = SEPOL_ERR;
493 		}
494 	}
495 
496 	return rc;
497 }
498 
__cil_verify_levelrange_sensitivity(struct cil_db * db,struct cil_sens * low,struct cil_sens * high)499 int __cil_verify_levelrange_sensitivity(struct cil_db *db, struct cil_sens *low, struct cil_sens *high)
500 {
501 	struct cil_list_item *curr;
502 	int found = CIL_FALSE;
503 	int rc = SEPOL_ERR;
504 
505 	cil_list_for_each(curr, db->sensitivityorder) {
506 		if (curr->data == low) {
507 			found = CIL_TRUE;
508 		}
509 
510 		if ((found == CIL_TRUE) && (curr->data == high)) {
511 			break;
512 		}
513 	}
514 
515 	if (found != CIL_TRUE || curr == NULL) {
516 		goto exit;
517 	}
518 
519 	return SEPOL_OK;
520 
521 exit:
522 	cil_log(CIL_ERR, "Sensitivity %s does not dominate %s\n",
523 		high->datum.name, low->datum.name);
524 	return rc;
525 
526 }
527 
__cil_verify_levelrange_cats(struct cil_cats * low,struct cil_cats * high)528 int __cil_verify_levelrange_cats(struct cil_cats *low, struct cil_cats *high)
529 {
530 	int rc = SEPOL_ERR;
531 	struct cil_list_item *item;
532 
533 	if (low == NULL || (low == NULL && high == NULL)) {
534 		return SEPOL_OK;
535 	}
536 
537 	if (high == NULL) {
538 		rc = SEPOL_ERR;
539 		goto exit;
540 	}
541 
542 	cil_list_for_each(item, low->datum_expr) {
543 		rc = __cil_verify_cat_in_cats(item->data, high);
544 		if (rc != SEPOL_OK) {
545 			goto exit;
546 		}
547 	}
548 
549 	return SEPOL_OK;
550 
551 exit:
552 	cil_log(CIL_ERR, "Low level category set must be a subset of the high level category set\n");
553 	return rc;
554 }
555 
__cil_verify_levelrange(struct cil_db * db,struct cil_levelrange * lr)556 int __cil_verify_levelrange(struct cil_db *db, struct cil_levelrange *lr)
557 {
558 	int rc = SEPOL_ERR;
559 
560 	rc = __cil_verify_levelrange_sensitivity(db, lr->low->sens, lr->high->sens);
561 	if (rc != SEPOL_OK) {
562 		goto exit;
563 	}
564 
565 	rc = __cil_verify_levelrange_cats(lr->low->cats, lr->high->cats);
566 	if (rc != SEPOL_OK) {
567 		goto exit;
568 	}
569 
570 	rc = __cil_verify_cats_associated_with_sens(lr->low->sens, lr->low->cats);
571 	if (rc != SEPOL_OK) {
572 		cil_log(CIL_ERR, "Low level sensitivity and categories are not associated\n");
573 		goto exit;
574 	}
575 
576 	rc = __cil_verify_cats_associated_with_sens(lr->high->sens, lr->high->cats);
577 	if (rc != SEPOL_OK) {
578 		cil_log(CIL_ERR, "High level sensitivity and categories are not associated\n");
579 		goto exit;
580 	}
581 
582 	return SEPOL_OK;
583 
584 exit:
585 	return rc;
586 }
587 
__cil_verify_named_levelrange(struct cil_db * db,struct cil_tree_node * node)588 int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node)
589 {
590 	int rc = SEPOL_ERR;
591 	struct cil_levelrange *lr = node->data;
592 
593 	rc = __cil_verify_levelrange(db, lr);
594 	if (rc != SEPOL_OK) {
595 		goto exit;
596 	}
597 
598 	return SEPOL_OK;
599 exit:
600 	cil_log(CIL_ERR, "Invalid named range at line %d of %s\n", node->line, node->path);
601 	return rc;
602 }
603 
__cil_verify_user(struct cil_db * db,struct cil_tree_node * node)604 int __cil_verify_user(struct cil_db *db, struct cil_tree_node *node)
605 {
606 	int rc = SEPOL_ERR;
607 	struct cil_user *user = node->data;
608 
609 	if (user->dftlevel == NULL) {
610 		cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name);
611 		goto exit;
612 	} else if (user->range == NULL) {
613 		cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name);
614 		goto exit;
615 	} else if (user->bounds != NULL) {
616 		int steps = 0;
617 		int limit = 2;
618 		struct cil_user *u1 = user;
619 		struct cil_user *u2 = user->bounds;
620 
621 		while (u2 != NULL) {
622 			if (u1 == u2) {
623 				cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name);
624 				goto exit;
625 			}
626 
627 			if (steps == limit) {
628 				steps = 0;
629 				limit *= 2;
630 				u1 = u2;
631 			}
632 
633 			u2 = u2->bounds;
634 			steps++;
635 		}
636 	}
637 
638 	/* Verify user range only if anonymous */
639 	if (user->range->datum.name == NULL) {
640 		rc = __cil_verify_levelrange(db, user->range);
641 		if (rc != SEPOL_OK) {
642 			goto exit;
643 		}
644 	}
645 
646 	return SEPOL_OK;
647 exit:
648 	cil_log(CIL_ERR, "Invalid user at line %d of %s\n", node->line, node->path);
649 	return rc;
650 }
651 
__cil_verify_role(struct cil_tree_node * node)652 int __cil_verify_role(struct cil_tree_node *node)
653 {
654 	int rc = SEPOL_ERR;
655 	struct cil_role *role = node->data;
656 	int steps = 0;
657 	int limit = 2;
658 	struct cil_role *r1 = role;
659 	struct cil_role *r2 = role->bounds;
660 
661 	while (r2 != NULL) {
662 		if (r1 == r2) {
663 			cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name);
664 			goto exit;
665 		}
666 
667 		if (steps == limit) {
668 			steps = 0;
669 			limit *= 2;
670 			r1 = r2;
671 		}
672 
673 		r2 = r2->bounds;
674 		steps++;
675 	}
676 
677 	return SEPOL_OK;
678 exit:
679 	cil_log(CIL_ERR, "Invalid role at line %d of %s\n", node->line, node->path);
680 	return rc;
681 }
682 
__cil_verify_type(struct cil_tree_node * node)683 int __cil_verify_type(struct cil_tree_node *node)
684 {
685 	int rc = SEPOL_ERR;
686 	struct cil_type *type = node->data;
687 	int steps = 0;
688 	int limit = 2;
689 	struct cil_type *t1 = type;
690 	struct cil_type *t2 = type->bounds;
691 
692 	while (t2 != NULL) {
693 		if (t1 == t2) {
694 			cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name);
695 			goto exit;
696 		}
697 
698 		if (steps == limit) {
699 			steps = 0;
700 			limit *= 2;
701 			t1 = t2;
702 		}
703 
704 		t2 = t2->bounds;
705 		steps++;
706 	}
707 
708 	return SEPOL_OK;
709 exit:
710 	cil_log(CIL_ERR, "Invalid type at line %d of %s\n", node->line, node->path);
711 	return rc;
712 }
713 
__cil_verify_context(struct cil_db * db,struct cil_context * ctx)714 int __cil_verify_context(struct cil_db *db, struct cil_context *ctx)
715 {
716 	int rc = SEPOL_ERR;
717 	struct cil_user *user = ctx->user;
718 	struct cil_role *role = ctx->role;
719 	struct cil_type *type = ctx->type;
720 	struct cil_level *user_low = user->range->low;
721 	struct cil_level *user_high = user->range->high;
722 	struct cil_level *ctx_low = ctx->range->low;
723 	struct cil_level *ctx_high = ctx->range->high;
724 	struct cil_list *sensitivityorder = db->sensitivityorder;
725 	struct cil_list_item *curr;
726 	int found = CIL_FALSE;
727 
728 	if (user->roles != NULL) {
729 		cil_list_for_each(curr, user->roles) {
730 			struct cil_role *userrole = curr->data;
731 			if (userrole == role) {
732 				break;
733 			}
734 		}
735 
736 		if (curr == NULL) {
737 			cil_log(CIL_ERR, "Role %s is invalid for user %s\n",
738 					ctx->role_str, ctx->user_str);
739 			rc = SEPOL_ERR;
740 			goto exit;
741 		}
742 	} else {
743 		cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str);
744 		rc = SEPOL_ERR;
745 		goto exit;
746 	}
747 
748 	if (role->types != NULL) {
749 		if (!ebitmap_get_bit(role->types, type->value)) {
750 			cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str);
751 			rc = SEPOL_ERR;
752 			goto exit;
753 		}
754 	} else {
755 		cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str);
756 		rc = SEPOL_ERR;
757 		goto exit;
758 	}
759 
760 	/* Verify range only when anonymous */
761 	if (ctx->range->datum.name == NULL) {
762 		rc = __cil_verify_levelrange(db, ctx->range);
763 		if (rc != SEPOL_OK) {
764 			goto exit;
765 		}
766 	}
767 
768 	for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) {
769 		struct cil_sens *sens = curr->data;
770 
771 		if (found == CIL_FALSE) {
772 			if (sens == user_low->sens) {
773 				found = CIL_TRUE;
774 			} else if (sens == ctx_low->sens) {
775 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
776 					ctx->range_str, ctx->user_str);
777 				rc = SEPOL_ERR;
778 				goto exit;
779 			}
780 		}
781 
782 		if (found == CIL_TRUE) {
783 			if (sens == ctx_high->sens) {
784 				break;
785 			} else if (sens == user_high->sens) {
786 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
787 					ctx->range_str, ctx->user_str);
788 				rc = SEPOL_ERR;
789 				goto exit;
790 			}
791 		}
792 	}
793 
794 	return SEPOL_OK;
795 exit:
796 	cil_log(CIL_ERR, "Invalid context\n");
797 	return rc;
798 }
799 
__cil_verify_named_context(struct cil_db * db,struct cil_tree_node * node)800 int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node)
801 {
802 	int rc = SEPOL_ERR;
803 	struct cil_context *ctx = node->data;
804 
805 	rc = __cil_verify_context(db, ctx);
806 	if (rc != SEPOL_OK) {
807 		goto exit;
808 	}
809 
810 	return SEPOL_OK;
811 exit:
812 	cil_log(CIL_ERR, "Invalid named context at line %d of %s\n", node->line, node->path);
813 	return rc;
814 }
815 
__cil_verify_rule(struct cil_tree_node * node,struct cil_complex_symtab * symtab)816 int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
817 {
818 
819 	int rc = SEPOL_ERR;
820 	struct cil_type_rule *typerule = NULL;
821 	struct cil_roletransition *roletrans = NULL;
822 	struct cil_complex_symtab_key ckey;
823 
824 	switch (node->flavor) {
825 	case CIL_ROLETRANSITION: {
826 		roletrans = node->data;
827 		ckey.key1 = (intptr_t)roletrans->src;
828 		ckey.key2 = (intptr_t)roletrans->tgt;
829 		ckey.key3 = (intptr_t)roletrans->obj;
830 		ckey.key4 = CIL_ROLETRANSITION;
831 		break;
832 	}
833 	case CIL_TYPE_RULE: {
834 		typerule = node->data;
835 		ckey.key1 = (intptr_t)typerule->src;
836 		ckey.key2 = (intptr_t)typerule->tgt;
837 		ckey.key3 = (intptr_t)typerule->obj;
838 		ckey.key4 = (intptr_t)typerule->rule_kind;
839 		break;
840 	}
841 	default:
842 		break;
843 	}
844 
845 
846 	rc = cil_complex_symtab_insert(symtab, &ckey, NULL);
847 	if (rc == SEPOL_EEXIST) {
848 		struct cil_complex_symtab_datum *datum = NULL;
849 		cil_complex_symtab_search(symtab, &ckey, &datum);
850 		if (datum == NULL) {
851 			cil_log(CIL_ERR, "Duplicate rule defined on line %d of %s\n",
852 				node->line, node->path);
853 			rc = SEPOL_ERR;
854 			goto exit;
855 		}
856 	}
857 
858 	return SEPOL_OK;
859 exit:
860 	cil_log(CIL_ERR, "Invalid rule at line %d of %s\n", node->line, node->path);
861 	return rc;
862 }
863 
__cil_verify_booleanif_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)864 int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
865 {
866 	int rc = SEPOL_ERR;
867 	struct cil_tree_node *rule_node = node;
868 	struct cil_booleanif *bif = node->parent->parent->data;
869 
870 	switch (rule_node->flavor) {
871 	case CIL_AVRULE: {
872 		struct cil_avrule *avrule = NULL;
873 		avrule = rule_node->data;
874 		if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) {
875 			if (bif->preserved_tunable) {
876 				cil_log(CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables) at line %d or %s\n",
877 					node->line, node->path);
878 			} else {
879 				cil_log(CIL_ERR, "Neverallow found in booleanif block at line %d or %s\n",
880 					node->line, node->path);
881 			}
882 			rc = SEPOL_ERR;
883 			goto exit;
884 		}
885 		break;
886 	}
887 	case CIL_TYPE_RULE: /*
888 	struct cil_type_rule *typerule = NULL;
889 	struct cil_tree_node *temp_node = NULL;
890 	struct cil_complex_symtab *symtab = extra_args;
891 	struct cil_complex_symtab_key ckey;
892 	struct cil_complex_symtab_datum datum;
893 		typerule = rule_node->data;
894 
895 		ckey.key1 = (intptr_t)typerule->src;
896 		ckey.key2 = (intptr_t)typerule->tgt;
897 		ckey.key3 = (intptr_t)typerule->obj;
898 		ckey.key4 = (intptr_t)typerule->rule_kind;
899 
900 		datum.data = node;
901 
902 		rc = cil_complex_symtab_insert(symtab, &ckey, &datum);
903 		if (rc != SEPOL_OK) {
904 			goto exit;
905 		}
906 
907 		for (temp_node = rule_node->next;
908 			temp_node != NULL;
909 			temp_node = temp_node->next) {
910 
911 			if (temp_node->flavor == CIL_TYPE_RULE) {
912 				typerule = temp_node->data;
913 				if ((intptr_t)typerule->src == ckey.key1 &&
914 					(intptr_t)typerule->tgt == ckey.key2 &&
915 					(intptr_t)typerule->obj == ckey.key3 &&
916 					(intptr_t)typerule->rule_kind == ckey.key4) {
917 					cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line);
918 					rc = SEPOL_ERR;
919 					goto exit;
920 				}
921 			}
922 		}
923 		break;*/
924 
925 		//TODO Fix duplicate type_rule detection
926 		break;
927 	case CIL_CALL:
928 		//Fall through to check content of call
929 		break;
930 	case CIL_TUNABLEIF:
931 		//Fall through
932 		break;
933 	case CIL_NAMETYPETRANSITION:
934 		/* While type transitions with file component are not allowed in
935 		   booleanif statements if they don't have "*" as the file. We
936 		   can't check that here. Or at least we won't right now. */
937 		break;
938 	default: {
939 		const char * flavor = cil_node_to_string(node);
940 		if (bif->preserved_tunable) {
941 			cil_log(CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables) at line %d of %s\n",
942 					flavor, node->line, node->path);
943 		} else {
944 			cil_log(CIL_ERR, "Invalid %s statement in booleanif at line %d of %s\n",
945 					flavor, node->line, node->path);
946 		}
947 		goto exit;
948 	}
949 	}
950 
951 	rc = SEPOL_OK;
952 exit:
953 	return rc;
954 }
955 
__cil_verify_booleanif(struct cil_tree_node * node,struct cil_complex_symtab * symtab)956 int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
957 {
958 	int rc = SEPOL_ERR;
959 	struct cil_booleanif *bif = (struct cil_booleanif*)node->data;
960 	struct cil_tree_node *cond_block = node->cl_head;
961 
962 	while (cond_block != NULL) {
963 		rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab);
964 		if (rc != SEPOL_OK) {
965 			goto exit;
966 		}
967 		cond_block = cond_block->next;
968 	}
969 
970 	return SEPOL_OK;
971 exit:
972 	if (bif->preserved_tunable) {
973 		cil_log(CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables) at line %d of %s\n", node->line, node->path);
974 	} else {
975 		cil_log(CIL_ERR, "Invalid booleanif at line %d of %s\n", node->line, node->path);
976 	}
977 	return rc;
978 }
979 
__cil_verify_netifcon(struct cil_db * db,struct cil_tree_node * node)980 int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node)
981 {
982 	int rc = SEPOL_ERR;
983 	struct cil_netifcon *netif = node->data;
984 	struct cil_context *if_ctx = netif->if_context;
985 	struct cil_context *pkt_ctx = netif->packet_context;
986 
987 	/* Verify only when anonymous */
988 	if (if_ctx->datum.name == NULL) {
989 		rc = __cil_verify_context(db, if_ctx);
990 		if (rc != SEPOL_OK) {
991 			goto exit;
992 		}
993 	}
994 
995 	/* Verify only when anonymous */
996 	if (pkt_ctx->datum.name == NULL) {
997 		rc = __cil_verify_context(db, pkt_ctx);
998 		if (rc != SEPOL_OK) {
999 			goto exit;
1000 		}
1001 	}
1002 
1003 	return SEPOL_OK;
1004 
1005 exit:
1006 	cil_log(CIL_ERR, "Invalid netifcon at line %d of %s\n", node->line, node->path);
1007 	return rc;
1008 }
1009 
__cil_verify_genfscon(struct cil_db * db,struct cil_tree_node * node)1010 int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node)
1011 {
1012 	int rc = SEPOL_ERR;
1013 	struct cil_genfscon *genfs = node->data;
1014 	struct cil_context *ctx = genfs->context;
1015 
1016 	/* Verify only when anonymous */
1017 	if (ctx->datum.name == NULL) {
1018 		rc = __cil_verify_context(db, ctx);
1019 		if (rc != SEPOL_OK) {
1020 			goto exit;
1021 		}
1022 	}
1023 
1024 	return SEPOL_OK;
1025 
1026 exit:
1027 	cil_log(CIL_ERR, "Invalid genfscon at line %d of %s\n", node->line, node->path);
1028 	return rc;
1029 }
1030 
__cil_verify_filecon(struct cil_db * db,struct cil_tree_node * node)1031 int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node)
1032 {
1033 	int rc = SEPOL_ERR;
1034 	struct cil_filecon *file = node->data;
1035 	struct cil_context *ctx = file->context;
1036 
1037 	if (ctx == NULL) {
1038 		rc = SEPOL_OK;
1039 		goto exit;
1040 	}
1041 
1042 	/* Verify only when anonymous */
1043 	if (ctx->datum.name == NULL) {
1044 		rc = __cil_verify_context(db, ctx);
1045 		if (rc != SEPOL_OK) {
1046 			cil_log(CIL_ERR, "Invalid filecon at line %d of %s\n",
1047 				node->line, node->path);
1048 			goto exit;
1049 		}
1050 	}
1051 
1052 	return SEPOL_OK;
1053 
1054 exit:
1055 	return rc;
1056 }
1057 
__cil_verify_nodecon(struct cil_db * db,struct cil_tree_node * node)1058 int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node)
1059 {
1060 	int rc = SEPOL_ERR;
1061 	struct cil_nodecon *nodecon = node->data;
1062 	struct cil_context *ctx = nodecon->context;
1063 
1064 	/* Verify only when anonymous */
1065 	if (ctx->datum.name == NULL) {
1066 		rc = __cil_verify_context(db, ctx);
1067 		if (rc != SEPOL_OK) {
1068 			goto exit;
1069 		}
1070 	}
1071 
1072 	return SEPOL_OK;
1073 
1074 exit:
1075 	cil_log(CIL_ERR, "Invalid nodecon at line %d of %s\n", node->line, node->path);
1076 	return rc;
1077 }
1078 
__cil_verify_portcon(struct cil_db * db,struct cil_tree_node * node)1079 int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node)
1080 {
1081 	int rc = SEPOL_ERR;
1082 	struct cil_portcon *port = node->data;
1083 	struct cil_context *ctx = port->context;
1084 
1085 	/* Verify only when anonymous */
1086 	if (ctx->datum.name == NULL) {
1087 		rc = __cil_verify_context(db, ctx);
1088 		if (rc != SEPOL_OK) {
1089 			goto exit;
1090 		}
1091 	}
1092 
1093 	return SEPOL_OK;
1094 
1095 exit:
1096 	cil_log(CIL_ERR, "Invalid portcon at line %d of %s\n", node->line, node->path);
1097 	return rc;
1098 }
1099 
__cil_verify_pirqcon(struct cil_db * db,struct cil_tree_node * node)1100 int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node)
1101 {
1102 	int rc = SEPOL_ERR;
1103 	struct cil_pirqcon *pirq = node->data;
1104 	struct cil_context *ctx = pirq->context;
1105 
1106 	/* Verify only when anonymous */
1107 	if (ctx->datum.name == NULL) {
1108 		rc = __cil_verify_context(db, ctx);
1109 		if (rc != SEPOL_OK) {
1110 			goto exit;
1111 		}
1112 	}
1113 
1114 	return SEPOL_OK;
1115 
1116 exit:
1117 	cil_log(CIL_ERR, "Invalid pirqcon at line %d of %s\n", node->line, node->path);
1118 	return rc;
1119 }
1120 
__cil_verify_iomemcon(struct cil_db * db,struct cil_tree_node * node)1121 int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node)
1122 {
1123 	int rc = SEPOL_ERR;
1124 	struct cil_iomemcon *iomem = node->data;
1125 	struct cil_context *ctx = iomem->context;
1126 
1127 	/* Verify only when anonymous */
1128 	if (ctx->datum.name == NULL) {
1129 		rc = __cil_verify_context(db, ctx);
1130 		if (rc != SEPOL_OK) {
1131 			goto exit;
1132 		}
1133 	}
1134 
1135 	return SEPOL_OK;
1136 
1137 exit:
1138 	cil_log(CIL_ERR, "Invalid iomemcon at line %d of %s\n", node->line, node->path);
1139 	return rc;
1140 }
1141 
__cil_verify_ioportcon(struct cil_db * db,struct cil_tree_node * node)1142 int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node)
1143 {
1144 	int rc = SEPOL_ERR;
1145 	struct cil_ioportcon *ioport = node->data;
1146 	struct cil_context *ctx = ioport->context;
1147 
1148 	/* Verify only when anonymous */
1149 	if (ctx->datum.name == NULL) {
1150 		rc = __cil_verify_context(db, ctx);
1151 		if (rc != SEPOL_OK) {
1152 			goto exit;
1153 		}
1154 	}
1155 
1156 	return SEPOL_OK;
1157 
1158 exit:
1159 	cil_log(CIL_ERR, "Invalid ioportcon at line %d of %s\n", node->line, node->path);
1160 	return rc;
1161 }
1162 
__cil_verify_pcidevicecon(struct cil_db * db,struct cil_tree_node * node)1163 int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node)
1164 {
1165 	int rc = SEPOL_ERR;
1166 	struct cil_pcidevicecon *pcidev = node->data;
1167 	struct cil_context *ctx = pcidev->context;
1168 
1169 	/* Verify only when anonymous */
1170 	if (ctx->datum.name == NULL) {
1171 		rc = __cil_verify_context(db, ctx);
1172 		if (rc != SEPOL_OK) {
1173 			goto exit;
1174 		}
1175 	}
1176 
1177 	return SEPOL_OK;
1178 
1179 exit:
1180 	cil_log(CIL_ERR, "Invalid pcidevicecon at line %d of %s\n", node->line, node->path);
1181 	return rc;
1182 }
1183 
__cil_verify_devicetreecon(struct cil_db * db,struct cil_tree_node * node)1184 int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node)
1185 {
1186 	int rc = SEPOL_ERR;
1187 	struct cil_devicetreecon *dt = node->data;
1188 	struct cil_context *ctx = dt->context;
1189 
1190 	/* Verify only when anonymous */
1191 	if (ctx->datum.name == NULL) {
1192 		rc = __cil_verify_context(db, ctx);
1193 		if (rc != SEPOL_OK) {
1194 			goto exit;
1195 		}
1196 	}
1197 
1198 	return SEPOL_OK;
1199 
1200 exit:
1201 	cil_log(CIL_ERR, "Invalid devicetreecon at line %d of %s\n", node->line, node->path);
1202 	return rc;
1203 }
1204 
__cil_verify_fsuse(struct cil_db * db,struct cil_tree_node * node)1205 int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node)
1206 {
1207 	int rc = SEPOL_ERR;
1208 	struct cil_fsuse *fsuse = node->data;
1209 	struct cil_context *ctx = fsuse->context;
1210 
1211 	/* Verify only when anonymous */
1212 	if (ctx->datum.name == NULL) {
1213 		rc = __cil_verify_context(db, ctx);
1214 		if (rc != SEPOL_OK) {
1215 			goto exit;
1216 		}
1217 	}
1218 
1219 	return SEPOL_OK;
1220 
1221 exit:
1222 	cil_log(CIL_ERR, "Invalid fsuse at line %d of %s\n", node->line, node->path);
1223 	return rc;
1224 }
1225 
__cil_verify_class(struct cil_tree_node * node)1226 int __cil_verify_class(struct cil_tree_node *node)
1227 {
1228 	int rc = SEPOL_ERR;
1229 	struct cil_class *class = node->data;
1230 
1231 	if (class->common != NULL) {
1232 		struct cil_class *common = class->common;
1233 		struct cil_tree_node *common_node = common->datum.nodes->head->data;
1234 		struct cil_tree_node *curr_com_perm = NULL;
1235 
1236 		for (curr_com_perm = common_node->cl_head;
1237 			curr_com_perm != NULL;
1238 			curr_com_perm = curr_com_perm->next) {
1239 			struct cil_perm *com_perm = curr_com_perm->data;
1240 			struct cil_tree_node *curr_class_perm = NULL;
1241 
1242 			for (curr_class_perm = node->cl_head;
1243 				curr_class_perm != NULL;
1244 				curr_class_perm = curr_class_perm->next) {
1245 				struct cil_perm *class_perm = curr_class_perm->data;
1246 
1247 				if (com_perm->datum.name == class_perm->datum.name) {
1248 					cil_log(CIL_ERR, "Duplicate permissions between %s common and class declarations\n", class_perm->datum.name);
1249 					goto exit;
1250 				}
1251 			}
1252 		}
1253 	}
1254 
1255 	return SEPOL_OK;
1256 
1257 exit:
1258 	cil_log(CIL_ERR, "Invalid class at line %d of %s\n", node->line, node->path);
1259 	return rc;
1260 }
1261 
__cil_verify_policycap(struct cil_tree_node * node)1262 int __cil_verify_policycap(struct cil_tree_node *node)
1263 {
1264 	int rc;
1265 	struct cil_policycap *polcap = node->data;
1266 
1267 	rc = sepol_polcap_getnum((const char*)polcap->datum.name);
1268 	if (rc == SEPOL_ERR) {
1269 		goto exit;
1270 	}
1271 
1272 	return SEPOL_OK;
1273 
1274 exit:
1275 	cil_log(CIL_ERR, "Invalid policycap (%s) at line %d of %s\n",
1276 		(const char*)polcap->datum.name, node->line, node->path);
1277 	return rc;
1278 }
1279 
__cil_verify_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1280 int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1281 {
1282 	int rc = SEPOL_ERR;
1283 	int *avrule_cnt = 0;
1284 	int *handleunknown;
1285 	int *mls;
1286 	int *nseuserdflt = 0;
1287 	int *pass = 0;
1288 	struct cil_args_verify *args = extra_args;
1289 	struct cil_complex_symtab *csymtab = NULL;
1290 	struct cil_db *db = NULL;
1291 
1292 	if (node == NULL || extra_args == NULL) {
1293 		goto exit;
1294 	}
1295 
1296 	db = args->db;
1297 	avrule_cnt = args->avrule_cnt;
1298 	handleunknown = args->handleunknown;
1299 	mls = args->mls;
1300 	nseuserdflt = args->nseuserdflt;
1301 	csymtab = args->csymtab;
1302 	pass = args->pass;
1303 
1304 	if (node->flavor == CIL_MACRO) {
1305 		*finished = CIL_TREE_SKIP_HEAD;
1306 		rc = SEPOL_OK;
1307 		goto exit;
1308 	} else if (node->flavor == CIL_BLOCK) {
1309 		struct cil_block *blk = node->data;
1310 		if (blk->is_abstract == CIL_TRUE) {
1311 			*finished = CIL_TREE_SKIP_HEAD;
1312 		}
1313 		rc = SEPOL_OK;
1314 		goto exit;
1315 	}
1316 
1317 	switch (*pass) {
1318 	case 0: {
1319 		switch (node->flavor) {
1320 		case CIL_USER:
1321 			rc = __cil_verify_user(db, node);
1322 			break;
1323 		case CIL_SELINUXUSERDEFAULT:
1324 			(*nseuserdflt)++;
1325 			rc = SEPOL_OK;
1326 			break;
1327 		case CIL_ROLE:
1328 			rc = __cil_verify_role(node);
1329 			break;
1330 		case CIL_TYPE:
1331 			rc = __cil_verify_type(node);
1332 			break;
1333 		case CIL_AVRULE:
1334 			(*avrule_cnt)++;
1335 			rc = SEPOL_OK;
1336 			break;
1337 		case CIL_HANDLEUNKNOWN:
1338 			if (*handleunknown != -1) {
1339 				cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n");
1340 				rc = SEPOL_ERR;
1341 			} else {
1342 				*handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown;
1343 				rc = SEPOL_OK;
1344 			}
1345 			break;
1346 		case CIL_MLS:
1347 			if (*mls != -1) {
1348 				cil_log(CIL_ERR, "Policy can not have more than one mls\n");
1349 				rc = SEPOL_ERR;
1350 			} else {
1351 				*mls = ((struct cil_mls*)node->data)->value;
1352 				rc = SEPOL_OK;
1353 			}
1354 			break;
1355 		case CIL_ROLETRANSITION:
1356 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1357 			//rc = __cil_verify_rule(node, csymtab);
1358 			break;
1359 		case CIL_TYPE_RULE:
1360 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1361 			//rc = __cil_verify_rule(node, csymtab);
1362 			break;
1363 		case CIL_BOOLEANIF:
1364 			rc = __cil_verify_booleanif(node, csymtab);
1365 			*finished = CIL_TREE_SKIP_HEAD;
1366 			break;
1367 		case CIL_LEVELRANGE:
1368 			rc = __cil_verify_named_levelrange(db, node);
1369 			break;
1370 		case CIL_CLASS:
1371 			rc = __cil_verify_class(node);
1372 			break;
1373 		case CIL_POLICYCAP:
1374 			rc = __cil_verify_policycap(node);
1375 			break;
1376 		default:
1377 			rc = SEPOL_OK;
1378 			break;
1379 		}
1380 		break;
1381 	}
1382 	case 1:	{
1383 		switch (node->flavor) {
1384 		case CIL_CONTEXT:
1385 			rc = __cil_verify_named_context(db, node);
1386 			break;
1387 		case CIL_NETIFCON:
1388 			rc = __cil_verify_netifcon(db, node);
1389 			break;
1390 		case CIL_GENFSCON:
1391 			rc = __cil_verify_genfscon(db, node);
1392 			break;
1393 		case CIL_FILECON:
1394 			rc = __cil_verify_filecon(db, node);
1395 			break;
1396 		case CIL_NODECON:
1397 			rc = __cil_verify_nodecon(db, node);
1398 			break;
1399 		case CIL_PORTCON:
1400 			rc = __cil_verify_portcon(db, node);
1401 			break;
1402 		case CIL_PIRQCON:
1403 			rc = __cil_verify_pirqcon(db, node);
1404 			break;
1405 		case CIL_IOMEMCON:
1406 			rc = __cil_verify_iomemcon(db, node);
1407 			break;
1408 		case CIL_IOPORTCON:
1409 			rc = __cil_verify_ioportcon(db, node);
1410 			break;
1411 		case CIL_PCIDEVICECON:
1412 			rc = __cil_verify_pcidevicecon(db, node);
1413 			break;
1414 		case CIL_DEVICETREECON:
1415 			rc = __cil_verify_devicetreecon(db, node);
1416 			break;
1417 		case CIL_FSUSE:
1418 			rc = __cil_verify_fsuse(db, node);
1419 			break;
1420 		case CIL_RANGETRANSITION:
1421 			rc = SEPOL_OK;
1422 			break;
1423 		default:
1424 			rc = SEPOL_OK;
1425 			break;
1426 		}
1427 		break;
1428 	}
1429 	default:
1430 		rc = SEPOL_ERR;
1431 	}
1432 
1433 exit:
1434 	return rc;
1435 }
1436 
__cil_verify_classperms(struct cil_list * classperms,struct cil_symtab_datum * orig)1437 static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig)
1438 {
1439 	int rc = SEPOL_ERR;
1440 	struct cil_list_item *curr;
1441 
1442 	cil_list_for_each(curr, classperms) {
1443 		if (curr->flavor == CIL_CLASSPERMS) {
1444 			struct cil_classperms *cp = curr->data;
1445 			if (FLAVOR(cp->class) == CIL_CLASS) {
1446 				return SEPOL_OK;
1447 			} else { /* MAP */
1448 				struct cil_list_item *i = NULL;
1449 				cil_list_for_each(i, cp->perms) {
1450 					struct cil_perm *cmp = i->data;
1451 					if (&cmp->datum == orig) {
1452 						rc = SEPOL_ERR;
1453 						goto exit;
1454 					}
1455 					rc = __cil_verify_classperms(cmp->classperms, orig);
1456 					if (rc != SEPOL_OK) {
1457 						goto exit;
1458 					}
1459 				}
1460 			}
1461 		} else { /* SET */
1462 			struct cil_classperms_set *cp_set = curr->data;
1463 			struct cil_classpermission *cp = cp_set->set;
1464 			if (&cp->datum == orig) {
1465 				rc = SEPOL_ERR;
1466 				goto exit;
1467 			}
1468 			rc = __cil_verify_classperms(cp->classperms, orig);
1469 			if (rc != SEPOL_OK) {
1470 				goto exit;
1471 			}
1472 		}
1473 	}
1474 
1475 	return SEPOL_OK;
1476 
1477 exit:
1478 	return rc;
1479 }
1480 
__cil_verify_classpermission(struct cil_tree_node * node)1481 static int __cil_verify_classpermission(struct cil_tree_node *node)
1482 {
1483 	int rc = SEPOL_ERR;
1484 	struct cil_classpermission *cp = node->data;
1485 
1486 	rc = __cil_verify_classperms(cp->classperms, &cp->datum);
1487 	if (rc != SEPOL_OK) {
1488 		cil_log(CIL_ERR, "Found circular class permissions involving the set %s at line %d of %s\n",cp->datum.name, node->line, node->path);
1489 		return rc;
1490 	}
1491 
1492 	return SEPOL_OK;
1493 }
1494 
1495 struct cil_verify_map_args {
1496 	struct cil_class *class;
1497 	struct cil_tree_node *node;
1498 	int rc;
1499 };
1500 
__verify_map_perm_classperms(hashtab_key_t k,hashtab_datum_t d,void * args)1501 static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1502 {
1503 	int rc = SEPOL_ERR;
1504 	struct cil_verify_map_args *map_args = args;
1505 	struct cil_perm *cmp = (struct cil_perm *)d;
1506 
1507 	rc = __cil_verify_classperms(cmp->classperms, &cmp->datum);
1508 	if (rc != SEPOL_OK) {
1509 		cil_log(CIL_ERR, "Found circular class permissions involving the map class %s and permission %s at line %d of %s\n", map_args->class->datum.name, cmp->datum.name, map_args->node->line, map_args->node->path);
1510 		map_args->rc = SEPOL_ERR;
1511 	}
1512 
1513 	return SEPOL_OK;
1514 }
1515 
__cil_verify_map_class(struct cil_tree_node * node)1516 static int __cil_verify_map_class(struct cil_tree_node *node)
1517 {
1518 	struct cil_class *mc = node->data;
1519 	struct cil_verify_map_args map_args;
1520 
1521 	map_args.class = mc;
1522 	map_args.node = node;
1523 	map_args.rc = SEPOL_OK;
1524 
1525 	cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args);
1526 
1527 	if (map_args.rc != SEPOL_OK) {
1528 		return SEPOL_ERR;
1529 	}
1530 
1531 	return SEPOL_OK;
1532 }
1533 
__cil_verify_no_classperms_loop_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1534 static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
1535 {
1536 	int rc = SEPOL_ERR;
1537 
1538 	if (node->flavor == CIL_MACRO) {
1539 		*finished = CIL_TREE_SKIP_HEAD;
1540 		rc = SEPOL_OK;
1541 		goto exit;
1542 	} else if (node->flavor == CIL_BLOCK) {
1543 		struct cil_block *blk = node->data;
1544 		if (blk->is_abstract == CIL_TRUE) {
1545 			*finished = CIL_TREE_SKIP_HEAD;
1546 		}
1547 		rc = SEPOL_OK;
1548 		goto exit;
1549 	}
1550 
1551 	switch (node->flavor) {
1552 	case CIL_MAP_CLASS:
1553 		rc = __cil_verify_map_class(node);
1554 		break;
1555 	case CIL_CLASSPERMISSION:
1556 		rc = __cil_verify_classpermission(node);
1557 		break;
1558 	default:
1559 		rc = SEPOL_OK;
1560 		break;
1561 	}
1562 
1563 exit:
1564 	return rc;
1565 }
1566 
cil_verify_no_classperms_loop(struct cil_db * db)1567 int cil_verify_no_classperms_loop(struct cil_db *db)
1568 {
1569 	int rc = SEPOL_ERR;
1570 
1571 	rc = cil_tree_walk(db->ast->root, __cil_verify_no_classperms_loop_helper, NULL, NULL, NULL);
1572 	if (rc != SEPOL_OK) {
1573 		cil_log(CIL_ERR, "Failed to verify no loops in class permissions\n");
1574 		goto exit;
1575 	}
1576 
1577 exit:
1578 	return rc;
1579 }
1580