• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <unistd.h>
35 #include <ctype.h>
36 
37 #include <sepol/policydb/polcaps.h>
38 #include <sepol/errcodes.h>
39 
40 #include "cil_internal.h"
41 #include "cil_flavor.h"
42 #include "cil_log.h"
43 #include "cil_mem.h"
44 #include "cil_tree.h"
45 #include "cil_list.h"
46 #include "cil_find.h"
47 
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;
54 	int i = 0;
55 
56 	if (name == NULL) {
57 		cil_log(CIL_ERR, "Name is NULL\n");
58 		goto exit;
59 	}
60 
61 	len = strlen(name);
62 	if (len >= CIL_MAX_NAME_LENGTH) {
63 		cil_log(CIL_ERR, "Name length greater than max name length of %d",
64 			CIL_MAX_NAME_LENGTH);
65 		rc = SEPOL_ERR;
66 		goto exit;
67 	}
68 
69 	if (!isalpha(name[0])) {
70 			cil_log(CIL_ERR, "First character in %s is not a letter\n", name);
71 			goto exit;
72 	}
73 
74 	for (i = 1; i < len; i++) {
75 		if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
76 			cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
77 			goto exit;
78 		}
79 	}
80 	return SEPOL_OK;
81 
82 exit:
83 	cil_log(CIL_ERR, "Invalid name\n");
84 	return rc;
85 }
86 
__cil_verify_syntax(struct cil_tree_node * parse_current,enum cil_syntax s[],int len)87 int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len)
88 {
89 	int rc = SEPOL_ERR;
90 	int num_extras = 0;
91 	struct cil_tree_node *c = parse_current;
92 	int i = 0;
93 	while (i < len) {
94 		if ((s[i] & CIL_SYN_END) && c == NULL) {
95 			break;
96 		}
97 
98 		if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) {
99 			if (c == NULL) {
100 				if (num_extras > 0) {
101 					i++;
102 					continue;
103 				} else {
104 					goto exit;
105 				}
106 			} else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) {
107 				c = c->next;
108 				num_extras++;
109 				continue;
110 			} else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) {
111 				c = c->next;
112 				num_extras++;
113 				continue;
114 			}
115 		}
116 
117 		if (c == NULL) {
118 			goto exit;
119 		}
120 
121 		if (s[i] & CIL_SYN_STRING) {
122 			if (c->data != NULL && c->cl_head == NULL) {
123 				c = c->next;
124 				i++;
125 				continue;
126 			}
127 		}
128 
129 		if (s[i] & CIL_SYN_LIST) {
130 			if (c->data == NULL && c->cl_head != NULL) {
131 				c = c->next;
132 				i++;
133 				continue;
134 			}
135 		}
136 
137 		if (s[i] & CIL_SYN_EMPTY_LIST) {
138 			if (c->data == NULL && c->cl_head == NULL) {
139 				c = c->next;
140 				i++;
141 				continue;
142 			}
143 		}
144 		goto exit;
145 	}
146 	return SEPOL_OK;
147 
148 exit:
149 	cil_log(CIL_ERR, "Invalid syntax\n");
150 	return rc;
151 }
152 
cil_verify_expr_syntax(struct cil_tree_node * current,enum cil_flavor op,enum cil_flavor expr_flavor)153 int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor)
154 {
155 	int rc;
156 	enum cil_syntax syntax[] = {
157 		CIL_SYN_STRING,
158 		CIL_SYN_STRING | CIL_SYN_LIST,
159 		CIL_SYN_STRING | CIL_SYN_LIST,
160 		CIL_SYN_END
161 	};
162 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
163 
164 	switch (op) {
165 	case CIL_NOT:
166 		syntax[2] = CIL_SYN_END;
167 		syntax_len = 3;
168 		break;
169 	case CIL_AND:
170 	case CIL_OR:
171 	case CIL_XOR:
172 		break;
173 	case CIL_EQ:
174 	case CIL_NEQ:
175 		if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) {
176 			cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data);
177 			goto exit;
178 		}
179 		break;
180 	case CIL_ALL:
181 		if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) {
182 			cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data);
183 			goto exit;
184 		}
185 		syntax[1] = CIL_SYN_END;
186 		syntax_len = 2;
187 		break;
188 	case CIL_RANGE:
189 		if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) {
190 			cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data);
191 			goto exit;
192 		}
193 		syntax[1] = CIL_SYN_STRING;
194 		syntax[2] = CIL_SYN_STRING;
195 		break;
196 	case CIL_NONE: /* String or List */
197 		syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS;
198 		syntax[1] = CIL_SYN_END;
199 		syntax_len = 2;
200 		break;
201 	default:
202 		cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data);
203 		goto exit;
204 	}
205 
206 	rc = __cil_verify_syntax(current, syntax, syntax_len);
207 	if (rc != SEPOL_OK) {
208 		goto exit;
209 	}
210 
211 	return SEPOL_OK;
212 
213 exit:
214 	return SEPOL_ERR;
215 }
216 
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)217 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)
218 {
219 	if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) {
220 		if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) {
221 			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");
222 			goto exit;
223 		} else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) {
224 			if (expr_flavor != CIL_MLSVALIDATETRANS) {
225 				cil_log(CIL_ERR, "u3, r3, and t3 can only be used with mlsvalidatetrans rules\n");
226 				goto exit;
227 			}
228 		}
229 	} else {
230 		if (r_flavor == CIL_CONS_U2) {
231 			if (op != CIL_EQ && op != CIL_NEQ) {
232 				cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
233 				goto exit;
234 			} else if (l_flavor != CIL_CONS_U1) {
235 				cil_log(CIL_ERR, "u2 on the right side must be used with u1 on the left\n");
236 				goto exit;
237 			}
238 		} else if (r_flavor == CIL_CONS_R2) {
239 			if (l_flavor != CIL_CONS_R1) {
240 				cil_log(CIL_ERR, "r2 on the right side must be used with r1 on the left\n");
241 				goto exit;
242 			}
243 		} else if (r_flavor == CIL_CONS_T2) {
244 			if (op != CIL_EQ && op != CIL_NEQ) {
245 				cil_log(CIL_ERR, "t2 on the right side must be used with eq or neq as the operator\n");
246 				goto exit;
247 			} else if (l_flavor != CIL_CONS_T1) {
248 				cil_log(CIL_ERR, "t2 on the right side must be used with t1 on the left\n");
249 				goto exit;
250 			}
251 		} else if (r_flavor == CIL_CONS_L2) {
252 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_H1) {
253 				cil_log(CIL_ERR, "l2 on the right side must be used with l1 or h1 on the left\n");
254 				goto exit;
255 			}
256 		} else if (r_flavor == CIL_CONS_H2) {
257 			if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_L2 && l_flavor != CIL_CONS_H1 ) {
258 				cil_log(CIL_ERR, "h2 on the right side must be used with l1, l2, or h1 on the left\n");
259 				goto exit;
260 			}
261 		} else if (r_flavor == CIL_CONS_H1) {
262 			if (l_flavor != CIL_CONS_L1) {
263 				cil_log(CIL_ERR, "h1 on the right side must be used with l1 on the left\n");
264 				goto exit;
265 			}
266 		}
267 	}
268 
269 	return SEPOL_OK;
270 
271 exit:
272 	return SEPOL_ERR;
273 }
274 
cil_verify_constraint_expr_syntax(struct cil_tree_node * current,enum cil_flavor op)275 int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op)
276 {
277 	int rc;
278 	enum cil_syntax syntax[] = {
279 		CIL_SYN_STRING,
280 		CIL_SYN_END,
281 		CIL_SYN_END,
282 		CIL_SYN_END
283 	};
284 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
285 
286 	switch (op) {
287 	case CIL_NOT:
288 		syntax[1] = CIL_SYN_LIST;
289 		syntax_len--;
290 		break;
291 	case CIL_AND:
292 	case CIL_OR:
293 		syntax[1] = CIL_SYN_LIST;
294 		syntax[2] = CIL_SYN_LIST;
295 		break;
296 	case CIL_EQ:
297 	case CIL_NEQ:
298 		syntax[1] = CIL_SYN_STRING;
299 		syntax[2] = CIL_SYN_STRING | CIL_SYN_LIST;
300 		break;
301 	case CIL_CONS_DOM:
302 	case CIL_CONS_DOMBY:
303 	case CIL_CONS_INCOMP:
304 		syntax[1] = CIL_SYN_STRING;
305 		syntax[2] = CIL_SYN_STRING;
306 		break;
307 	default:
308 		cil_log(CIL_ERR, "Invalid operator (%s) for constraint expression\n", (char*)current->data);
309 		goto exit;
310 	}
311 
312 	rc = __cil_verify_syntax(current, syntax, syntax_len);
313 	if (rc != SEPOL_OK) {
314 		cil_log(CIL_ERR, "Invalid constraint syntax\n");
315 		goto exit;
316 	}
317 
318 	return SEPOL_OK;
319 
320 exit:
321 	return SEPOL_ERR;
322 }
323 
cil_verify_no_self_reference(struct cil_symtab_datum * datum,struct cil_list * datum_list)324 int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
325 {
326 	struct cil_list_item *i;
327 
328 	cil_list_for_each(i, datum_list) {
329 		if (i->flavor == CIL_DATUM) {
330 			struct cil_symtab_datum *d = i->data;
331 			if (d == datum) {
332 				cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name);
333 				return SEPOL_ERR;
334 			}
335 		} else if (i->flavor == CIL_LIST) {
336 			int rc = cil_verify_no_self_reference(datum, i->data);
337 			if (rc != SEPOL_OK) {
338 				return SEPOL_ERR;
339 			}
340 		}
341 	}
342 
343 	return SEPOL_OK;
344 }
345 
__cil_verify_ranges(struct cil_list * list)346 int __cil_verify_ranges(struct cil_list *list)
347 {
348 	int rc = SEPOL_ERR;
349 	struct cil_list_item *curr;
350 	struct cil_list_item *range = NULL;
351 
352 	if (list == NULL || list->head == NULL) {
353 		goto exit;
354 	}
355 
356 	cil_list_for_each(curr, list) {
357 		/* range */
358 		if (curr->flavor == CIL_LIST) {
359 			range = ((struct cil_list*)curr->data)->head;
360 			if (range == NULL || range->next == NULL || range->next->next != NULL) {
361 				goto exit;
362 			}
363 		}
364 	}
365 
366 	return SEPOL_OK;
367 
368 exit:
369 	cil_log(CIL_ERR,"Invalid Range syntax\n");
370 	return rc;
371 }
372 
373 struct cil_args_verify_order {
374 	uint32_t *flavor;
375 };
376 
__cil_verify_ordered_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)377 int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
378 {
379 	struct cil_args_verify_order *args = extra_args;
380 	uint32_t *flavor = args->flavor;
381 
382 	if (node->flavor == *flavor) {
383 		if (node->flavor == CIL_SID) {
384 			struct cil_sid *sid = node->data;
385 			if (sid->ordered == CIL_FALSE) {
386 				cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name);
387 				return SEPOL_ERR;
388 			}
389 		} else if (node->flavor == CIL_CLASS) {
390 			struct cil_class *class = node->data;
391 			if (class->ordered == CIL_FALSE) {
392 				cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name);
393 				return SEPOL_ERR;
394 			}
395 		} else if (node->flavor == CIL_CAT) {
396 			struct cil_cat *cat = node->data;
397 			if (cat->ordered == CIL_FALSE) {
398 				cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name);
399 				return SEPOL_ERR;
400 			}
401 		} else if (node->flavor == CIL_SENS) {
402 			struct cil_sens *sens = node->data;
403 			if (sens->ordered == CIL_FALSE) {
404 				cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name);
405 				return SEPOL_ERR;
406 			}
407 		}
408 	}
409 
410 	return SEPOL_OK;
411 }
412 
__cil_verify_ordered(struct cil_tree_node * current,enum cil_flavor flavor)413 int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor)
414 {
415 	struct cil_args_verify_order extra_args;
416 	int rc = SEPOL_ERR;
417 
418 	extra_args.flavor = &flavor;
419 
420 	rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args);
421 
422 	return rc;
423 }
424 
__cil_verify_initsids(struct cil_list * sids)425 int __cil_verify_initsids(struct cil_list *sids)
426 {
427 	int rc = SEPOL_OK;
428 	struct cil_list_item *i;
429 
430 	if (sids->head == NULL) {
431 		cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n");
432 		return SEPOL_ERR;
433 	}
434 
435 	cil_list_for_each(i, sids) {
436 		struct cil_sid *sid = i->data;
437 		if (sid->context == NULL) {
438 			struct cil_tree_node *node = sid->datum.nodes->head->data;
439 			cil_tree_log(node, CIL_ERR, "No context assigned to SID %s declared",sid->datum.name);
440 			rc = SEPOL_ERR;
441 		}
442 	}
443 
444 	return rc;
445 }
446 
__cil_is_cat_in_cats(struct cil_cat * cat,struct cil_cats * cats)447 int __cil_is_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
448 {
449 	struct cil_list_item *i;
450 
451 	cil_list_for_each(i, cats->datum_expr) {
452 		struct cil_cat *c = i->data;
453 		if (c == cat) {
454 			return CIL_TRUE;
455 		}
456 	}
457 
458 	return CIL_FALSE;
459 }
460 
461 
__cil_verify_cat_in_cats(struct cil_cat * cat,struct cil_cats * cats)462 int __cil_verify_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
463 {
464 	if (__cil_is_cat_in_cats(cat, cats) != CIL_TRUE) {
465 		cil_log(CIL_ERR, "Failed to find category %s in category list\n", cat->datum.name);
466 		return SEPOL_ERR;
467 	}
468 
469 	return SEPOL_OK;
470 }
471 
__cil_verify_cats_associated_with_sens(struct cil_sens * sens,struct cil_cats * cats)472 int __cil_verify_cats_associated_with_sens(struct cil_sens *sens, struct cil_cats *cats)
473 {
474 	int rc = SEPOL_OK;
475 	struct cil_list_item *i, *j;
476 
477 	if (!cats) {
478 		return SEPOL_OK;
479 	}
480 
481 	if (!sens->cats_list) {
482 		cil_log(CIL_ERR, "No categories can be used with sensitivity %s\n", sens->datum.name);
483 		return SEPOL_ERR;
484 	}
485 
486 	cil_list_for_each(i, cats->datum_expr) {
487 		struct cil_cat *cat = i->data;
488 		int ok = CIL_FALSE;
489 		cil_list_for_each(j, sens->cats_list) {
490 			if (__cil_is_cat_in_cats(cat, j->data) == CIL_TRUE) {
491 				ok = CIL_TRUE;
492 				break;
493 			}
494 		}
495 
496 		if (ok != CIL_TRUE) {
497 			cil_log(CIL_ERR, "Category %s cannot be used with sensitivity %s\n",
498 					cat->datum.name, sens->datum.name);
499 			rc = SEPOL_ERR;
500 		}
501 	}
502 
503 	return rc;
504 }
505 
__cil_verify_levelrange_sensitivity(struct cil_db * db,struct cil_sens * low,struct cil_sens * high)506 int __cil_verify_levelrange_sensitivity(struct cil_db *db, struct cil_sens *low, struct cil_sens *high)
507 {
508 	struct cil_list_item *curr;
509 	int found = CIL_FALSE;
510 	int rc = SEPOL_ERR;
511 
512 	cil_list_for_each(curr, db->sensitivityorder) {
513 		if (curr->data == low) {
514 			found = CIL_TRUE;
515 		}
516 
517 		if ((found == CIL_TRUE) && (curr->data == high)) {
518 			break;
519 		}
520 	}
521 
522 	if (found != CIL_TRUE || curr == NULL) {
523 		goto exit;
524 	}
525 
526 	return SEPOL_OK;
527 
528 exit:
529 	cil_log(CIL_ERR, "Sensitivity %s does not dominate %s\n",
530 		high->datum.name, low->datum.name);
531 	return rc;
532 
533 }
534 
__cil_verify_levelrange_cats(struct cil_cats * low,struct cil_cats * high)535 int __cil_verify_levelrange_cats(struct cil_cats *low, struct cil_cats *high)
536 {
537 	int rc = SEPOL_ERR;
538 	struct cil_list_item *item;
539 
540 	if (low == NULL || (low == NULL && high == NULL)) {
541 		return SEPOL_OK;
542 	}
543 
544 	if (high == NULL) {
545 		rc = SEPOL_ERR;
546 		goto exit;
547 	}
548 
549 	cil_list_for_each(item, low->datum_expr) {
550 		rc = __cil_verify_cat_in_cats(item->data, high);
551 		if (rc != SEPOL_OK) {
552 			goto exit;
553 		}
554 	}
555 
556 	return SEPOL_OK;
557 
558 exit:
559 	cil_log(CIL_ERR, "Low level category set must be a subset of the high level category set\n");
560 	return rc;
561 }
562 
__cil_verify_levelrange(struct cil_db * db,struct cil_levelrange * lr)563 int __cil_verify_levelrange(struct cil_db *db, struct cil_levelrange *lr)
564 {
565 	int rc = SEPOL_ERR;
566 
567 	rc = __cil_verify_levelrange_sensitivity(db, lr->low->sens, lr->high->sens);
568 	if (rc != SEPOL_OK) {
569 		goto exit;
570 	}
571 
572 	rc = __cil_verify_levelrange_cats(lr->low->cats, lr->high->cats);
573 	if (rc != SEPOL_OK) {
574 		goto exit;
575 	}
576 
577 	rc = __cil_verify_cats_associated_with_sens(lr->low->sens, lr->low->cats);
578 	if (rc != SEPOL_OK) {
579 		cil_log(CIL_ERR, "Low level sensitivity and categories are not associated\n");
580 		goto exit;
581 	}
582 
583 	rc = __cil_verify_cats_associated_with_sens(lr->high->sens, lr->high->cats);
584 	if (rc != SEPOL_OK) {
585 		cil_log(CIL_ERR, "High level sensitivity and categories are not associated\n");
586 		goto exit;
587 	}
588 
589 	return SEPOL_OK;
590 
591 exit:
592 	return rc;
593 }
594 
__cil_verify_named_levelrange(struct cil_db * db,struct cil_tree_node * node)595 int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node)
596 {
597 	int rc = SEPOL_ERR;
598 	struct cil_levelrange *lr = node->data;
599 
600 	rc = __cil_verify_levelrange(db, lr);
601 	if (rc != SEPOL_OK) {
602 		goto exit;
603 	}
604 
605 	return SEPOL_OK;
606 exit:
607 	cil_tree_log(node, CIL_ERR, "Invalid named range");
608 	return rc;
609 }
610 
__cil_verify_user_pre_eval(struct cil_tree_node * node)611 static int __cil_verify_user_pre_eval(struct cil_tree_node *node)
612 {
613 	int rc = SEPOL_ERR;
614 	struct cil_user *user = node->data;
615 
616 	if (user->dftlevel == NULL) {
617 		cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name);
618 		goto exit;
619 	} else if (user->range == NULL) {
620 		cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name);
621 		goto exit;
622 	} else if (user->bounds != NULL) {
623 		int steps = 0;
624 		int limit = 2;
625 		struct cil_user *u1 = user;
626 		struct cil_user *u2 = user->bounds;
627 
628 		while (u2 != NULL) {
629 			if (u1 == u2) {
630 				cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name);
631 				goto exit;
632 			}
633 
634 			if (steps == limit) {
635 				steps = 0;
636 				limit *= 2;
637 				u1 = u2;
638 			}
639 
640 			u2 = u2->bounds;
641 			steps++;
642 		}
643 	}
644 
645 	return SEPOL_OK;
646 exit:
647 	cil_tree_log(node, CIL_ERR, "Invalid user");
648 	return rc;
649 }
650 
__cil_verify_user_post_eval(struct cil_db * db,struct cil_tree_node * node)651 static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node)
652 {
653 	int rc = SEPOL_ERR;
654 	struct cil_user *user = node->data;
655 
656 	/* Verify user range only if anonymous */
657 	if (user->range->datum.name == NULL) {
658 		rc = __cil_verify_levelrange(db, user->range);
659 		if (rc != SEPOL_OK) {
660 			goto exit;
661 		}
662 	}
663 
664 	return SEPOL_OK;
665 exit:
666 	cil_tree_log(node, CIL_ERR, "Invalid user");
667 	return rc;
668 }
669 
__cil_verify_role(struct cil_tree_node * node)670 int __cil_verify_role(struct cil_tree_node *node)
671 {
672 	int rc = SEPOL_ERR;
673 	struct cil_role *role = node->data;
674 	int steps = 0;
675 	int limit = 2;
676 	struct cil_role *r1 = role;
677 	struct cil_role *r2 = role->bounds;
678 
679 	while (r2 != NULL) {
680 		if (r1 == r2) {
681 			cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name);
682 			goto exit;
683 		}
684 
685 		if (steps == limit) {
686 			steps = 0;
687 			limit *= 2;
688 			r1 = r2;
689 		}
690 
691 		r2 = r2->bounds;
692 		steps++;
693 	}
694 
695 	return SEPOL_OK;
696 exit:
697 	cil_tree_log(node, CIL_ERR, "Invalid role");
698 	return rc;
699 }
700 
__cil_verify_type(struct cil_tree_node * node)701 int __cil_verify_type(struct cil_tree_node *node)
702 {
703 	int rc = SEPOL_ERR;
704 	struct cil_type *type = node->data;
705 	int steps = 0;
706 	int limit = 2;
707 	struct cil_type *t1 = type;
708 	struct cil_type *t2 = type->bounds;
709 
710 	while (t2 != NULL) {
711 		if (t1 == t2) {
712 			cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name);
713 			goto exit;
714 		}
715 
716 		if (steps == limit) {
717 			steps = 0;
718 			limit *= 2;
719 			t1 = t2;
720 		}
721 
722 		t2 = t2->bounds;
723 		steps++;
724 	}
725 
726 	return SEPOL_OK;
727 exit:
728 	cil_tree_log(node, CIL_ERR, "Invalid type");
729 	return rc;
730 }
731 
__cil_verify_context(struct cil_db * db,struct cil_context * ctx)732 int __cil_verify_context(struct cil_db *db, struct cil_context *ctx)
733 {
734 	int rc = SEPOL_ERR;
735 	struct cil_user *user = ctx->user;
736 	struct cil_role *role = ctx->role;
737 	struct cil_type *type = ctx->type;
738 	struct cil_level *user_low = user->range->low;
739 	struct cil_level *user_high = user->range->high;
740 	struct cil_level *ctx_low = ctx->range->low;
741 	struct cil_level *ctx_high = ctx->range->high;
742 	struct cil_list *sensitivityorder = db->sensitivityorder;
743 	struct cil_list_item *curr;
744 	int found = CIL_FALSE;
745 
746 	if (user->roles != NULL) {
747 		if (!ebitmap_get_bit(user->roles, role->value)) {
748 			cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str);
749 			rc = SEPOL_ERR;
750 			goto exit;
751 		}
752 	} else {
753 		cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str);
754 		rc = SEPOL_ERR;
755 		goto exit;
756 	}
757 
758 	if (role->types != NULL) {
759 		if (!ebitmap_get_bit(role->types, type->value)) {
760 			cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str);
761 			rc = SEPOL_ERR;
762 			goto exit;
763 		}
764 	} else {
765 		cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str);
766 		rc = SEPOL_ERR;
767 		goto exit;
768 	}
769 
770 	/* Verify range only when anonymous */
771 	if (ctx->range->datum.name == NULL) {
772 		rc = __cil_verify_levelrange(db, ctx->range);
773 		if (rc != SEPOL_OK) {
774 			goto exit;
775 		}
776 	}
777 
778 	for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) {
779 		struct cil_sens *sens = curr->data;
780 
781 		if (found == CIL_FALSE) {
782 			if (sens == user_low->sens) {
783 				found = CIL_TRUE;
784 			} else if (sens == ctx_low->sens) {
785 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
786 					ctx->range_str, ctx->user_str);
787 				rc = SEPOL_ERR;
788 				goto exit;
789 			}
790 		}
791 
792 		if (found == CIL_TRUE) {
793 			if (sens == ctx_high->sens) {
794 				break;
795 			} else if (sens == user_high->sens) {
796 				cil_log(CIL_ERR, "Range %s is invalid for user %s\n",
797 					ctx->range_str, ctx->user_str);
798 				rc = SEPOL_ERR;
799 				goto exit;
800 			}
801 		}
802 	}
803 
804 	return SEPOL_OK;
805 exit:
806 	cil_log(CIL_ERR, "Invalid context\n");
807 	return rc;
808 }
809 
__cil_verify_named_context(struct cil_db * db,struct cil_tree_node * node)810 int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node)
811 {
812 	int rc = SEPOL_ERR;
813 	struct cil_context *ctx = node->data;
814 
815 	rc = __cil_verify_context(db, ctx);
816 	if (rc != SEPOL_OK) {
817 		goto exit;
818 	}
819 
820 	return SEPOL_OK;
821 exit:
822 	cil_tree_log(node, CIL_ERR, "Invalid named context");
823 	return rc;
824 }
825 
__cil_verify_rule(struct cil_tree_node * node,struct cil_complex_symtab * symtab)826 int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
827 {
828 
829 	int rc = SEPOL_ERR;
830 	struct cil_type_rule *typerule = NULL;
831 	struct cil_roletransition *roletrans = NULL;
832 	struct cil_complex_symtab_key ckey;
833 
834 	switch (node->flavor) {
835 	case CIL_ROLETRANSITION: {
836 		roletrans = node->data;
837 		ckey.key1 = (intptr_t)roletrans->src;
838 		ckey.key2 = (intptr_t)roletrans->tgt;
839 		ckey.key3 = (intptr_t)roletrans->obj;
840 		ckey.key4 = CIL_ROLETRANSITION;
841 		break;
842 	}
843 	case CIL_TYPE_RULE: {
844 		typerule = node->data;
845 		ckey.key1 = (intptr_t)typerule->src;
846 		ckey.key2 = (intptr_t)typerule->tgt;
847 		ckey.key3 = (intptr_t)typerule->obj;
848 		ckey.key4 = (intptr_t)typerule->rule_kind;
849 		break;
850 	}
851 	default:
852 		break;
853 	}
854 
855 
856 	rc = cil_complex_symtab_insert(symtab, &ckey, NULL);
857 	if (rc == SEPOL_EEXIST) {
858 		struct cil_complex_symtab_datum *datum = NULL;
859 		cil_complex_symtab_search(symtab, &ckey, &datum);
860 		if (datum == NULL) {
861 			cil_tree_log(node, CIL_ERR, "Duplicate rule defined");
862 			rc = SEPOL_ERR;
863 			goto exit;
864 		}
865 	}
866 
867 	return SEPOL_OK;
868 exit:
869 	cil_tree_log(node, CIL_ERR, "Invalid rule");
870 	return rc;
871 }
872 
__cil_verify_booleanif_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)873 int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
874 {
875 	int rc = SEPOL_ERR;
876 	struct cil_tree_node *rule_node = node;
877 	struct cil_booleanif *bif = node->parent->parent->data;
878 
879 	switch (rule_node->flavor) {
880 	case CIL_AVRULE: {
881 		struct cil_avrule *avrule = NULL;
882 		avrule = rule_node->data;
883 		if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) {
884 			if (bif->preserved_tunable) {
885 				cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)");
886 			} else {
887 				cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block");
888 			}
889 			rc = SEPOL_ERR;
890 			goto exit;
891 		}
892 		break;
893 	}
894 	case CIL_TYPE_RULE: /*
895 	struct cil_type_rule *typerule = NULL;
896 	struct cil_tree_node *temp_node = NULL;
897 	struct cil_complex_symtab *symtab = extra_args;
898 	struct cil_complex_symtab_key ckey;
899 	struct cil_complex_symtab_datum datum;
900 		typerule = rule_node->data;
901 
902 		ckey.key1 = (intptr_t)typerule->src;
903 		ckey.key2 = (intptr_t)typerule->tgt;
904 		ckey.key3 = (intptr_t)typerule->obj;
905 		ckey.key4 = (intptr_t)typerule->rule_kind;
906 
907 		datum.data = node;
908 
909 		rc = cil_complex_symtab_insert(symtab, &ckey, &datum);
910 		if (rc != SEPOL_OK) {
911 			goto exit;
912 		}
913 
914 		for (temp_node = rule_node->next;
915 			temp_node != NULL;
916 			temp_node = temp_node->next) {
917 
918 			if (temp_node->flavor == CIL_TYPE_RULE) {
919 				typerule = temp_node->data;
920 				if ((intptr_t)typerule->src == ckey.key1 &&
921 					(intptr_t)typerule->tgt == ckey.key2 &&
922 					(intptr_t)typerule->obj == ckey.key3 &&
923 					(intptr_t)typerule->rule_kind == ckey.key4) {
924 					cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line);
925 					rc = SEPOL_ERR;
926 					goto exit;
927 				}
928 			}
929 		}
930 		break;*/
931 
932 		//TODO Fix duplicate type_rule detection
933 		break;
934 	case CIL_CALL:
935 		//Fall through to check content of call
936 		break;
937 	case CIL_TUNABLEIF:
938 		//Fall through
939 		break;
940 	case CIL_NAMETYPETRANSITION:
941 		/* While type transitions with file component are not allowed in
942 		   booleanif statements if they don't have "*" as the file. We
943 		   can't check that here. Or at least we won't right now. */
944 		break;
945 	default: {
946 		const char * flavor = cil_node_to_string(node);
947 		if (bif->preserved_tunable) {
948 			cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor);
949 		} else {
950 			cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor);
951 		}
952 		goto exit;
953 	}
954 	}
955 
956 	rc = SEPOL_OK;
957 exit:
958 	return rc;
959 }
960 
__cil_verify_booleanif(struct cil_tree_node * node,struct cil_complex_symtab * symtab)961 int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
962 {
963 	int rc = SEPOL_ERR;
964 	struct cil_booleanif *bif = (struct cil_booleanif*)node->data;
965 	struct cil_tree_node *cond_block = node->cl_head;
966 
967 	while (cond_block != NULL) {
968 		rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab);
969 		if (rc != SEPOL_OK) {
970 			goto exit;
971 		}
972 		cond_block = cond_block->next;
973 	}
974 
975 	return SEPOL_OK;
976 exit:
977 	if (bif->preserved_tunable) {
978 		cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)");
979 	} else {
980 		cil_tree_log(node, CIL_ERR, "Invalid booleanif");
981 	}
982 	return rc;
983 }
984 
__cil_verify_netifcon(struct cil_db * db,struct cil_tree_node * node)985 int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node)
986 {
987 	int rc = SEPOL_ERR;
988 	struct cil_netifcon *netif = node->data;
989 	struct cil_context *if_ctx = netif->if_context;
990 	struct cil_context *pkt_ctx = netif->packet_context;
991 
992 	/* Verify only when anonymous */
993 	if (if_ctx->datum.name == NULL) {
994 		rc = __cil_verify_context(db, if_ctx);
995 		if (rc != SEPOL_OK) {
996 			goto exit;
997 		}
998 	}
999 
1000 	/* Verify only when anonymous */
1001 	if (pkt_ctx->datum.name == NULL) {
1002 		rc = __cil_verify_context(db, pkt_ctx);
1003 		if (rc != SEPOL_OK) {
1004 			goto exit;
1005 		}
1006 	}
1007 
1008 	return SEPOL_OK;
1009 
1010 exit:
1011 	cil_tree_log(node, CIL_ERR, "Invalid netifcon");
1012 	return rc;
1013 }
1014 
__cil_verify_genfscon(struct cil_db * db,struct cil_tree_node * node)1015 int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node)
1016 {
1017 	int rc = SEPOL_ERR;
1018 	struct cil_genfscon *genfs = node->data;
1019 	struct cil_context *ctx = genfs->context;
1020 
1021 	/* Verify only when anonymous */
1022 	if (ctx->datum.name == NULL) {
1023 		rc = __cil_verify_context(db, ctx);
1024 		if (rc != SEPOL_OK) {
1025 			goto exit;
1026 		}
1027 	}
1028 
1029 	return SEPOL_OK;
1030 
1031 exit:
1032 	cil_tree_log(node, CIL_ERR, "Invalid genfscon");
1033 	return rc;
1034 }
1035 
__cil_verify_filecon(struct cil_db * db,struct cil_tree_node * node)1036 int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node)
1037 {
1038 	int rc = SEPOL_ERR;
1039 	struct cil_filecon *file = node->data;
1040 	struct cil_context *ctx = file->context;
1041 
1042 	if (ctx == NULL) {
1043 		rc = SEPOL_OK;
1044 		goto exit;
1045 	}
1046 
1047 	/* Verify only when anonymous */
1048 	if (ctx->datum.name == NULL) {
1049 		rc = __cil_verify_context(db, ctx);
1050 		if (rc != SEPOL_OK) {
1051 			cil_tree_log(node, CIL_ERR, "Invalid filecon");
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_tree_log(node, CIL_ERR, "Invalid nodecon");
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_tree_log(node, CIL_ERR, "Invalid portcon");
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_tree_log(node, CIL_ERR, "Invalid pirqcon");
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_tree_log(node, CIL_ERR, "Invalid iomemcon");
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_tree_log(node, CIL_ERR, "Invalid ioportcon");
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_tree_log(node, CIL_ERR, "Invalid pcidevicecon");
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_tree_log(node, CIL_ERR, "Invalid devicetreecon");
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_tree_log(node, CIL_ERR, "Invalid fsuse");
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_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind);
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_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", 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_tree_log(node, CIL_ERR, "Invalid class");
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_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name);
1333 	return rc;
1334 }
1335 
__cil_verify_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1336 int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1337 {
1338 	int rc = SEPOL_ERR;
1339 	int *avrule_cnt = 0;
1340 	int *handleunknown;
1341 	int *mls;
1342 	int *nseuserdflt = 0;
1343 	int *pass = 0;
1344 	struct cil_args_verify *args = extra_args;
1345 	struct cil_complex_symtab *csymtab = NULL;
1346 	struct cil_db *db = NULL;
1347 
1348 	if (node == NULL || extra_args == NULL) {
1349 		goto exit;
1350 	}
1351 
1352 	db = args->db;
1353 	avrule_cnt = args->avrule_cnt;
1354 	handleunknown = args->handleunknown;
1355 	mls = args->mls;
1356 	nseuserdflt = args->nseuserdflt;
1357 	csymtab = args->csymtab;
1358 	pass = args->pass;
1359 
1360 	if (node->flavor == CIL_MACRO) {
1361 		*finished = CIL_TREE_SKIP_HEAD;
1362 		rc = SEPOL_OK;
1363 		goto exit;
1364 	} else if (node->flavor == CIL_BLOCK) {
1365 		struct cil_block *blk = node->data;
1366 		if (blk->is_abstract == CIL_TRUE) {
1367 			*finished = CIL_TREE_SKIP_HEAD;
1368 		}
1369 		rc = SEPOL_OK;
1370 		goto exit;
1371 	}
1372 
1373 	switch (*pass) {
1374 	case 0: {
1375 		switch (node->flavor) {
1376 		case CIL_USER:
1377 			rc = __cil_verify_user_post_eval(db, node);
1378 			break;
1379 		case CIL_SELINUXUSERDEFAULT:
1380 			(*nseuserdflt)++;
1381 			rc = SEPOL_OK;
1382 			break;
1383 		case CIL_ROLE:
1384 			rc = __cil_verify_role(node);
1385 			break;
1386 		case CIL_TYPE:
1387 			rc = __cil_verify_type(node);
1388 			break;
1389 		case CIL_AVRULE:
1390 			(*avrule_cnt)++;
1391 			rc = SEPOL_OK;
1392 			break;
1393 		case CIL_HANDLEUNKNOWN:
1394 			if (*handleunknown != -1) {
1395 				cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n");
1396 				rc = SEPOL_ERR;
1397 			} else {
1398 				*handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown;
1399 				rc = SEPOL_OK;
1400 			}
1401 			break;
1402 		case CIL_MLS:
1403 			if (*mls != -1) {
1404 				cil_log(CIL_ERR, "Policy can not have more than one mls\n");
1405 				rc = SEPOL_ERR;
1406 			} else {
1407 				*mls = ((struct cil_mls*)node->data)->value;
1408 				rc = SEPOL_OK;
1409 			}
1410 			break;
1411 		case CIL_ROLETRANSITION:
1412 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1413 			//rc = __cil_verify_rule(node, csymtab);
1414 			break;
1415 		case CIL_TYPE_RULE:
1416 			rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1417 			//rc = __cil_verify_rule(node, csymtab);
1418 			break;
1419 		case CIL_BOOLEANIF:
1420 			rc = __cil_verify_booleanif(node, csymtab);
1421 			*finished = CIL_TREE_SKIP_HEAD;
1422 			break;
1423 		case CIL_LEVELRANGE:
1424 			rc = __cil_verify_named_levelrange(db, node);
1425 			break;
1426 		case CIL_CLASS:
1427 			rc = __cil_verify_class(node);
1428 			break;
1429 		case CIL_POLICYCAP:
1430 			rc = __cil_verify_policycap(node);
1431 			break;
1432 		default:
1433 			rc = SEPOL_OK;
1434 			break;
1435 		}
1436 		break;
1437 	}
1438 	case 1:	{
1439 		switch (node->flavor) {
1440 		case CIL_CONTEXT:
1441 			rc = __cil_verify_named_context(db, node);
1442 			break;
1443 		case CIL_NETIFCON:
1444 			rc = __cil_verify_netifcon(db, node);
1445 			break;
1446 		case CIL_GENFSCON:
1447 			rc = __cil_verify_genfscon(db, node);
1448 			break;
1449 		case CIL_FILECON:
1450 			rc = __cil_verify_filecon(db, node);
1451 			break;
1452 		case CIL_NODECON:
1453 			rc = __cil_verify_nodecon(db, node);
1454 			break;
1455 		case CIL_PORTCON:
1456 			rc = __cil_verify_portcon(db, node);
1457 			break;
1458 		case CIL_PIRQCON:
1459 			rc = __cil_verify_pirqcon(db, node);
1460 			break;
1461 		case CIL_IOMEMCON:
1462 			rc = __cil_verify_iomemcon(db, node);
1463 			break;
1464 		case CIL_IOPORTCON:
1465 			rc = __cil_verify_ioportcon(db, node);
1466 			break;
1467 		case CIL_PCIDEVICECON:
1468 			rc = __cil_verify_pcidevicecon(db, node);
1469 			break;
1470 		case CIL_DEVICETREECON:
1471 			rc = __cil_verify_devicetreecon(db, node);
1472 			break;
1473 		case CIL_FSUSE:
1474 			rc = __cil_verify_fsuse(db, node);
1475 			break;
1476 		case CIL_AVRULEX:
1477 			rc = __cil_verify_avrulex(node);
1478 			break;
1479 		case CIL_PERMISSIONX:
1480 			rc = __cil_verify_permissionx(node->data, node);
1481 			break;
1482 		case CIL_RANGETRANSITION:
1483 			rc = SEPOL_OK;
1484 			break;
1485 		default:
1486 			rc = SEPOL_OK;
1487 			break;
1488 		}
1489 		break;
1490 	}
1491 	default:
1492 		rc = SEPOL_ERR;
1493 	}
1494 
1495 exit:
1496 	return rc;
1497 }
1498 
__cil_verify_classperms(struct cil_list * classperms,struct cil_symtab_datum * orig)1499 static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig)
1500 {
1501 	int rc = SEPOL_ERR;
1502 	struct cil_list_item *curr;
1503 
1504 	cil_list_for_each(curr, classperms) {
1505 		if (curr->flavor == CIL_CLASSPERMS) {
1506 			struct cil_classperms *cp = curr->data;
1507 			if (FLAVOR(cp->class) == CIL_CLASS) {
1508 				return SEPOL_OK;
1509 			} else { /* MAP */
1510 				struct cil_list_item *i = NULL;
1511 				cil_list_for_each(i, cp->perms) {
1512 					struct cil_perm *cmp = i->data;
1513 					if (&cmp->datum == orig) {
1514 						rc = SEPOL_ERR;
1515 						goto exit;
1516 					}
1517 					rc = __cil_verify_classperms(cmp->classperms, orig);
1518 					if (rc != SEPOL_OK) {
1519 						goto exit;
1520 					}
1521 				}
1522 			}
1523 		} else { /* SET */
1524 			struct cil_classperms_set *cp_set = curr->data;
1525 			struct cil_classpermission *cp = cp_set->set;
1526 			if (&cp->datum == orig) {
1527 				rc = SEPOL_ERR;
1528 				goto exit;
1529 			}
1530 			rc = __cil_verify_classperms(cp->classperms, orig);
1531 			if (rc != SEPOL_OK) {
1532 				goto exit;
1533 			}
1534 		}
1535 	}
1536 
1537 	return SEPOL_OK;
1538 
1539 exit:
1540 	return rc;
1541 }
1542 
__cil_verify_classpermission(struct cil_tree_node * node)1543 static int __cil_verify_classpermission(struct cil_tree_node *node)
1544 {
1545 	int rc = SEPOL_ERR;
1546 	struct cil_classpermission *cp = node->data;
1547 
1548 	if (cp->classperms == NULL) {
1549 		cil_tree_log(node, CIL_ERR, "Classpermission %s does not have a classpermissionset", cp->datum.name);
1550 		rc = SEPOL_ERR;
1551 		goto exit;
1552 	}
1553 
1554 	rc = __cil_verify_classperms(cp->classperms, &cp->datum);
1555 	if (rc != SEPOL_OK) {
1556 		cil_tree_log(node, CIL_ERR, "Found circular class permissions involving the set %s",cp->datum.name);
1557 		goto exit;
1558 	}
1559 
1560 	rc = SEPOL_OK;
1561 
1562 exit:
1563 	return rc;
1564 }
1565 
1566 struct cil_verify_map_args {
1567 	struct cil_class *class;
1568 	struct cil_tree_node *node;
1569 	int rc;
1570 };
1571 
__verify_map_perm_classperms(hashtab_key_t k,hashtab_datum_t d,void * args)1572 static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1573 {
1574 	int rc = SEPOL_ERR;
1575 	struct cil_verify_map_args *map_args = args;
1576 	struct cil_perm *cmp = (struct cil_perm *)d;
1577 
1578 	if (cmp->classperms == NULL) {
1579 		cil_tree_log(map_args->node, CIL_ERR, "Map class %s does not have a classmapping for %s", map_args->class->datum.name, cmp->datum.name);
1580 		map_args->rc = SEPOL_ERR;
1581 		goto exit;
1582 	}
1583 
1584 	rc = __cil_verify_classperms(cmp->classperms, &cmp->datum);
1585 	if (rc != SEPOL_OK) {
1586 		cil_tree_log(map_args->node, CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", map_args->class->datum.name, cmp->datum.name);
1587 		map_args->rc = SEPOL_ERR;
1588 		goto exit;
1589 	}
1590 
1591 exit:
1592 	return SEPOL_OK;
1593 }
1594 
__cil_verify_map_class(struct cil_tree_node * node)1595 static int __cil_verify_map_class(struct cil_tree_node *node)
1596 {
1597 	struct cil_class *mc = node->data;
1598 	struct cil_verify_map_args map_args;
1599 
1600 	map_args.class = mc;
1601 	map_args.node = node;
1602 	map_args.rc = SEPOL_OK;
1603 
1604 	cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args);
1605 
1606 	if (map_args.rc != SEPOL_OK) {
1607 		return SEPOL_ERR;
1608 	}
1609 
1610 	return SEPOL_OK;
1611 }
1612 
__cil_pre_verify_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1613 int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
1614 {
1615 	int rc = SEPOL_ERR;
1616 
1617 	if (node->flavor == CIL_MACRO) {
1618 		*finished = CIL_TREE_SKIP_HEAD;
1619 		rc = SEPOL_OK;
1620 		goto exit;
1621 	} else if (node->flavor == CIL_BLOCK) {
1622 		struct cil_block *blk = node->data;
1623 		if (blk->is_abstract == CIL_TRUE) {
1624 			*finished = CIL_TREE_SKIP_HEAD;
1625 		}
1626 		rc = SEPOL_OK;
1627 		goto exit;
1628 	}
1629 
1630 	switch (node->flavor) {
1631 	case CIL_USER:
1632 		rc = __cil_verify_user_pre_eval(node);
1633 		if (rc != SEPOL_OK) {
1634 			goto exit;
1635 		}
1636 		break;
1637 	case CIL_MAP_CLASS:
1638 		rc = __cil_verify_map_class(node);
1639 		break;
1640 	case CIL_CLASSPERMISSION:
1641 		rc = __cil_verify_classpermission(node);
1642 		break;
1643 	default:
1644 		rc = SEPOL_OK;
1645 		break;
1646 	}
1647 
1648 exit:
1649 	return rc;
1650 }
1651