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