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