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