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