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