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