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