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