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
34 #include <sepol/policydb/conditional.h>
35
36 #include "cil_internal.h"
37 #include "cil_flavor.h"
38 #include "cil_log.h"
39 #include "cil_mem.h"
40 #include "cil_tree.h"
41 #include "cil_list.h"
42 #include "cil_build_ast.h"
43 #include "cil_resolve_ast.h"
44 #include "cil_reset_ast.h"
45 #include "cil_copy_ast.h"
46 #include "cil_verify.h"
47 #include "cil_strpool.h"
48 #include "cil_symtab.h"
49
50 struct cil_args_resolve {
51 struct cil_db *db;
52 enum cil_pass pass;
53 uint32_t *changed;
54 char *last_resolved_name;
55 struct cil_tree_node *optstack;
56 struct cil_tree_node *boolif;
57 struct cil_tree_node *macro;
58 struct cil_tree_node *blockstack;
59 struct cil_list *sidorder_lists;
60 struct cil_list *classorder_lists;
61 struct cil_list *unordered_classorder_lists;
62 struct cil_list *catorder_lists;
63 struct cil_list *sensitivityorder_lists;
64 struct cil_list *in_list;
65 };
66
__cil_insert_name(struct cil_db * db,hashtab_key_t key,struct cil_tree_node * ast_node)67 static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node)
68 {
69 /* Currently only used for typetransition file names.
70 But could be used for any string that is passed as a parameter.
71 */
72 struct cil_tree_node *parent = ast_node->parent;
73 struct cil_macro *macro = NULL;
74 struct cil_name *name;
75 symtab_t *symtab;
76 enum cil_sym_index sym_index;
77 struct cil_symtab_datum *datum = NULL;
78
79 cil_flavor_to_symtab_index(CIL_NAME, &sym_index);
80 symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
81
82 cil_symtab_get_datum(symtab, key, &datum);
83 if (datum != NULL) {
84 return (struct cil_name *)datum;
85 }
86
87 if (parent->flavor == CIL_CALL) {
88 struct cil_call *call = parent->data;
89 macro = call->macro;
90 } else if (parent->flavor == CIL_MACRO) {
91 macro = parent->data;
92 }
93 if (macro != NULL) {
94 struct cil_list_item *item;
95 cil_list_for_each(item, macro->params) {
96 if (((struct cil_param*)item->data)->str == key) {
97 return NULL;
98 }
99 }
100 }
101
102 cil_name_init(&name);
103 cil_symtab_insert(symtab, key, (struct cil_symtab_datum *)name, ast_node);
104 cil_list_append(db->names, CIL_NAME, name);
105
106 return name;
107 }
108
__cil_resolve_perms(symtab_t * class_symtab,symtab_t * common_symtab,struct cil_list * perm_strs,struct cil_list ** perm_datums,enum cil_flavor class_flavor)109 static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab, struct cil_list *perm_strs, struct cil_list **perm_datums, enum cil_flavor class_flavor)
110 {
111 int rc = SEPOL_ERR;
112 struct cil_list_item *curr;
113
114 cil_list_init(perm_datums, perm_strs->flavor);
115
116 cil_list_for_each(curr, perm_strs) {
117 if (curr->flavor == CIL_LIST) {
118 struct cil_list *sub_list;
119 rc = __cil_resolve_perms(class_symtab, common_symtab, curr->data, &sub_list, class_flavor);
120 if (rc != SEPOL_OK) {
121 cil_log(CIL_ERR, "Failed to resolve permission list\n");
122 goto exit;
123 }
124 cil_list_append(*perm_datums, CIL_LIST, sub_list);
125 } else if (curr->flavor == CIL_STRING) {
126 struct cil_symtab_datum *perm_datum = NULL;
127 rc = cil_symtab_get_datum(class_symtab, curr->data, &perm_datum);
128 if (rc == SEPOL_ENOENT) {
129 if (common_symtab) {
130 rc = cil_symtab_get_datum(common_symtab, curr->data, &perm_datum);
131 }
132 }
133 if (rc != SEPOL_OK) {
134 struct cil_list *empty_list;
135 if (class_flavor == CIL_MAP_CLASS) {
136 cil_log(CIL_ERR, "Failed to resolve permission %s for map class\n", (char*)curr->data);
137 goto exit;
138 }
139 cil_log(CIL_WARN, "Failed to resolve permission %s\n", (char*)curr->data);
140 /* Use an empty list to represent unknown perm */
141 cil_list_init(&empty_list, perm_strs->flavor);
142 cil_list_append(*perm_datums, CIL_LIST, empty_list);
143 } else {
144 cil_list_append(*perm_datums, CIL_DATUM, perm_datum);
145 }
146 } else {
147 cil_list_append(*perm_datums, curr->flavor, curr->data);
148 }
149 }
150
151 return SEPOL_OK;
152
153 exit:
154 return rc;
155 }
156
cil_resolve_classperms(struct cil_tree_node * current,struct cil_classperms * cp,void * extra_args)157 int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, void *extra_args)
158 {
159 int rc = SEPOL_ERR;
160 struct cil_symtab_datum *datum = NULL;
161 symtab_t *common_symtab = NULL;
162 struct cil_class *class;
163
164 rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum);
165 if (rc != SEPOL_OK) {
166 goto exit;
167 }
168
169 class = (struct cil_class *)datum;
170
171 if (class->common != NULL) {
172 common_symtab = &class->common->perms;
173 }
174
175 cp->class = class;
176
177 rc = __cil_resolve_perms(&class->perms, common_symtab, cp->perm_strs, &cp->perms, FLAVOR(datum));
178 if (rc != SEPOL_OK) {
179 goto exit;
180 }
181
182 return SEPOL_OK;
183
184 exit:
185 return rc;
186 }
187
cil_resolve_classperms_set(struct cil_tree_node * current,struct cil_classperms_set * cp_set,void * extra_args)188 int cil_resolve_classperms_set(struct cil_tree_node *current, struct cil_classperms_set *cp_set, void *extra_args)
189 {
190 int rc = SEPOL_ERR;
191 struct cil_symtab_datum *datum = NULL;
192
193 rc = cil_resolve_name(current, cp_set->set_str, CIL_SYM_CLASSPERMSETS, extra_args, &datum);
194 if (rc != SEPOL_OK) {
195 goto exit;
196 }
197 cp_set->set = (struct cil_classpermission*)datum;
198
199 /* This could be an anonymous classpermission */
200 if (datum->name == NULL) {
201 rc = cil_resolve_classperms_list(current, cp_set->set->classperms, extra_args);
202 if (rc != SEPOL_OK) {
203 goto exit;
204 }
205 }
206
207 return SEPOL_OK;
208
209 exit:
210 return rc;
211 }
212
cil_resolve_classperms_list(struct cil_tree_node * current,struct cil_list * cp_list,void * extra_args)213 int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, void *extra_args)
214 {
215 int rc = SEPOL_ERR;
216 struct cil_list_item *curr;
217
218 cil_list_for_each(curr, cp_list) {
219 if (curr->flavor == CIL_CLASSPERMS) {
220 rc = cil_resolve_classperms(current, curr->data, extra_args);
221 if (rc != SEPOL_OK) {
222 goto exit;
223 }
224 } else {
225 rc = cil_resolve_classperms_set(current, curr->data, extra_args);
226 if (rc != SEPOL_OK) {
227 goto exit;
228 }
229 }
230 }
231
232 return SEPOL_OK;
233
234 exit:
235 return rc;
236 }
237
cil_resolve_classpermissionset(struct cil_tree_node * current,struct cil_classpermissionset * cps,void * extra_args)238 int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, void *extra_args)
239 {
240 int rc = SEPOL_ERR;
241 struct cil_args_resolve *args = extra_args;
242 struct cil_list_item *curr;
243 struct cil_symtab_datum *datum;
244 struct cil_classpermission *cp;
245
246 rc = cil_resolve_name(current, cps->set_str, CIL_SYM_CLASSPERMSETS, args, &datum);
247 if (rc != SEPOL_OK) {
248 goto exit;
249 }
250
251 rc = cil_resolve_classperms_list(current, cps->classperms, extra_args);
252 if (rc != SEPOL_OK) {
253 goto exit;
254 }
255
256 cp = (struct cil_classpermission *)datum;
257
258 if (cp->classperms == NULL) {
259 cil_list_init(&cp->classperms, CIL_CLASSPERMS);
260 }
261
262 cil_list_for_each(curr, cps->classperms) {
263 cil_list_append(cp->classperms, curr->flavor, curr->data);
264 }
265
266 return SEPOL_OK;
267
268 exit:
269 return rc;
270 }
271
cil_type_used(struct cil_symtab_datum * datum,int used)272 int cil_type_used(struct cil_symtab_datum *datum, int used)
273 {
274 int rc = SEPOL_ERR;
275 struct cil_typeattribute *attr = NULL;
276
277 if (FLAVOR(datum) == CIL_TYPEATTRIBUTE) {
278 attr = (struct cil_typeattribute*)datum;
279 attr->used |= used;
280 if ((attr->used & CIL_ATTR_EXPAND_TRUE) &&
281 (attr->used & CIL_ATTR_EXPAND_FALSE)) {
282 cil_log(CIL_ERR, "Conflicting use of expandtypeattribute. "
283 "Expandtypeattribute may be set to true or false "
284 "but not both. \n");
285 goto exit;
286 }
287 }
288
289 return SEPOL_OK;
290 exit:
291 return rc;
292 }
293
cil_resolve_permissionx(struct cil_tree_node * current,struct cil_permissionx * permx,void * extra_args)294 int cil_resolve_permissionx(struct cil_tree_node *current, struct cil_permissionx *permx, void *extra_args)
295 {
296 struct cil_symtab_datum *obj_datum = NULL;
297 int rc = SEPOL_ERR;
298
299 rc = cil_resolve_name(current, permx->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
300 if (rc != SEPOL_OK) {
301 goto exit;
302 }
303 permx->obj = (struct cil_class*)obj_datum;
304
305 return SEPOL_OK;
306
307 exit:
308 return rc;
309 }
310
cil_resolve_avrule(struct cil_tree_node * current,void * extra_args)311 int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args)
312 {
313 struct cil_args_resolve *args = extra_args;
314 struct cil_db *db = NULL;
315
316 struct cil_avrule *rule = current->data;
317 struct cil_symtab_datum *src_datum = NULL;
318 struct cil_symtab_datum *tgt_datum = NULL;
319 struct cil_symtab_datum *permx_datum = NULL;
320 int used;
321 int rc = SEPOL_ERR;
322
323 if (args != NULL) {
324 db = args->db;
325 }
326
327 rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, args, &src_datum);
328 if (rc != SEPOL_OK) {
329 goto exit;
330 }
331 rule->src = src_datum;
332
333 if (rule->tgt_str == CIL_KEY_SELF) {
334 rule->tgt = db->selftype;
335 } else {
336 rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum);
337 if (rc != SEPOL_OK) {
338 goto exit;
339 }
340 rule->tgt = tgt_datum;
341 used = (rule->rule_kind == CIL_AVRULE_NEVERALLOW) ?
342 CIL_ATTR_NEVERALLOW : CIL_ATTR_AVRULE;
343 cil_type_used(src_datum, used); /* src not used if tgt is self */
344 cil_type_used(tgt_datum, used);
345 }
346
347 if (!rule->is_extended) {
348 rc = cil_resolve_classperms_list(current, rule->perms.classperms, extra_args);
349 if (rc != SEPOL_OK) {
350 goto exit;
351 }
352 } else {
353 if (rule->perms.x.permx_str != NULL) {
354 rc = cil_resolve_name(current, rule->perms.x.permx_str, CIL_SYM_PERMX, args, &permx_datum);
355 if (rc != SEPOL_OK) {
356 goto exit;
357 }
358 rule->perms.x.permx = (struct cil_permissionx*)permx_datum;
359 } else {
360 rc = cil_resolve_permissionx(current, rule->perms.x.permx, extra_args);
361 if (rc != SEPOL_OK) {
362 goto exit;
363 }
364 }
365 }
366
367 return SEPOL_OK;
368
369 exit:
370 return rc;
371 }
372
cil_resolve_type_rule(struct cil_tree_node * current,void * extra_args)373 int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args)
374 {
375 struct cil_type_rule *rule = current->data;
376 struct cil_symtab_datum *src_datum = NULL;
377 struct cil_symtab_datum *tgt_datum = NULL;
378 struct cil_symtab_datum *obj_datum = NULL;
379 struct cil_symtab_datum *result_datum = NULL;
380 struct cil_tree_node *result_node = NULL;
381 int rc = SEPOL_ERR;
382
383 rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, extra_args, &src_datum);
384 if (rc != SEPOL_OK) {
385 goto exit;
386 }
387 rule->src = src_datum;
388
389 rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum);
390 if (rc != SEPOL_OK) {
391 goto exit;
392 }
393 rule->tgt = tgt_datum;
394
395 rc = cil_resolve_name(current, rule->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
396 if (rc != SEPOL_OK) {
397 goto exit;
398 }
399 rule->obj = (struct cil_class*)obj_datum;
400
401 rc = cil_resolve_name(current, rule->result_str, CIL_SYM_TYPES, extra_args, &result_datum);
402 if (rc != SEPOL_OK) {
403 goto exit;
404 }
405
406 result_node = result_datum->nodes->head->data;
407
408 if (result_node->flavor != CIL_TYPE) {
409 cil_log(CIL_ERR, "Type rule result must be a type [%d]\n",result_node->flavor);
410 rc = SEPOL_ERR;
411 goto exit;
412 }
413 rule->result = result_datum;
414
415 return SEPOL_OK;
416
417 exit:
418 return rc;
419 }
420
cil_resolve_typeattributeset(struct cil_tree_node * current,void * extra_args)421 int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args)
422 {
423 struct cil_typeattributeset *attrtypes = current->data;
424 struct cil_symtab_datum *attr_datum = NULL;
425 struct cil_tree_node *attr_node = NULL;
426 struct cil_typeattribute *attr = NULL;
427 int rc = SEPOL_ERR;
428
429 rc = cil_resolve_name(current, attrtypes->attr_str, CIL_SYM_TYPES, extra_args, &attr_datum);
430 if (rc != SEPOL_OK) {
431 goto exit;
432 }
433
434 attr_node = attr_datum->nodes->head->data;
435
436 if (attr_node->flavor != CIL_TYPEATTRIBUTE) {
437 rc = SEPOL_ERR;
438 cil_log(CIL_ERR, "Attribute type not an attribute\n");
439 goto exit;
440 }
441
442 attr = (struct cil_typeattribute*)attr_datum;
443
444 rc = cil_resolve_expr(CIL_TYPEATTRIBUTESET, attrtypes->str_expr, &attrtypes->datum_expr, current, extra_args);
445 if (rc != SEPOL_OK) {
446 goto exit;
447 }
448
449 rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr);
450 if (rc != SEPOL_OK) {
451 goto exit;
452 }
453
454 if (attr->expr_list == NULL) {
455 cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE);
456 }
457
458 cil_list_append(attr->expr_list, CIL_LIST, attrtypes->datum_expr);
459
460 return SEPOL_OK;
461
462 exit:
463 return rc;
464 }
465
cil_resolve_expandtypeattribute(struct cil_tree_node * current,void * extra_args)466 int cil_resolve_expandtypeattribute(struct cil_tree_node *current, void *extra_args)
467 {
468 struct cil_expandtypeattribute *expandattr = current->data;
469 struct cil_symtab_datum *attr_datum = NULL;
470 struct cil_tree_node *attr_node = NULL;
471 struct cil_list_item *curr;
472 int used;
473 int rc = SEPOL_ERR;
474
475 cil_list_init(&expandattr->attr_datums, CIL_TYPE);
476
477 cil_list_for_each(curr, expandattr->attr_strs) {
478 rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_TYPES, extra_args, &attr_datum);
479 if (rc != SEPOL_OK) {
480 goto exit;
481 }
482
483 attr_node = attr_datum->nodes->head->data;
484
485 if (attr_node->flavor != CIL_TYPEATTRIBUTE) {
486 rc = SEPOL_ERR;
487 cil_log(CIL_ERR, "Attribute type not an attribute\n");
488 goto exit;
489 }
490 used = expandattr->expand ? CIL_ATTR_EXPAND_TRUE : CIL_ATTR_EXPAND_FALSE;
491 rc = cil_type_used(attr_datum, used);
492 if (rc != SEPOL_OK) {
493 goto exit;
494 }
495
496 cil_list_append(expandattr->attr_datums, CIL_TYPE, attr_datum);
497 }
498
499 return SEPOL_OK;
500 exit:
501 return rc;
502 }
503
cil_resolve_aliasactual(struct cil_tree_node * current,void * extra_args,enum cil_flavor flavor,enum cil_flavor alias_flavor)504 int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor alias_flavor)
505 {
506 int rc = SEPOL_ERR;
507 enum cil_sym_index sym_index;
508 struct cil_aliasactual *aliasactual = current->data;
509 struct cil_symtab_datum *alias_datum = NULL;
510 struct cil_symtab_datum *actual_datum = NULL;
511 struct cil_alias *alias;
512
513 rc = cil_flavor_to_symtab_index(flavor, &sym_index);
514 if (rc != SEPOL_OK) {
515 goto exit;
516 }
517
518 rc = cil_resolve_name(current, aliasactual->alias_str, sym_index, extra_args, &alias_datum);
519 if (rc != SEPOL_OK) {
520 goto exit;
521 }
522 if (NODE(alias_datum)->flavor != alias_flavor) {
523 cil_log(CIL_ERR, "%s is not an alias\n",alias_datum->name);
524 goto exit;
525 }
526
527 rc = cil_resolve_name(current, aliasactual->actual_str, sym_index, extra_args, &actual_datum);
528 if (rc != SEPOL_OK) {
529 goto exit;
530 }
531
532 alias = (struct cil_alias *)alias_datum;
533
534 if (alias->actual != NULL) {
535 cil_log(CIL_ERR, "Alias cannot bind more than one value\n");
536 rc = SEPOL_ERR;
537 goto exit;
538 }
539
540 alias->actual = actual_datum;
541
542 return SEPOL_OK;
543
544 exit:
545 return rc;
546 }
547
cil_resolve_alias_to_actual(struct cil_tree_node * current,enum cil_flavor flavor)548 int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_flavor flavor)
549 {
550 struct cil_alias *alias = current->data;
551 struct cil_alias *a1 = current->data;
552 struct cil_alias *a2 = current->data;
553 struct cil_tree_node *a1_node = NULL;
554 int steps = 0;
555 int limit = 2;
556
557 if (alias->actual == NULL) {
558 cil_tree_log(current, CIL_ERR, "Alias declared but not used");
559 return SEPOL_ERR;
560 }
561
562 a1_node = a1->datum.nodes->head->data;
563
564 while (flavor != a1_node->flavor) {
565 a1 = a1->actual;
566 a1_node = a1->datum.nodes->head->data;
567 steps += 1;
568
569 if (a1 == a2) {
570 cil_log(CIL_ERR, "Circular alias found: %s ", a1->datum.name);
571 a1 = a1->actual;
572 while (a1 != a2) {
573 cil_log(CIL_ERR, "%s ", a1->datum.name);
574 a1 = a1->actual;
575 }
576 cil_log(CIL_ERR,"\n");
577 return SEPOL_ERR;
578 }
579
580 if (steps == limit) {
581 steps = 0;
582 limit *= 2;
583 a2 = a1;
584 }
585 }
586
587 alias->actual = a1;
588
589 return SEPOL_OK;
590 }
591
cil_resolve_typepermissive(struct cil_tree_node * current,void * extra_args)592 int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args)
593 {
594 struct cil_typepermissive *typeperm = current->data;
595 struct cil_symtab_datum *type_datum = NULL;
596 struct cil_tree_node *type_node = NULL;
597 int rc = SEPOL_ERR;
598
599 rc = cil_resolve_name(current, typeperm->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
600 if (rc != SEPOL_OK) {
601 goto exit;
602 }
603
604 type_node = type_datum->nodes->head->data;
605
606 if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) {
607 cil_log(CIL_ERR, "Typepermissive must be a type or type alias\n");
608 rc = SEPOL_ERR;
609 goto exit;
610 }
611
612 typeperm->type = type_datum;
613
614 return SEPOL_OK;
615
616 exit:
617 return rc;
618 }
619
cil_resolve_nametypetransition(struct cil_tree_node * current,void * extra_args)620 int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_args)
621 {
622 struct cil_args_resolve *args = extra_args;
623 struct cil_nametypetransition *nametypetrans = current->data;
624 struct cil_symtab_datum *src_datum = NULL;
625 struct cil_symtab_datum *tgt_datum = NULL;
626 struct cil_symtab_datum *obj_datum = NULL;
627 struct cil_symtab_datum *name_datum = NULL;
628 struct cil_symtab_datum *result_datum = NULL;
629 struct cil_tree_node *result_node = NULL;
630 int rc = SEPOL_ERR;
631
632 rc = cil_resolve_name(current, nametypetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum);
633 if (rc != SEPOL_OK) {
634 goto exit;
635 }
636 nametypetrans->src = src_datum;
637
638 rc = cil_resolve_name(current, nametypetrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum);
639 if (rc != SEPOL_OK) {
640 goto exit;
641 }
642 nametypetrans->tgt = tgt_datum;
643
644 rc = cil_resolve_name(current, nametypetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
645 if (rc != SEPOL_OK) {
646 goto exit;
647 }
648 nametypetrans->obj = (struct cil_class*)obj_datum;
649
650 nametypetrans->name = __cil_insert_name(args->db, nametypetrans->name_str, current);
651 if (nametypetrans->name == NULL) {
652 rc = cil_resolve_name(current, nametypetrans->name_str, CIL_SYM_NAMES, extra_args, &name_datum);
653 if (rc != SEPOL_OK) {
654 goto exit;
655 }
656 nametypetrans->name = (struct cil_name *)name_datum;
657 }
658
659 rc = cil_resolve_name(current, nametypetrans->result_str, CIL_SYM_TYPES, extra_args, &result_datum);
660 if (rc != SEPOL_OK) {
661 goto exit;
662 }
663
664 result_node = result_datum->nodes->head->data;
665
666 if (result_node->flavor != CIL_TYPE && result_node->flavor != CIL_TYPEALIAS) {
667 cil_log(CIL_ERR, "typetransition result is not a type or type alias\n");
668 rc = SEPOL_ERR;
669 goto exit;
670 }
671 nametypetrans->result = result_datum;
672
673 return SEPOL_OK;
674
675 exit:
676 return rc;
677 }
678
cil_resolve_rangetransition(struct cil_tree_node * current,void * extra_args)679 int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args)
680 {
681 struct cil_rangetransition *rangetrans = current->data;
682 struct cil_symtab_datum *src_datum = NULL;
683 struct cil_symtab_datum *exec_datum = NULL;
684 struct cil_symtab_datum *obj_datum = NULL;
685 struct cil_symtab_datum *range_datum = NULL;
686 int rc = SEPOL_ERR;
687
688 rc = cil_resolve_name(current, rangetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum);
689 if (rc != SEPOL_OK) {
690 goto exit;
691 }
692 rangetrans->src = src_datum;
693
694 rc = cil_resolve_name(current, rangetrans->exec_str, CIL_SYM_TYPES, extra_args, &exec_datum);
695 if (rc != SEPOL_OK) {
696 goto exit;
697 }
698 rangetrans->exec = exec_datum;
699
700 rc = cil_resolve_name(current, rangetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
701 if (rc != SEPOL_OK) {
702 goto exit;
703 }
704 rangetrans->obj = (struct cil_class*)obj_datum;
705
706 if (rangetrans->range_str != NULL) {
707 rc = cil_resolve_name(current, rangetrans->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum);
708 if (rc != SEPOL_OK) {
709 goto exit;
710 }
711 rangetrans->range = (struct cil_levelrange*)range_datum;
712
713 /* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/
714 if (rangetrans->range->datum.name == NULL) {
715 rc = cil_resolve_levelrange(current, rangetrans->range, extra_args);
716 if (rc != SEPOL_OK) {
717 goto exit;
718 }
719 }
720 } else {
721 rc = cil_resolve_levelrange(current, rangetrans->range, extra_args);
722 if (rc != SEPOL_OK) {
723 goto exit;
724 }
725 }
726
727 return SEPOL_OK;
728
729 exit:
730 return rc;
731 }
732
__class_update_perm_values(hashtab_key_t k,hashtab_datum_t d,void * args)733 int __class_update_perm_values(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
734 {
735 struct cil_perm *perm = (struct cil_perm *)d;
736
737 perm->value += *((int *)args);
738
739 return SEPOL_OK;
740 }
741
cil_resolve_classcommon(struct cil_tree_node * current,void * extra_args)742 int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args)
743 {
744 struct cil_class *class = NULL;
745 struct cil_class *common = NULL;
746 struct cil_classcommon *clscom = current->data;
747 struct cil_symtab_datum *class_datum = NULL;
748 struct cil_symtab_datum *common_datum = NULL;
749 int rc = SEPOL_ERR;
750
751 rc = cil_resolve_name(current, clscom->class_str, CIL_SYM_CLASSES, extra_args, &class_datum);
752 if (rc != SEPOL_OK) {
753 goto exit;
754 }
755
756 rc = cil_resolve_name(current, clscom->common_str, CIL_SYM_COMMONS, extra_args, &common_datum);
757 if (rc != SEPOL_OK) {
758 goto exit;
759 }
760
761 class = (struct cil_class *)class_datum;
762 common = (struct cil_class *)common_datum;
763 if (class->common != NULL) {
764 cil_log(CIL_ERR, "class cannot be associeated with more than one common\n");
765 rc = SEPOL_ERR;
766 goto exit;
767 }
768
769 class->common = common;
770
771 cil_symtab_map(&class->perms, __class_update_perm_values, &common->num_perms);
772
773 class->num_perms += common->num_perms;
774 if (class->num_perms > CIL_PERMS_PER_CLASS) {
775 cil_tree_log(current, CIL_ERR, "Too many permissions in class '%s' when including common permissions", class->datum.name);
776 goto exit;
777 }
778
779 return SEPOL_OK;
780
781 exit:
782 return rc;
783 }
784
cil_resolve_classmapping(struct cil_tree_node * current,void * extra_args)785 int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args)
786 {
787 int rc = SEPOL_ERR;
788 struct cil_classmapping *mapping = current->data;
789 struct cil_class *map = NULL;
790 struct cil_perm *mp = NULL;
791 struct cil_symtab_datum *datum = NULL;
792 struct cil_list_item *curr;
793
794 rc = cil_resolve_name(current, mapping->map_class_str, CIL_SYM_CLASSES, extra_args, &datum);
795 if (rc != SEPOL_OK) {
796 goto exit;
797 }
798 map = (struct cil_class*)datum;
799
800 rc = cil_symtab_get_datum(&map->perms, mapping->map_perm_str, &datum);
801 if (rc != SEPOL_OK) {
802 goto exit;
803 }
804
805 mp = (struct cil_perm*)datum;
806
807 rc = cil_resolve_classperms_list(current, mapping->classperms, extra_args);
808 if (rc != SEPOL_OK) {
809 goto exit;
810 }
811
812 if (mp->classperms == NULL) {
813 cil_list_init(&mp->classperms, CIL_CLASSPERMS);
814 }
815
816 cil_list_for_each(curr, mapping->classperms) {
817 cil_list_append(mp->classperms, curr->flavor, curr->data);
818 }
819
820 return SEPOL_OK;
821
822 exit:
823 return rc;
824 }
825
cil_resolve_userrole(struct cil_tree_node * current,void * extra_args)826 int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args)
827 {
828 struct cil_userrole *userrole = current->data;
829 struct cil_symtab_datum *user_datum = NULL;
830 struct cil_symtab_datum *role_datum = NULL;
831 int rc = SEPOL_ERR;
832
833 rc = cil_resolve_name(current, userrole->user_str, CIL_SYM_USERS, extra_args, &user_datum);
834 if (rc != SEPOL_OK) {
835 goto exit;
836 }
837 userrole->user = (struct cil_user*)user_datum;
838
839 rc = cil_resolve_name(current, userrole->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
840 if (rc != SEPOL_OK) {
841 goto exit;
842 }
843 userrole->role = role_datum;
844
845 return SEPOL_OK;
846
847 exit:
848 return rc;
849 }
850
cil_resolve_userlevel(struct cil_tree_node * current,void * extra_args)851 int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args)
852 {
853 struct cil_userlevel *usrlvl = current->data;
854 struct cil_symtab_datum *user_datum = NULL;
855 struct cil_symtab_datum *lvl_datum = NULL;
856 struct cil_user *user = NULL;
857 struct cil_tree_node *user_node = NULL;
858 int rc = SEPOL_ERR;
859
860 rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, extra_args, &user_datum);
861 if (rc != SEPOL_OK) {
862 goto exit;
863 }
864
865 user_node = user_datum->nodes->head->data;
866
867 if (user_node->flavor != CIL_USER) {
868 cil_log(CIL_ERR, "Userlevel must be a user\n");
869 rc = SEPOL_ERR;
870 goto exit;
871 }
872
873 user = (struct cil_user*)user_datum;
874
875 if (usrlvl->level_str != NULL) {
876 rc = cil_resolve_name(current, usrlvl->level_str, CIL_SYM_LEVELS, extra_args, &lvl_datum);
877 if (rc != SEPOL_OK) {
878 goto exit;
879 }
880 usrlvl->level = (struct cil_level*)lvl_datum;
881 user->dftlevel = usrlvl->level;
882
883 /* This could still be an anonymous level even if level_str is set, if level_str is a param_str*/
884 if (user->dftlevel->datum.name == NULL) {
885 rc = cil_resolve_level(current, user->dftlevel, extra_args);
886 if (rc != SEPOL_OK) {
887 goto exit;
888 }
889 }
890 } else if (usrlvl->level != NULL) {
891 rc = cil_resolve_level(current, usrlvl->level, extra_args);
892 if (rc != SEPOL_OK) {
893 goto exit;
894 }
895 user->dftlevel = usrlvl->level;
896 }
897
898 return SEPOL_OK;
899
900 exit:
901 return rc;
902 }
903
cil_resolve_userrange(struct cil_tree_node * current,void * extra_args)904 int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args)
905 {
906 struct cil_userrange *userrange = current->data;
907 struct cil_symtab_datum *user_datum = NULL;
908 struct cil_symtab_datum *range_datum = NULL;
909 struct cil_user *user = NULL;
910 struct cil_tree_node *user_node = NULL;
911 int rc = SEPOL_ERR;
912
913 rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, extra_args, &user_datum);
914 if (rc != SEPOL_OK) {
915 goto exit;
916 }
917
918 user_node = user_datum->nodes->head->data;
919
920 if (user_node->flavor != CIL_USER) {
921 cil_log(CIL_ERR, "Userrange must be a user: %s\n", user_datum->fqn);
922 rc = SEPOL_ERR;
923 goto exit;
924 }
925
926 user = (struct cil_user*)user_datum;
927
928 if (userrange->range_str != NULL) {
929 rc = cil_resolve_name(current, userrange->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum);
930 if (rc != SEPOL_OK) {
931 goto exit;
932 }
933 userrange->range = (struct cil_levelrange*)range_datum;
934 user->range = userrange->range;
935
936 /* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/
937 if (user->range->datum.name == NULL) {
938 rc = cil_resolve_levelrange(current, user->range, extra_args);
939 if (rc != SEPOL_OK) {
940 goto exit;
941 }
942 }
943 } else if (userrange->range != NULL) {
944 rc = cil_resolve_levelrange(current, userrange->range, extra_args);
945 if (rc != SEPOL_OK) {
946 goto exit;
947 }
948 user->range = userrange->range;
949 }
950
951 return SEPOL_OK;
952
953 exit:
954 return rc;
955 }
956
cil_resolve_userprefix(struct cil_tree_node * current,void * extra_args)957 int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args)
958 {
959 struct cil_userprefix *userprefix = current->data;
960 struct cil_symtab_datum *user_datum = NULL;
961 struct cil_tree_node *user_node = NULL;
962 int rc = SEPOL_ERR;
963
964 rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, extra_args, &user_datum);
965 if (rc != SEPOL_OK) {
966 goto exit;
967 }
968
969 user_node = user_datum->nodes->head->data;
970
971 if (user_node->flavor != CIL_USER) {
972 cil_log(CIL_ERR, "Userprefix must be a user: %s\n", user_datum->fqn);
973 rc = SEPOL_ERR;
974 goto exit;
975 }
976
977 userprefix->user = (struct cil_user*)user_datum;
978
979 exit:
980 return rc;
981 }
982
cil_resolve_selinuxuser(struct cil_tree_node * current,void * extra_args)983 int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args)
984 {
985 struct cil_selinuxuser *selinuxuser = current->data;
986 struct cil_symtab_datum *user_datum = NULL;
987 struct cil_symtab_datum *lvlrange_datum = NULL;
988 struct cil_tree_node *user_node = NULL;
989 int rc = SEPOL_ERR;
990
991 rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, extra_args, &user_datum);
992 if (rc != SEPOL_OK) {
993 goto exit;
994 }
995
996 user_node = user_datum->nodes->head->data;
997
998 if (user_node->flavor != CIL_USER) {
999 cil_log(CIL_ERR, "Selinuxuser must be a user: %s\n", user_datum->fqn);
1000 rc = SEPOL_ERR;
1001 goto exit;
1002 }
1003
1004 selinuxuser->user = (struct cil_user*)user_datum;
1005
1006 if (selinuxuser->range_str != NULL) {
1007 rc = cil_resolve_name(current, selinuxuser->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
1008 if (rc != SEPOL_OK) {
1009 goto exit;
1010 }
1011 selinuxuser->range = (struct cil_levelrange*)lvlrange_datum;
1012
1013 /* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/
1014 if (selinuxuser->range->datum.name == NULL) {
1015 rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args);
1016 if (rc != SEPOL_OK) {
1017 goto exit;
1018 }
1019 }
1020 } else if (selinuxuser->range != NULL) {
1021 rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args);
1022 if (rc != SEPOL_OK) {
1023 goto exit;
1024 }
1025 }
1026
1027 rc = SEPOL_OK;
1028 exit:
1029 return rc;
1030 }
1031
cil_resolve_roletype(struct cil_tree_node * current,void * extra_args)1032 int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args)
1033 {
1034 struct cil_roletype *roletype = current->data;
1035 struct cil_symtab_datum *role_datum = NULL;
1036 struct cil_symtab_datum *type_datum = NULL;
1037 int rc = SEPOL_ERR;
1038
1039 rc = cil_resolve_name(current, roletype->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
1040 if (rc != SEPOL_OK) {
1041 goto exit;
1042 }
1043 roletype->role = (struct cil_role*)role_datum;
1044
1045 rc = cil_resolve_name(current, roletype->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
1046 if (rc != SEPOL_OK) {
1047 goto exit;
1048 }
1049 roletype->type = (struct cil_type*)type_datum;
1050
1051 return SEPOL_OK;
1052
1053 exit:
1054 return rc;
1055 }
1056
cil_resolve_roletransition(struct cil_tree_node * current,void * extra_args)1057 int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args)
1058 {
1059 struct cil_roletransition *roletrans = current->data;
1060 struct cil_symtab_datum *src_datum = NULL;
1061 struct cil_symtab_datum *tgt_datum = NULL;
1062 struct cil_symtab_datum *obj_datum = NULL;
1063 struct cil_symtab_datum *result_datum = NULL;
1064 struct cil_tree_node *node = NULL;
1065 int rc = SEPOL_ERR;
1066
1067 rc = cil_resolve_name(current, roletrans->src_str, CIL_SYM_ROLES, extra_args, &src_datum);
1068 if (rc != SEPOL_OK) {
1069 goto exit;
1070 }
1071 roletrans->src = (struct cil_role*)src_datum;
1072
1073 rc = cil_resolve_name(current, roletrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum);
1074 if (rc != SEPOL_OK) {
1075 goto exit;
1076 }
1077 roletrans->tgt = tgt_datum;
1078
1079 rc = cil_resolve_name(current, roletrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
1080 if (rc != SEPOL_OK) {
1081 goto exit;
1082 }
1083 roletrans->obj = (struct cil_class*)obj_datum;
1084
1085 rc = cil_resolve_name(current, roletrans->result_str, CIL_SYM_ROLES, extra_args, &result_datum);
1086 if (rc != SEPOL_OK) {
1087 goto exit;
1088 }
1089 node = result_datum->nodes->head->data;
1090 if (node->flavor != CIL_ROLE) {
1091 rc = SEPOL_ERR;
1092 printf("%i\n", node->flavor);
1093 cil_log(CIL_ERR, "roletransition must result in a role, but %s is a %s\n", roletrans->result_str, cil_node_to_string(node));
1094 goto exit;
1095 }
1096 roletrans->result = (struct cil_role*)result_datum;
1097
1098 return SEPOL_OK;
1099
1100 exit:
1101 return rc;
1102 }
1103
cil_resolve_roleallow(struct cil_tree_node * current,void * extra_args)1104 int cil_resolve_roleallow(struct cil_tree_node *current, void *extra_args)
1105 {
1106 struct cil_roleallow *roleallow = current->data;
1107 struct cil_symtab_datum *src_datum = NULL;
1108 struct cil_symtab_datum *tgt_datum = NULL;
1109 int rc = SEPOL_ERR;
1110
1111 rc = cil_resolve_name(current, roleallow->src_str, CIL_SYM_ROLES, extra_args, &src_datum);
1112 if (rc != SEPOL_OK) {
1113 goto exit;
1114 }
1115 roleallow->src = (struct cil_role*)src_datum;
1116
1117 rc = cil_resolve_name(current, roleallow->tgt_str, CIL_SYM_ROLES, extra_args, &tgt_datum);
1118 if (rc != SEPOL_OK) {
1119 goto exit;
1120 }
1121 roleallow->tgt = (struct cil_role*)tgt_datum;
1122
1123 return SEPOL_OK;
1124
1125 exit:
1126 return rc;
1127 }
1128
cil_resolve_roleattributeset(struct cil_tree_node * current,void * extra_args)1129 int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args)
1130 {
1131 int rc = SEPOL_ERR;
1132 struct cil_roleattributeset *attrroles = current->data;
1133 struct cil_symtab_datum *attr_datum = NULL;
1134 struct cil_tree_node *attr_node = NULL;
1135 struct cil_roleattribute *attr = NULL;
1136
1137 rc = cil_resolve_name(current, attrroles->attr_str, CIL_SYM_ROLES, extra_args, &attr_datum);
1138 if (rc != SEPOL_OK) {
1139 goto exit;
1140 }
1141 attr_node = attr_datum->nodes->head->data;
1142
1143 if (attr_node->flavor != CIL_ROLEATTRIBUTE) {
1144 rc = SEPOL_ERR;
1145 cil_log(CIL_ERR, "Attribute role not an attribute\n");
1146 goto exit;
1147 }
1148 attr = (struct cil_roleattribute*)attr_datum;
1149
1150 rc = cil_resolve_expr(CIL_ROLEATTRIBUTESET, attrroles->str_expr, &attrroles->datum_expr, current, extra_args);
1151 if (rc != SEPOL_OK) {
1152 goto exit;
1153 }
1154
1155 rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr);
1156 if (rc != SEPOL_OK) {
1157 goto exit;
1158 }
1159
1160 if (attr->expr_list == NULL) {
1161 cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE);
1162 }
1163
1164 cil_list_append(attr->expr_list, CIL_LIST, attrroles->datum_expr);
1165
1166 return SEPOL_OK;
1167
1168 exit:
1169 return rc;
1170 }
1171
1172 struct cil_ordered_list {
1173 int merged;
1174 struct cil_list *list;
1175 struct cil_tree_node *node;
1176 };
1177
__cil_ordered_list_init(struct cil_ordered_list ** ordered)1178 void __cil_ordered_list_init(struct cil_ordered_list **ordered)
1179 {
1180 *ordered = cil_malloc(sizeof(**ordered));
1181
1182 (*ordered)->merged = CIL_FALSE;
1183 (*ordered)->list = NULL;
1184 (*ordered)->node = NULL;
1185 }
1186
__cil_ordered_list_destroy(struct cil_ordered_list ** ordered)1187 void __cil_ordered_list_destroy(struct cil_ordered_list **ordered)
1188 {
1189 cil_list_destroy(&(*ordered)->list, CIL_FALSE);
1190 (*ordered)->node = NULL;
1191 free(*ordered);
1192 *ordered = NULL;
1193 }
1194
__cil_ordered_lists_destroy(struct cil_list ** ordered_lists)1195 void __cil_ordered_lists_destroy(struct cil_list **ordered_lists)
1196 {
1197 struct cil_list_item *item = NULL;
1198
1199 if (ordered_lists == NULL || *ordered_lists == NULL) {
1200 return;
1201 }
1202
1203 item = (*ordered_lists)->head;
1204 while (item != NULL) {
1205 struct cil_list_item *next = item->next;
1206 struct cil_ordered_list *ordered = item->data;
1207 __cil_ordered_list_destroy(&ordered);
1208 free(item);
1209 item = next;
1210 }
1211 free(*ordered_lists);
1212 *ordered_lists = NULL;
1213 }
1214
__cil_ordered_lists_reset(struct cil_list ** ordered_lists)1215 void __cil_ordered_lists_reset(struct cil_list **ordered_lists)
1216 {
1217 __cil_ordered_lists_destroy(ordered_lists);
1218 cil_list_init(ordered_lists, CIL_LIST_ITEM);
1219 }
1220
__cil_ordered_item_insert(struct cil_list * old,struct cil_list_item * curr,struct cil_list_item * item)1221 struct cil_list_item *__cil_ordered_item_insert(struct cil_list *old, struct cil_list_item *curr, struct cil_list_item *item)
1222 {
1223 if (item->flavor == CIL_SID) {
1224 struct cil_sid *sid = item->data;
1225 if (sid->ordered == CIL_TRUE) {
1226 cil_log(CIL_ERR, "SID %s has already been merged into the ordered list\n", sid->datum.name);
1227 return NULL;
1228 }
1229 sid->ordered = CIL_TRUE;
1230 } else if (item->flavor == CIL_CLASS) {
1231 struct cil_class *class = item->data;
1232 if (class->ordered == CIL_TRUE) {
1233 cil_log(CIL_ERR, "Class %s has already been merged into the ordered list\n", class->datum.name);
1234 return NULL;
1235 }
1236 class->ordered = CIL_TRUE;
1237 } else if (item->flavor == CIL_CAT) {
1238 struct cil_cat *cat = item->data;
1239 if (cat->ordered == CIL_TRUE) {
1240 cil_log(CIL_ERR, "Category %s has already been merged into the ordered list\n", cat->datum.name);
1241 return NULL;
1242 }
1243 cat->ordered = CIL_TRUE;
1244 } else if (item->flavor == CIL_SENS) {
1245 struct cil_sens *sens = item->data;
1246 if (sens->ordered == CIL_TRUE) {
1247 cil_log(CIL_ERR, "Sensitivity %s has already been merged into the ordered list\n", sens->datum.name);
1248 return NULL;
1249 }
1250 sens->ordered = CIL_TRUE;
1251 }
1252
1253 return cil_list_insert(old, curr, item->flavor, item->data);
1254 }
1255
__cil_ordered_list_insert(struct cil_list * old,struct cil_list_item * ocurr,struct cil_list_item * nstart,struct cil_list_item * nstop)1256 int __cil_ordered_list_insert(struct cil_list *old, struct cil_list_item *ocurr, struct cil_list_item *nstart, struct cil_list_item *nstop)
1257 {
1258 struct cil_list_item *ncurr = NULL;
1259
1260 for (ncurr = nstart; ncurr != nstop; ncurr = ncurr->next) {
1261 ocurr = __cil_ordered_item_insert(old, ocurr, ncurr);
1262 if (ocurr == NULL) {
1263 return SEPOL_ERR;
1264 }
1265 }
1266 return SEPOL_OK;
1267 }
1268
__cil_ordered_find_match(struct cil_list_item * t,struct cil_list_item * i)1269 struct cil_list_item *__cil_ordered_find_match(struct cil_list_item *t, struct cil_list_item *i)
1270 {
1271 while (i) {
1272 if (i->data == t->data) {
1273 return i;
1274 }
1275 i = i->next;
1276 }
1277 return NULL;
1278 }
1279
__cil_ordered_lists_merge(struct cil_list * old,struct cil_list * new)1280 int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
1281 {
1282 struct cil_list_item *omatch = NULL;
1283 struct cil_list_item *ofirst = old->head;
1284 struct cil_list_item *ocurr = NULL;
1285 struct cil_list_item *oprev = NULL;
1286 struct cil_list_item *nmatch = NULL;
1287 struct cil_list_item *nfirst = new->head;
1288 struct cil_list_item *ncurr = NULL;
1289 int rc = SEPOL_ERR;
1290
1291 if (nfirst == NULL) {
1292 return SEPOL_OK;
1293 }
1294
1295 if (ofirst == NULL) {
1296 /* First list added */
1297 rc = __cil_ordered_list_insert(old, NULL, nfirst, NULL);
1298 return rc;
1299 }
1300
1301 /* Find a match between the new list and the old one */
1302 for (nmatch = nfirst; nmatch; nmatch = nmatch->next) {
1303 omatch = __cil_ordered_find_match(nmatch, ofirst);
1304 if (omatch) {
1305 break;
1306 }
1307 }
1308
1309 if (!nmatch) {
1310 /* List cannot be merged yet */
1311 return SEPOL_ERR;
1312 }
1313
1314 if (nmatch != nfirst && omatch != ofirst) {
1315 /* Potential ordering conflict--try again later */
1316 return SEPOL_ERR;
1317 }
1318
1319 if (nmatch != nfirst) {
1320 /* Prepend the beginning of the new list up to the first match to the old list */
1321 rc = __cil_ordered_list_insert(old, NULL, nfirst, nmatch);
1322 if (rc != SEPOL_OK) {
1323 return rc;
1324 }
1325 }
1326
1327 /* In the overlapping protion, add items from the new list not in the old list */
1328 ncurr = nmatch->next;
1329 ocurr = omatch->next;
1330 oprev = omatch;
1331 while (ncurr && ocurr) {
1332 if (ncurr->data == ocurr->data) {
1333 oprev = ocurr;
1334 ocurr = ocurr->next;
1335 ncurr = ncurr->next;
1336 } else {
1337 /* Handle gap in old: old = (A C) new = (A B C) */
1338 nmatch = __cil_ordered_find_match(ocurr, ncurr->next);
1339 if (nmatch) {
1340 rc = __cil_ordered_list_insert(old, oprev, ncurr, nmatch);
1341 if (rc != SEPOL_OK) {
1342 return rc;
1343 }
1344 oprev = ocurr;
1345 ocurr = ocurr->next;
1346 ncurr = nmatch->next;
1347 continue;
1348 }
1349 /* Handle gap in new: old = (A B C) new = (A C) */
1350 omatch = __cil_ordered_find_match(ncurr, ocurr->next);
1351 if (omatch) {
1352 /* Nothing to insert, just skip */
1353 oprev = omatch;
1354 ocurr = omatch->next;
1355 ncurr = ncurr->next;
1356 continue;
1357 } else {
1358 return SEPOL_ERR;
1359 }
1360 }
1361 }
1362
1363 if (ncurr) {
1364 /* Add the rest of the items from the new list */
1365 rc = __cil_ordered_list_insert(old, old->tail, ncurr, NULL);
1366 if (rc != SEPOL_OK) {
1367 return rc;
1368 }
1369 }
1370
1371 return SEPOL_OK;
1372 }
1373
insert_unordered(struct cil_list * merged,struct cil_list * unordered)1374 static int insert_unordered(struct cil_list *merged, struct cil_list *unordered)
1375 {
1376 struct cil_list_item *curr = NULL;
1377 struct cil_ordered_list *unordered_list = NULL;
1378 struct cil_list_item *item = NULL;
1379 struct cil_list_item *ret = NULL;
1380 int rc = SEPOL_ERR;
1381
1382 cil_list_for_each(curr, unordered) {
1383 unordered_list = curr->data;
1384
1385 cil_list_for_each(item, unordered_list->list) {
1386 if (cil_list_contains(merged, item->data)) {
1387 /* item was declared in an ordered statement, which supercedes
1388 * all unordered statements */
1389 if (item->flavor == CIL_CLASS) {
1390 cil_log(CIL_WARN, "Ignoring '%s' as it has already been declared in classorder.\n", ((struct cil_class*)(item->data))->datum.name);
1391 }
1392 continue;
1393 }
1394
1395 ret = __cil_ordered_item_insert(merged, merged->tail, item);
1396 if (ret == NULL) {
1397 rc = SEPOL_ERR;
1398 goto exit;
1399 }
1400 }
1401 }
1402
1403 rc = SEPOL_OK;
1404
1405 exit:
1406 return rc;
1407 }
1408
__cil_ordered_lists_merge_all(struct cil_list ** ordered_lists,struct cil_list ** unordered_lists)1409 struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists)
1410 {
1411 struct cil_list *composite = NULL;
1412 struct cil_list_item *curr = NULL;
1413 int changed = CIL_TRUE;
1414 int waiting = 1;
1415 int rc = SEPOL_ERR;
1416
1417 cil_list_init(&composite, CIL_LIST_ITEM);
1418
1419 while (waiting && changed == CIL_TRUE) {
1420 changed = CIL_FALSE;
1421 waiting = 0;
1422 cil_list_for_each(curr, *ordered_lists) {
1423 struct cil_ordered_list *ordered_list = curr->data;
1424 if (ordered_list->merged == CIL_FALSE) {
1425 rc = __cil_ordered_lists_merge(composite, ordered_list->list);
1426 if (rc != SEPOL_OK) {
1427 /* Can't merge yet */
1428 waiting++;
1429 } else {
1430 ordered_list->merged = CIL_TRUE;
1431 changed = CIL_TRUE;
1432 }
1433 }
1434 }
1435 if (waiting > 0 && changed == CIL_FALSE) {
1436 cil_list_for_each(curr, *ordered_lists) {
1437 struct cil_ordered_list *ordered_list = curr->data;
1438 if (ordered_list->merged == CIL_FALSE) {
1439 cil_tree_log(ordered_list->node, CIL_ERR, "Unable to merge ordered list");
1440 }
1441 }
1442 goto exit;
1443 }
1444 }
1445
1446 if (unordered_lists != NULL) {
1447 rc = insert_unordered(composite, *unordered_lists);
1448 if (rc != SEPOL_OK) {
1449 goto exit;
1450 }
1451 }
1452
1453 __cil_ordered_lists_destroy(ordered_lists);
1454 __cil_ordered_lists_destroy(unordered_lists);
1455
1456 return composite;
1457
1458 exit:
1459 __cil_ordered_lists_destroy(ordered_lists);
1460 __cil_ordered_lists_destroy(unordered_lists);
1461 cil_list_destroy(&composite, CIL_FALSE);
1462 return NULL;
1463 }
1464
cil_resolve_classorder(struct cil_tree_node * current,void * extra_args)1465 int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
1466 {
1467 struct cil_args_resolve *args = extra_args;
1468 struct cil_list *classorder_list = args->classorder_lists;
1469 struct cil_list *unordered_classorder_list = args->unordered_classorder_lists;
1470 struct cil_classorder *classorder = current->data;
1471 struct cil_list *new = NULL;
1472 struct cil_list_item *curr = NULL;
1473 struct cil_symtab_datum *datum = NULL;
1474 struct cil_ordered_list *class_list = NULL;
1475 int rc = SEPOL_ERR;
1476 int unordered = CIL_FALSE;
1477
1478 cil_list_init(&new, CIL_CLASSORDER);
1479
1480 cil_list_for_each(curr, classorder->class_list_str) {
1481 if (curr->data == CIL_KEY_UNORDERED) {
1482 unordered = CIL_TRUE;
1483 continue;
1484 }
1485
1486 rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
1487 if (rc != SEPOL_OK) {
1488 cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
1489 goto exit;
1490 }
1491 cil_list_append(new, CIL_CLASS, datum);
1492 }
1493
1494 __cil_ordered_list_init(&class_list);
1495 class_list->list = new;
1496 class_list->node = current;
1497 if (unordered) {
1498 cil_list_append(unordered_classorder_list, CIL_CLASSORDER, class_list);
1499 } else {
1500 cil_list_append(classorder_list, CIL_CLASSORDER, class_list);
1501 }
1502
1503 return SEPOL_OK;
1504
1505 exit:
1506 cil_list_destroy(&new, CIL_FALSE);
1507 return rc;
1508 }
1509
cil_resolve_sidorder(struct cil_tree_node * current,void * extra_args)1510 int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args)
1511 {
1512 struct cil_args_resolve *args = extra_args;
1513 struct cil_list *sidorder_list = args->sidorder_lists;
1514 struct cil_sidorder *sidorder = current->data;
1515 struct cil_list *new = NULL;
1516 struct cil_list_item *curr = NULL;
1517 struct cil_symtab_datum *datum = NULL;
1518 struct cil_ordered_list *ordered = NULL;
1519 int rc = SEPOL_ERR;
1520
1521 cil_list_init(&new, CIL_SIDORDER);
1522
1523 cil_list_for_each(curr, sidorder->sid_list_str) {
1524 rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SIDS, extra_args, &datum);
1525 if (rc != SEPOL_OK) {
1526 cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data);
1527 goto exit;
1528 }
1529 cil_list_append(new, CIL_SID, datum);
1530 }
1531
1532 __cil_ordered_list_init(&ordered);
1533 ordered->list = new;
1534 ordered->node = current;
1535 cil_list_append(sidorder_list, CIL_SIDORDER, ordered);
1536
1537 return SEPOL_OK;
1538
1539 exit:
1540 return rc;
1541 }
1542
cil_set_cat_values(struct cil_list * ordered_cats,struct cil_db * db)1543 void cil_set_cat_values(struct cil_list *ordered_cats, struct cil_db *db)
1544 {
1545 struct cil_list_item *curr;
1546 int v = 0;
1547
1548 cil_list_for_each(curr, ordered_cats) {
1549 struct cil_cat *cat = curr->data;
1550 cat->value = v;
1551 v++;
1552 }
1553
1554 db->num_cats = v;
1555 }
1556
cil_resolve_catorder(struct cil_tree_node * current,void * extra_args)1557 int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args)
1558 {
1559 struct cil_args_resolve *args = extra_args;
1560 struct cil_list *catorder_list = args->catorder_lists;
1561 struct cil_catorder *catorder = current->data;
1562 struct cil_list *new = NULL;
1563 struct cil_list_item *curr = NULL;
1564 struct cil_symtab_datum *cat_datum;
1565 struct cil_cat *cat = NULL;
1566 struct cil_ordered_list *ordered = NULL;
1567 int rc = SEPOL_ERR;
1568
1569 cil_list_init(&new, CIL_CATORDER);
1570
1571 cil_list_for_each(curr, catorder->cat_list_str) {
1572 struct cil_tree_node *node = NULL;
1573 rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CATS, extra_args, &cat_datum);
1574 if (rc != SEPOL_OK) {
1575 cil_log(CIL_ERR, "Failed to resolve category %s in categoryorder\n", (char *)curr->data);
1576 goto exit;
1577 }
1578 node = cat_datum->nodes->head->data;
1579 if (node->flavor != CIL_CAT) {
1580 cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", cat_datum->name);
1581 rc = SEPOL_ERR;
1582 goto exit;
1583 }
1584 cat = (struct cil_cat *)cat_datum;
1585 cil_list_append(new, CIL_CAT, cat);
1586 }
1587
1588 __cil_ordered_list_init(&ordered);
1589 ordered->list = new;
1590 ordered->node = current;
1591 cil_list_append(catorder_list, CIL_CATORDER, ordered);
1592
1593 return SEPOL_OK;
1594
1595 exit:
1596 return rc;
1597 }
1598
cil_resolve_sensitivityorder(struct cil_tree_node * current,void * extra_args)1599 int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args)
1600 {
1601 struct cil_args_resolve *args = extra_args;
1602 struct cil_list *sensitivityorder_list = args->sensitivityorder_lists;
1603 struct cil_sensorder *sensorder = current->data;
1604 struct cil_list *new = NULL;
1605 struct cil_list_item *curr = NULL;
1606 struct cil_symtab_datum *datum = NULL;
1607 struct cil_ordered_list *ordered = NULL;
1608 int rc = SEPOL_ERR;
1609
1610 cil_list_init(&new, CIL_LIST_ITEM);
1611
1612 cil_list_for_each(curr, sensorder->sens_list_str) {
1613 rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum);
1614 if (rc != SEPOL_OK) {
1615 cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data);
1616 goto exit;
1617 }
1618 cil_list_append(new, CIL_SENS, datum);
1619 }
1620
1621 __cil_ordered_list_init(&ordered);
1622 ordered->list = new;
1623 ordered->node = current;
1624 cil_list_append(sensitivityorder_list, CIL_SENSITIVITYORDER, ordered);
1625
1626 return SEPOL_OK;
1627
1628 exit:
1629 return rc;
1630 }
1631
cil_resolve_cats(struct cil_tree_node * current,struct cil_cats * cats,void * extra_args)1632 int cil_resolve_cats(struct cil_tree_node *current, struct cil_cats *cats, void *extra_args)
1633 {
1634 int rc = SEPOL_ERR;
1635
1636 rc = cil_resolve_expr(CIL_CATSET, cats->str_expr, &cats->datum_expr, current, extra_args);
1637 if (rc != SEPOL_OK) {
1638 goto exit;
1639 }
1640
1641 return SEPOL_OK;
1642
1643 exit:
1644 return rc;
1645 }
1646
1647
cil_resolve_catset(struct cil_tree_node * current,struct cil_catset * catset,void * extra_args)1648 int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args)
1649 {
1650 int rc = SEPOL_ERR;
1651
1652 rc = cil_resolve_cats(current, catset->cats, extra_args);
1653 if (rc != SEPOL_OK) {
1654 goto exit;
1655 }
1656
1657 rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr);
1658 if (rc != SEPOL_OK) {
1659 cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE);
1660 goto exit;
1661 }
1662
1663 exit:
1664 return rc;
1665 }
1666
cil_resolve_senscat(struct cil_tree_node * current,void * extra_args)1667 int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args)
1668 {
1669 int rc = SEPOL_ERR;
1670 struct cil_senscat *senscat = current->data;
1671 struct cil_symtab_datum *sens_datum;
1672 struct cil_sens *sens = NULL;
1673
1674 rc = cil_resolve_name(current, (char*)senscat->sens_str, CIL_SYM_SENS, extra_args, &sens_datum);
1675 if (rc != SEPOL_OK) {
1676 cil_log(CIL_ERR, "Failed to find sensitivity\n");
1677 goto exit;
1678 }
1679
1680 rc = cil_resolve_cats(current, senscat->cats, extra_args);
1681 if (rc != SEPOL_OK) {
1682 goto exit;
1683 }
1684
1685 sens = (struct cil_sens *)sens_datum;
1686
1687 if (sens->cats_list == NULL ) {
1688 cil_list_init(&sens->cats_list, CIL_CAT);
1689 }
1690
1691 cil_list_append(sens->cats_list, CIL_CAT, senscat->cats);
1692
1693 return SEPOL_OK;
1694
1695 exit:
1696 return rc;
1697 }
1698
cil_resolve_level(struct cil_tree_node * current,struct cil_level * level,void * extra_args)1699 int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, void *extra_args)
1700 {
1701 struct cil_symtab_datum *sens_datum = NULL;
1702 int rc = SEPOL_ERR;
1703
1704 rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum);
1705 if (rc != SEPOL_OK) {
1706 cil_log(CIL_ERR, "Failed to find sensitivity\n");
1707 goto exit;
1708 }
1709
1710 level->sens = (struct cil_sens *)sens_datum;
1711
1712 if (level->cats != NULL) {
1713 rc = cil_resolve_cats(current, level->cats, extra_args);
1714 if (rc != SEPOL_OK) {
1715 goto exit;
1716 }
1717 }
1718
1719 return SEPOL_OK;
1720
1721 exit:
1722 return rc;
1723 }
1724
cil_resolve_levelrange(struct cil_tree_node * current,struct cil_levelrange * lvlrange,void * extra_args)1725 int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *lvlrange, void *extra_args)
1726 {
1727 struct cil_symtab_datum *low_datum = NULL;
1728 struct cil_symtab_datum *high_datum = NULL;
1729 int rc = SEPOL_ERR;
1730
1731 if (lvlrange->low_str != NULL) {
1732 rc = cil_resolve_name(current, lvlrange->low_str, CIL_SYM_LEVELS, extra_args, &low_datum);
1733 if (rc != SEPOL_OK) {
1734 goto exit;
1735 }
1736 lvlrange->low = (struct cil_level*)low_datum;
1737
1738 /* This could still be an anonymous level even if low_str is set, if low_str is a param_str */
1739 if (lvlrange->low->datum.name == NULL) {
1740 rc = cil_resolve_level(current, lvlrange->low, extra_args);
1741 if (rc != SEPOL_OK) {
1742 goto exit;
1743 }
1744 }
1745 } else if (lvlrange->low != NULL) {
1746 rc = cil_resolve_level(current, lvlrange->low, extra_args);
1747 if (rc != SEPOL_OK) {
1748 goto exit;
1749 }
1750 }
1751
1752 if (lvlrange->high_str != NULL) {
1753 rc = cil_resolve_name(current, lvlrange->high_str, CIL_SYM_LEVELS, extra_args, &high_datum);
1754 if (rc != SEPOL_OK) {
1755 goto exit;
1756 }
1757 lvlrange->high = (struct cil_level*)high_datum;
1758
1759 /* This could still be an anonymous level even if high_str is set, if high_str is a param_str */
1760 if (lvlrange->high->datum.name == NULL) {
1761 rc = cil_resolve_level(current, lvlrange->high, extra_args);
1762 if (rc != SEPOL_OK) {
1763 goto exit;
1764 }
1765 }
1766 } else if (lvlrange->high != NULL) {
1767 rc = cil_resolve_level(current, lvlrange->high, extra_args);
1768 if (rc != SEPOL_OK) {
1769 goto exit;
1770 }
1771 }
1772
1773 return SEPOL_OK;
1774
1775 exit:
1776 return rc;
1777 }
1778
cil_resolve_constrain(struct cil_tree_node * current,void * extra_args)1779 int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args)
1780 {
1781 struct cil_constrain *cons = current->data;
1782 int rc = SEPOL_ERR;
1783
1784 rc = cil_resolve_classperms_list(current, cons->classperms, extra_args);
1785 if (rc != SEPOL_OK) {
1786 goto exit;
1787 }
1788
1789 rc = cil_resolve_expr(CIL_CONSTRAIN, cons->str_expr, &cons->datum_expr, current, extra_args);
1790 if (rc != SEPOL_OK) {
1791 goto exit;
1792 }
1793
1794 return SEPOL_OK;
1795
1796 exit:
1797 return rc;
1798 }
1799
cil_resolve_validatetrans(struct cil_tree_node * current,void * extra_args)1800 int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args)
1801 {
1802 struct cil_validatetrans *validtrans = current->data;
1803 struct cil_args_resolve *args = extra_args;
1804 struct cil_symtab_datum *class_datum = NULL;
1805 int rc = SEPOL_ERR;
1806
1807 rc = cil_resolve_name(current, validtrans->class_str, CIL_SYM_CLASSES, args, &class_datum);
1808 if (rc != SEPOL_OK) {
1809 goto exit;
1810 }
1811 validtrans->class = (struct cil_class*)class_datum;
1812
1813 rc = cil_resolve_expr(CIL_VALIDATETRANS, validtrans->str_expr, &validtrans->datum_expr, current, extra_args);
1814 if (rc != SEPOL_OK) {
1815 goto exit;
1816 }
1817
1818 return SEPOL_OK;
1819
1820 exit:
1821 return rc;
1822 }
1823
cil_resolve_context(struct cil_tree_node * current,struct cil_context * context,void * extra_args)1824 int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args)
1825 {
1826 struct cil_symtab_datum *user_datum = NULL;
1827 struct cil_symtab_datum *role_datum = NULL;
1828 struct cil_symtab_datum *type_datum = NULL;
1829 struct cil_tree_node *node = NULL;
1830 struct cil_symtab_datum *lvlrange_datum = NULL;
1831
1832 int rc = SEPOL_ERR;
1833
1834 rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, extra_args, &user_datum);
1835 if (rc != SEPOL_OK) {
1836 goto exit;
1837 }
1838
1839 node = user_datum->nodes->head->data;
1840
1841 if (node->flavor != CIL_USER) {
1842 cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn);
1843 rc = SEPOL_ERR;
1844 goto exit;
1845 }
1846
1847 context->user = (struct cil_user*)user_datum;
1848
1849 rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
1850 if (rc != SEPOL_OK) {
1851 goto exit;
1852 }
1853
1854 node = role_datum->nodes->head->data;
1855 if (node->flavor != CIL_ROLE) {
1856 rc = SEPOL_ERR;
1857 cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn);
1858 goto exit;
1859 }
1860
1861 context->role = (struct cil_role*)role_datum;
1862
1863 rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
1864 if (rc != SEPOL_OK) {
1865 goto exit;
1866 }
1867
1868 node = type_datum->nodes->head->data;
1869
1870 if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) {
1871 rc = SEPOL_ERR;
1872 cil_log(CIL_ERR, "Type not a type or type alias\n");
1873 goto exit;
1874 }
1875 context->type = type_datum;
1876
1877 if (context->range_str != NULL) {
1878 rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
1879 if (rc != SEPOL_OK) {
1880 goto exit;
1881 }
1882 context->range = (struct cil_levelrange*)lvlrange_datum;
1883
1884 /* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/
1885 if (context->range->datum.name == NULL) {
1886 rc = cil_resolve_levelrange(current, context->range, extra_args);
1887 if (rc != SEPOL_OK) {
1888 goto exit;
1889 }
1890 }
1891 } else if (context->range != NULL) {
1892 rc = cil_resolve_levelrange(current, context->range, extra_args);
1893 if (rc != SEPOL_OK) {
1894 goto exit;
1895 }
1896 }
1897
1898 return SEPOL_OK;
1899
1900 exit:
1901 return rc;
1902 }
1903
cil_resolve_filecon(struct cil_tree_node * current,void * extra_args)1904 int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args)
1905 {
1906 struct cil_filecon *filecon = current->data;
1907 struct cil_symtab_datum *context_datum = NULL;
1908 int rc = SEPOL_ERR;
1909
1910 if (filecon->context_str != NULL) {
1911 rc = cil_resolve_name(current, filecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
1912 if (rc != SEPOL_OK) {
1913 return rc;
1914 }
1915 filecon->context = (struct cil_context*)context_datum;
1916 } else if (filecon->context != NULL) {
1917 rc = cil_resolve_context(current, filecon->context, extra_args);
1918 if (rc != SEPOL_OK) {
1919 return rc;
1920 }
1921 }
1922
1923 return SEPOL_OK;
1924 }
1925
cil_resolve_portcon(struct cil_tree_node * current,void * extra_args)1926 int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args)
1927 {
1928 struct cil_portcon *portcon = current->data;
1929 struct cil_symtab_datum *context_datum = NULL;
1930 int rc = SEPOL_ERR;
1931
1932 if (portcon->context_str != NULL) {
1933 rc = cil_resolve_name(current, portcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
1934 if (rc != SEPOL_OK) {
1935 goto exit;
1936 }
1937 portcon->context = (struct cil_context*)context_datum;
1938 } else {
1939 rc = cil_resolve_context(current, portcon->context, extra_args);
1940 if (rc != SEPOL_OK) {
1941 goto exit;
1942 }
1943 }
1944
1945 return SEPOL_OK;
1946
1947 exit:
1948 return rc;
1949 }
1950
cil_resolve_genfscon(struct cil_tree_node * current,void * extra_args)1951 int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args)
1952 {
1953 struct cil_genfscon *genfscon = current->data;
1954 struct cil_symtab_datum *context_datum = NULL;
1955 int rc = SEPOL_ERR;
1956
1957 if (genfscon->context_str != NULL) {
1958 rc = cil_resolve_name(current, genfscon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
1959 if (rc != SEPOL_OK) {
1960 goto exit;
1961 }
1962 genfscon->context = (struct cil_context*)context_datum;
1963 } else {
1964 rc = cil_resolve_context(current, genfscon->context, extra_args);
1965 if (rc != SEPOL_OK) {
1966 goto exit;
1967 }
1968 }
1969
1970 return SEPOL_OK;
1971
1972 exit:
1973 return rc;
1974 }
1975
cil_resolve_nodecon(struct cil_tree_node * current,void * extra_args)1976 int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args)
1977 {
1978 struct cil_nodecon *nodecon = current->data;
1979 struct cil_symtab_datum *addr_datum = NULL;
1980 struct cil_symtab_datum *mask_datum = NULL;
1981 struct cil_symtab_datum *context_datum = NULL;
1982 int rc = SEPOL_ERR;
1983
1984 if (nodecon->addr_str != NULL) {
1985 rc = cil_resolve_name(current, nodecon->addr_str, CIL_SYM_IPADDRS, extra_args, &addr_datum);
1986 if (rc != SEPOL_OK) {
1987 goto exit;
1988 }
1989 nodecon->addr = (struct cil_ipaddr*)addr_datum;
1990 }
1991
1992 if (nodecon->mask_str != NULL) {
1993 rc = cil_resolve_name(current, nodecon->mask_str, CIL_SYM_IPADDRS, extra_args, &mask_datum);
1994 if (rc != SEPOL_OK) {
1995 goto exit;
1996 }
1997 nodecon->mask = (struct cil_ipaddr*)mask_datum;
1998 }
1999
2000 if (nodecon->context_str != NULL) {
2001 rc = cil_resolve_name(current, nodecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2002 if (rc != SEPOL_OK) {
2003 goto exit;
2004 }
2005 nodecon->context = (struct cil_context*)context_datum;
2006 } else {
2007 rc = cil_resolve_context(current, nodecon->context, extra_args);
2008 if (rc != SEPOL_OK) {
2009 goto exit;
2010 }
2011 }
2012
2013 if (nodecon->addr->family != nodecon->mask->family) {
2014 cil_log(CIL_ERR, "Nodecon ip address not in the same family\n");
2015 rc = SEPOL_ERR;
2016 goto exit;
2017 }
2018
2019
2020 return SEPOL_OK;
2021
2022 exit:
2023 return rc;
2024 }
2025
cil_resolve_netifcon(struct cil_tree_node * current,void * extra_args)2026 int cil_resolve_netifcon(struct cil_tree_node *current, void *extra_args)
2027 {
2028 struct cil_netifcon *netifcon = current->data;
2029 struct cil_symtab_datum *ifcon_datum = NULL;
2030 struct cil_symtab_datum *packcon_datum = NULL;
2031
2032 int rc = SEPOL_ERR;
2033
2034 if (netifcon->if_context_str != NULL) {
2035 rc = cil_resolve_name(current, netifcon->if_context_str, CIL_SYM_CONTEXTS, extra_args, &ifcon_datum);
2036 if (rc != SEPOL_OK) {
2037 goto exit;
2038 }
2039 netifcon->if_context = (struct cil_context*)ifcon_datum;
2040 } else {
2041 rc = cil_resolve_context(current, netifcon->if_context, extra_args);
2042 if (rc != SEPOL_OK) {
2043 goto exit;
2044 }
2045 }
2046
2047 if (netifcon->packet_context_str != NULL) {
2048 rc = cil_resolve_name(current, netifcon->packet_context_str, CIL_SYM_CONTEXTS, extra_args, &packcon_datum);
2049 if (rc != SEPOL_OK) {
2050 goto exit;
2051 }
2052 netifcon->packet_context = (struct cil_context*)packcon_datum;
2053 } else {
2054 rc = cil_resolve_context(current, netifcon->packet_context, extra_args);
2055 if (rc != SEPOL_OK) {
2056 goto exit;
2057 }
2058 }
2059 return SEPOL_OK;
2060
2061 exit:
2062 return rc;
2063 }
2064
cil_resolve_pirqcon(struct cil_tree_node * current,void * extra_args)2065 int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args)
2066 {
2067 struct cil_pirqcon *pirqcon = current->data;
2068 struct cil_symtab_datum *context_datum = NULL;
2069 int rc = SEPOL_ERR;
2070
2071 if (pirqcon->context_str != NULL) {
2072 rc = cil_resolve_name(current, pirqcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2073 if (rc != SEPOL_OK) {
2074 goto exit;
2075 }
2076 pirqcon->context = (struct cil_context*)context_datum;
2077 } else {
2078 rc = cil_resolve_context(current, pirqcon->context, extra_args);
2079 if (rc != SEPOL_OK) {
2080 goto exit;
2081 }
2082 }
2083
2084 return SEPOL_OK;
2085
2086 exit:
2087 return rc;
2088 }
2089
cil_resolve_iomemcon(struct cil_tree_node * current,void * extra_args)2090 int cil_resolve_iomemcon(struct cil_tree_node *current, void *extra_args)
2091 {
2092 struct cil_iomemcon *iomemcon = current->data;
2093 struct cil_symtab_datum *context_datum = NULL;
2094 int rc = SEPOL_ERR;
2095
2096 if (iomemcon->context_str != NULL) {
2097 rc = cil_resolve_name(current, iomemcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2098 if (rc != SEPOL_OK) {
2099 goto exit;
2100 }
2101 iomemcon->context = (struct cil_context*)context_datum;
2102 } else {
2103 rc = cil_resolve_context(current, iomemcon->context, extra_args);
2104 if (rc != SEPOL_OK) {
2105 goto exit;
2106 }
2107 }
2108
2109 return SEPOL_OK;
2110
2111 exit:
2112 return rc;
2113 }
2114
cil_resolve_ioportcon(struct cil_tree_node * current,void * extra_args)2115 int cil_resolve_ioportcon(struct cil_tree_node *current, void *extra_args)
2116 {
2117 struct cil_ioportcon *ioportcon = current->data;
2118 struct cil_symtab_datum *context_datum = NULL;
2119 int rc = SEPOL_ERR;
2120
2121 if (ioportcon->context_str != NULL) {
2122 rc = cil_resolve_name(current, ioportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2123 if (rc != SEPOL_OK) {
2124 goto exit;
2125 }
2126 ioportcon->context = (struct cil_context*)context_datum;
2127 } else {
2128 rc = cil_resolve_context(current, ioportcon->context, extra_args);
2129 if (rc != SEPOL_OK) {
2130 goto exit;
2131 }
2132 }
2133
2134 return SEPOL_OK;
2135
2136 exit:
2137 return rc;
2138 }
2139
cil_resolve_pcidevicecon(struct cil_tree_node * current,void * extra_args)2140 int cil_resolve_pcidevicecon(struct cil_tree_node *current, void *extra_args)
2141 {
2142 struct cil_pcidevicecon *pcidevicecon = current->data;
2143 struct cil_symtab_datum *context_datum = NULL;
2144 int rc = SEPOL_ERR;
2145
2146 if (pcidevicecon->context_str != NULL) {
2147 rc = cil_resolve_name(current, pcidevicecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2148 if (rc != SEPOL_OK) {
2149 goto exit;
2150 }
2151 pcidevicecon->context = (struct cil_context*)context_datum;
2152 } else {
2153 rc = cil_resolve_context(current, pcidevicecon->context, extra_args);
2154 if (rc != SEPOL_OK) {
2155 goto exit;
2156 }
2157 }
2158
2159 return SEPOL_OK;
2160
2161 exit:
2162 return rc;
2163 }
2164
cil_resolve_devicetreecon(struct cil_tree_node * current,void * extra_args)2165 int cil_resolve_devicetreecon(struct cil_tree_node *current, void *extra_args)
2166 {
2167 struct cil_devicetreecon *devicetreecon = current->data;
2168 struct cil_symtab_datum *context_datum = NULL;
2169 int rc = SEPOL_ERR;
2170
2171 if (devicetreecon->context_str != NULL) {
2172 rc = cil_resolve_name(current, devicetreecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2173 if (rc != SEPOL_OK) {
2174 goto exit;
2175 }
2176 devicetreecon->context = (struct cil_context*)context_datum;
2177 } else {
2178 rc = cil_resolve_context(current, devicetreecon->context, extra_args);
2179 if (rc != SEPOL_OK) {
2180 goto exit;
2181 }
2182 }
2183
2184 return SEPOL_OK;
2185
2186 exit:
2187 return rc;
2188 }
2189
cil_resolve_fsuse(struct cil_tree_node * current,void * extra_args)2190 int cil_resolve_fsuse(struct cil_tree_node *current, void *extra_args)
2191 {
2192 struct cil_fsuse *fsuse = current->data;
2193 struct cil_symtab_datum *context_datum = NULL;
2194 int rc = SEPOL_ERR;
2195
2196 if (fsuse->context_str != NULL) {
2197 rc = cil_resolve_name(current, fsuse->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2198 if (rc != SEPOL_OK) {
2199 goto exit;
2200 }
2201 fsuse->context = (struct cil_context*)context_datum;
2202 } else {
2203 rc = cil_resolve_context(current, fsuse->context, extra_args);
2204 if (rc != SEPOL_OK) {
2205 goto exit;
2206 }
2207 }
2208
2209 return SEPOL_OK;
2210
2211 exit:
2212 return rc;
2213 }
2214
cil_resolve_sidcontext(struct cil_tree_node * current,void * extra_args)2215 int cil_resolve_sidcontext(struct cil_tree_node *current, void *extra_args)
2216 {
2217 struct cil_sidcontext *sidcon = current->data;
2218 struct cil_symtab_datum *sid_datum = NULL;
2219 struct cil_symtab_datum *context_datum = NULL;
2220 struct cil_sid *sid = NULL;
2221
2222 int rc = SEPOL_ERR;
2223
2224 rc = cil_resolve_name(current, sidcon->sid_str, CIL_SYM_SIDS, extra_args, &sid_datum);
2225 if (rc != SEPOL_OK) {
2226 goto exit;
2227 }
2228 sid = (struct cil_sid*)sid_datum;
2229
2230 if (sidcon->context_str != NULL) {
2231 rc = cil_resolve_name(current, sidcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum);
2232 if (rc != SEPOL_OK) {
2233 goto exit;
2234 }
2235 sidcon->context = (struct cil_context*)context_datum;
2236 } else if (sidcon->context != NULL) {
2237 rc = cil_resolve_context(current, sidcon->context, extra_args);
2238 if (rc != SEPOL_OK) {
2239 goto exit;
2240 }
2241 }
2242
2243 if (sid->context != NULL) {
2244 cil_log(CIL_ERR, "sid's cannot be associated with more than one context\n");
2245 rc = SEPOL_ERR;
2246 goto exit;
2247 }
2248
2249 sid->context = sidcon->context;
2250
2251 return SEPOL_OK;
2252
2253 exit:
2254 return rc;
2255 }
2256
cil_resolve_blockinherit_link(struct cil_tree_node * current,void * extra_args)2257 int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args)
2258 {
2259 struct cil_blockinherit *inherit = current->data;
2260 struct cil_symtab_datum *block_datum = NULL;
2261 struct cil_tree_node *node = NULL;
2262 int rc = SEPOL_ERR;
2263
2264 rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
2265 if (rc != SEPOL_OK) {
2266 goto exit;
2267 }
2268
2269 node = block_datum->nodes->head->data;
2270
2271 if (node->flavor != CIL_BLOCK) {
2272 cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node));
2273 rc = SEPOL_ERR;
2274 goto exit;
2275 }
2276
2277 inherit->block = (struct cil_block *)block_datum;
2278
2279 if (inherit->block->bi_nodes == NULL) {
2280 cil_list_init(&inherit->block->bi_nodes, CIL_NODE);
2281 }
2282 cil_list_append(inherit->block->bi_nodes, CIL_NODE, current);
2283
2284 return SEPOL_OK;
2285
2286 exit:
2287 return rc;
2288 }
2289
cil_print_recursive_blockinherit(struct cil_tree_node * bi_node,struct cil_tree_node * terminating_node)2290 void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node)
2291 {
2292 struct cil_list *trace = NULL;
2293 struct cil_list_item *item = NULL;
2294 struct cil_tree_node *curr = NULL;
2295
2296 cil_list_init(&trace, CIL_NODE);
2297
2298 for (curr = bi_node; curr != terminating_node; curr = curr->parent) {
2299 if (curr->flavor == CIL_BLOCK) {
2300 cil_list_prepend(trace, CIL_NODE, curr);
2301 } else {
2302 if (curr != bi_node) {
2303 cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_blockinherit *)curr->data)->block));
2304 }
2305 cil_list_prepend(trace, CIL_NODE, curr);
2306 }
2307 }
2308 cil_list_prepend(trace, CIL_NODE, terminating_node);
2309
2310 cil_list_for_each(item, trace) {
2311 curr = item->data;
2312 if (curr->flavor == CIL_BLOCK) {
2313 cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name);
2314 } else {
2315 cil_tree_log(curr, CIL_ERR, "blockinherit %s", ((struct cil_blockinherit *)curr->data)->block_str);
2316 }
2317 }
2318
2319 cil_list_destroy(&trace, CIL_FALSE);
2320 }
2321
cil_check_recursive_blockinherit(struct cil_tree_node * bi_node)2322 int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node)
2323 {
2324 struct cil_tree_node *curr = NULL;
2325 struct cil_blockinherit *bi = NULL;
2326 struct cil_block *block = NULL;
2327 int rc = SEPOL_ERR;
2328
2329 bi = bi_node->data;
2330
2331 for (curr = bi_node->parent; curr != NULL; curr = curr->parent) {
2332 if (curr->flavor != CIL_BLOCK) {
2333 continue;
2334 }
2335
2336 block = curr->data;
2337
2338 if (block != bi->block) {
2339 continue;
2340 }
2341
2342 cil_log(CIL_ERR, "Recursive blockinherit found:\n");
2343 cil_print_recursive_blockinherit(bi_node, curr);
2344
2345 rc = SEPOL_ERR;
2346 goto exit;
2347 }
2348
2349 rc = SEPOL_OK;
2350
2351 exit:
2352 return rc;
2353 }
2354
cil_resolve_blockinherit_copy(struct cil_tree_node * current,void * extra_args)2355 int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args)
2356 {
2357 struct cil_block *block = current->data;
2358 struct cil_args_resolve *args = extra_args;
2359 struct cil_db *db = NULL;
2360 struct cil_list_item *item = NULL;
2361 int rc = SEPOL_ERR;
2362
2363 // This block is not inherited
2364 if (block->bi_nodes == NULL) {
2365 rc = SEPOL_OK;
2366 goto exit;
2367 }
2368
2369 db = args->db;
2370
2371 // Make sure this is the original block and not a merged block from a blockinherit
2372 if (current != block->datum.nodes->head->data) {
2373 rc = SEPOL_OK;
2374 goto exit;
2375 }
2376
2377 cil_list_for_each(item, block->bi_nodes) {
2378 rc = cil_check_recursive_blockinherit(item->data);
2379 if (rc != SEPOL_OK) {
2380 goto exit;
2381 }
2382
2383 rc = cil_copy_ast(db, current, item->data);
2384 if (rc != SEPOL_OK) {
2385 cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n");
2386 goto exit;
2387 }
2388 }
2389
2390 return SEPOL_OK;
2391
2392 exit:
2393 return rc;
2394 }
2395
cil_resolve_blockabstract(struct cil_tree_node * current,void * extra_args)2396 int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args)
2397 {
2398 struct cil_blockabstract *abstract = current->data;
2399 struct cil_symtab_datum *block_datum = NULL;
2400 struct cil_tree_node *block_node = NULL;
2401 int rc = SEPOL_ERR;
2402
2403 rc = cil_resolve_name(current, abstract->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
2404 if (rc != SEPOL_OK) {
2405 goto exit;
2406 }
2407
2408 block_node = block_datum->nodes->head->data;
2409 if (block_node->flavor != CIL_BLOCK) {
2410 cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc);
2411 goto exit;
2412 }
2413
2414 ((struct cil_block*)block_datum)->is_abstract = CIL_TRUE;
2415
2416 return SEPOL_OK;
2417
2418 exit:
2419 return rc;
2420 }
2421
cil_resolve_in(struct cil_tree_node * current,void * extra_args)2422 int cil_resolve_in(struct cil_tree_node *current, void *extra_args)
2423 {
2424 struct cil_in *in = current->data;
2425 struct cil_args_resolve *args = extra_args;
2426 struct cil_db *db = NULL;
2427 struct cil_symtab_datum *block_datum = NULL;
2428 struct cil_tree_node *block_node = NULL;
2429 int rc = SEPOL_ERR;
2430
2431 if (args != NULL) {
2432 db = args->db;
2433 }
2434
2435 rc = cil_resolve_name(current, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
2436 if (rc != SEPOL_OK) {
2437 goto exit;
2438 }
2439
2440 block_node = block_datum->nodes->head->data;
2441
2442 rc = cil_copy_ast(db, current, block_node);
2443 if (rc != SEPOL_OK) {
2444 printf("Failed to copy in, rc: %d\n", rc);
2445 goto exit;
2446 }
2447
2448 cil_tree_children_destroy(current);
2449 current->cl_head = NULL;
2450 current->cl_tail = NULL;
2451
2452 return SEPOL_OK;
2453
2454 exit:
2455 return rc;
2456 }
2457
cil_resolve_in_list(void * extra_args)2458 int cil_resolve_in_list(void *extra_args)
2459 {
2460 struct cil_args_resolve *args = extra_args;
2461 struct cil_list *ins = args->in_list;
2462 struct cil_list_item *curr = NULL;
2463 struct cil_tree_node *node = NULL;
2464 struct cil_tree_node *last_failed_node = NULL;
2465 struct cil_in *in = NULL;
2466 struct cil_symtab_datum *block_datum = NULL;
2467 int resolved = 0;
2468 int unresolved = 0;
2469 int rc = SEPOL_ERR;
2470
2471 do {
2472 resolved = 0;
2473 unresolved = 0;
2474
2475 cil_list_for_each(curr, ins) {
2476 if (curr->flavor != CIL_NODE) {
2477 continue;
2478 }
2479
2480 node = curr->data;
2481 in = node->data;
2482
2483 rc = cil_resolve_name(node, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
2484 if (rc != SEPOL_OK) {
2485 unresolved++;
2486 last_failed_node = node;
2487 } else {
2488 rc = cil_resolve_in(node, extra_args);
2489 if (rc != SEPOL_OK) {
2490 goto exit;
2491 }
2492
2493 resolved++;
2494 curr->data = NULL;
2495 curr->flavor = CIL_NONE;
2496 }
2497 }
2498
2499 if (unresolved > 0 && resolved == 0) {
2500 cil_tree_log(last_failed_node, CIL_ERR, "Failed to resolve in-statement");
2501 rc = SEPOL_ERR;
2502 goto exit;
2503 }
2504
2505 } while (unresolved > 0);
2506
2507 rc = SEPOL_OK;
2508
2509 exit:
2510 return rc;
2511 }
2512
2513
cil_resolve_bounds(struct cil_tree_node * current,void * extra_args,enum cil_flavor flavor,enum cil_flavor attr_flavor)2514 int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor attr_flavor)
2515 {
2516 int rc = SEPOL_ERR;
2517 struct cil_bounds *bounds = current->data;
2518 enum cil_sym_index index;
2519 struct cil_symtab_datum *parent_datum = NULL;
2520 struct cil_symtab_datum *child_datum = NULL;
2521
2522 rc = cil_flavor_to_symtab_index(flavor, &index);
2523 if (rc != SEPOL_OK) {
2524 goto exit;
2525 }
2526
2527 rc = cil_resolve_name(current, bounds->parent_str, index, extra_args, &parent_datum);
2528 if (rc != SEPOL_OK) {
2529 goto exit;
2530 }
2531 if (NODE(parent_datum)->flavor == attr_flavor) {
2532 cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
2533 rc = SEPOL_ERR;
2534 goto exit;
2535 }
2536
2537
2538 rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum);
2539 if (rc != SEPOL_OK) {
2540 goto exit;
2541 }
2542 if (NODE(child_datum)->flavor == attr_flavor) {
2543 cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
2544 rc = SEPOL_ERR;
2545 goto exit;
2546 }
2547
2548 switch (flavor) {
2549 case CIL_USER: {
2550 struct cil_user *user = (struct cil_user *)child_datum;
2551
2552 if (user->bounds != NULL) {
2553 cil_tree_log(NODE(user->bounds), CIL_ERR, "User %s already bound by parent", bounds->child_str);
2554 rc = SEPOL_ERR;
2555 goto exit;
2556 }
2557
2558 user->bounds = (struct cil_user *)parent_datum;
2559 break;
2560 }
2561 case CIL_ROLE: {
2562 struct cil_role *role = (struct cil_role *)child_datum;
2563
2564 if (role->bounds != NULL) {
2565 cil_tree_log(NODE(role->bounds), CIL_ERR, "Role %s already bound by parent", bounds->child_str);
2566 rc = SEPOL_ERR;
2567 goto exit;
2568 }
2569
2570 role->bounds = (struct cil_role *)parent_datum;
2571 break;
2572 }
2573 case CIL_TYPE: {
2574 struct cil_type *type = (struct cil_type *)child_datum;
2575
2576 if (type->bounds != NULL) {
2577 cil_tree_log(NODE(type->bounds), CIL_ERR, "Type %s already bound by parent", bounds->child_str);
2578 rc = SEPOL_ERR;
2579 goto exit;
2580 }
2581
2582 type->bounds = (struct cil_type *)parent_datum;
2583 break;
2584 }
2585 default:
2586 break;
2587 }
2588
2589 return SEPOL_OK;
2590
2591 exit:
2592 cil_tree_log(current, CIL_ERR, "Bad bounds statement");
2593 return rc;
2594 }
2595
cil_resolve_default(struct cil_tree_node * current,void * extra_args)2596 int cil_resolve_default(struct cil_tree_node *current, void *extra_args)
2597 {
2598 int rc = SEPOL_ERR;
2599 struct cil_default *def = current->data;
2600 struct cil_list_item *curr;
2601 struct cil_symtab_datum *datum;
2602
2603 cil_list_init(&def->class_datums, def->flavor);
2604
2605 cil_list_for_each(curr, def->class_strs) {
2606 rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
2607 if (rc != SEPOL_OK) {
2608 goto exit;
2609 }
2610 cil_list_append(def->class_datums, CIL_CLASS, datum);
2611 }
2612
2613 return SEPOL_OK;
2614
2615 exit:
2616 return rc;
2617 }
2618
cil_resolve_defaultrange(struct cil_tree_node * current,void * extra_args)2619 int cil_resolve_defaultrange(struct cil_tree_node *current, void *extra_args)
2620 {
2621 int rc = SEPOL_ERR;
2622 struct cil_defaultrange *def = current->data;
2623 struct cil_list_item *curr;
2624 struct cil_symtab_datum *datum;
2625
2626 cil_list_init(&def->class_datums, CIL_DEFAULTRANGE);
2627
2628 cil_list_for_each(curr, def->class_strs) {
2629 rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
2630 if (rc != SEPOL_OK) {
2631 goto exit;
2632 }
2633 cil_list_append(def->class_datums, CIL_CLASS, datum);
2634 }
2635
2636 return SEPOL_OK;
2637
2638 exit:
2639 return rc;
2640 }
2641
cil_print_recursive_call(struct cil_tree_node * call_node,struct cil_tree_node * terminating_node)2642 void cil_print_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *terminating_node)
2643 {
2644 struct cil_list *trace = NULL;
2645 struct cil_list_item * item = NULL;
2646 struct cil_tree_node *curr = NULL;
2647
2648 cil_list_init(&trace, CIL_NODE);
2649
2650 for (curr = call_node; curr != terminating_node; curr = curr->parent) {
2651 if (curr->flavor == CIL_CALL) {
2652 if (curr != call_node) {
2653 cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)curr->data)->macro));
2654 }
2655 cil_list_prepend(trace, CIL_NODE, curr);
2656 }
2657 }
2658
2659 if (terminating_node->flavor == CIL_MACRO) {
2660 cil_list_prepend(trace, CIL_NODE, terminating_node);
2661 } else {
2662 cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)terminating_node->data)->macro));
2663 }
2664
2665 cil_list_for_each(item, trace) {
2666 curr = item->data;
2667 if (curr->flavor == CIL_MACRO) {
2668 cil_tree_log(curr, CIL_ERR, "macro %s", DATUM(curr->data)->name);
2669 } else {
2670 cil_tree_log(curr, CIL_ERR, "call %s", ((struct cil_call *)curr->data)->macro_str);
2671 }
2672 }
2673
2674 cil_list_destroy(&trace, CIL_FALSE);
2675 }
2676
cil_check_recursive_call(struct cil_tree_node * call_node,struct cil_tree_node * macro_node)2677 int cil_check_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *macro_node)
2678 {
2679 struct cil_tree_node *curr = NULL;
2680 struct cil_call * call = NULL;
2681 int rc = SEPOL_ERR;
2682
2683 for (curr = call_node; curr != NULL; curr = curr->parent) {
2684 if (curr->flavor == CIL_CALL) {
2685 if (curr == call_node) {
2686 continue;
2687 }
2688
2689 call = curr->data;
2690 if (call->macro != macro_node->data) {
2691 continue;
2692 }
2693 } else if (curr->flavor == CIL_MACRO) {
2694 if (curr != macro_node) {
2695 rc = SEPOL_OK;
2696 goto exit;
2697 }
2698 } else {
2699 continue;
2700 }
2701
2702 cil_log(CIL_ERR, "Recursive macro call found:\n");
2703 cil_print_recursive_call(call_node, curr);
2704
2705 rc = SEPOL_ERR;
2706 goto exit;
2707 }
2708
2709 rc = SEPOL_OK;
2710 exit:
2711 return rc;
2712 }
2713
cil_resolve_call1(struct cil_tree_node * current,void * extra_args)2714 int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
2715 {
2716 struct cil_call *new_call = current->data;
2717 struct cil_args_resolve *args = extra_args;
2718 struct cil_db *db = NULL;
2719 struct cil_tree_node *macro_node = NULL;
2720 struct cil_symtab_datum *macro_datum = NULL;
2721 int rc = SEPOL_ERR;
2722
2723 if (args != NULL) {
2724 db = args->db;
2725 }
2726
2727 rc = cil_resolve_name(current, new_call->macro_str, CIL_SYM_BLOCKS, extra_args, ¯o_datum);
2728 if (rc != SEPOL_OK) {
2729 goto exit;
2730 }
2731
2732 macro_node = macro_datum->nodes->head->data;
2733
2734 if (macro_node->flavor != CIL_MACRO) {
2735 printf("Failed to resolve %s to a macro\n", new_call->macro_str);
2736 rc = SEPOL_ERR;
2737 goto exit;
2738 }
2739 new_call->macro = (struct cil_macro*)macro_datum;
2740
2741 if (new_call->macro->params != NULL ) {
2742
2743 struct cil_list_item *item;
2744 struct cil_args *new_arg = NULL;
2745 struct cil_tree_node *pc = NULL;
2746
2747 if (new_call->args_tree == NULL) {
2748 cil_tree_log(current, CIL_ERR, "Missing arguments");
2749 rc = SEPOL_ERR;
2750 goto exit;
2751 }
2752
2753 pc = new_call->args_tree->root->cl_head;
2754
2755 cil_list_init(&new_call->args, CIL_LIST_ITEM);
2756
2757 cil_list_for_each(item, new_call->macro->params) {
2758 enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
2759
2760 if (pc == NULL) {
2761 cil_tree_log(current, CIL_ERR, "Missing arguments");
2762 rc = SEPOL_ERR;
2763 goto exit;
2764 }
2765 if (item->flavor != CIL_PARAM) {
2766 rc = SEPOL_ERR;
2767 goto exit;
2768 }
2769
2770 cil_args_init(&new_arg);
2771
2772 switch (flavor) {
2773 case CIL_NAME: {
2774 struct cil_name *name;
2775 name = __cil_insert_name(args->db, pc->data, current);
2776 if (name != NULL) {
2777 new_arg->arg = (struct cil_symtab_datum *)name;
2778 } else {
2779 new_arg->arg_str = pc->data;
2780 }
2781 }
2782 break;
2783 case CIL_TYPE:
2784 new_arg->arg_str = pc->data;
2785 break;
2786 case CIL_ROLE:
2787 new_arg->arg_str = pc->data;
2788 break;
2789 case CIL_USER:
2790 new_arg->arg_str = pc->data;
2791 break;
2792 case CIL_SENS:
2793 new_arg->arg_str = pc->data;
2794 break;
2795 case CIL_CAT:
2796 new_arg->arg_str = pc->data;
2797 break;
2798 case CIL_BOOL:
2799 new_arg->arg_str = pc->data;
2800 break;
2801 case CIL_CATSET: {
2802 if (pc->cl_head != NULL) {
2803 struct cil_catset *catset = NULL;
2804 struct cil_tree_node *cat_node = NULL;
2805 cil_catset_init(&catset);
2806 rc = cil_fill_cats(pc, &catset->cats);
2807 if (rc != SEPOL_OK) {
2808 cil_destroy_catset(catset);
2809 goto exit;
2810 }
2811 cil_tree_node_init(&cat_node);
2812 cat_node->flavor = CIL_CATSET;
2813 cat_node->data = catset;
2814 cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
2815 CIL_LIST_ITEM, cat_node);
2816 new_arg->arg = (struct cil_symtab_datum*)catset;
2817 } else {
2818 new_arg->arg_str = pc->data;
2819 }
2820
2821 break;
2822 }
2823 case CIL_LEVEL: {
2824 if (pc->cl_head != NULL) {
2825 struct cil_level *level = NULL;
2826 struct cil_tree_node *lvl_node = NULL;
2827 cil_level_init(&level);
2828
2829 rc = cil_fill_level(pc->cl_head, level);
2830 if (rc != SEPOL_OK) {
2831 cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
2832 cil_destroy_level(level);
2833 goto exit;
2834 }
2835 cil_tree_node_init(&lvl_node);
2836 lvl_node->flavor = CIL_LEVEL;
2837 lvl_node->data = level;
2838 cil_list_append(((struct cil_symtab_datum*)level)->nodes,
2839 CIL_LIST_ITEM, lvl_node);
2840 new_arg->arg = (struct cil_symtab_datum*)level;
2841 } else {
2842 new_arg->arg_str = pc->data;
2843 }
2844
2845 break;
2846 }
2847 case CIL_LEVELRANGE: {
2848 if (pc->cl_head != NULL) {
2849 struct cil_levelrange *range = NULL;
2850 struct cil_tree_node *range_node = NULL;
2851 cil_levelrange_init(&range);
2852
2853 rc = cil_fill_levelrange(pc->cl_head, range);
2854 if (rc != SEPOL_OK) {
2855 cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
2856 cil_destroy_levelrange(range);
2857 goto exit;
2858 }
2859 cil_tree_node_init(&range_node);
2860 range_node->flavor = CIL_LEVELRANGE;
2861 range_node->data = range;
2862 cil_list_append(((struct cil_symtab_datum*)range)->nodes,
2863 CIL_LIST_ITEM, range_node);
2864 new_arg->arg = (struct cil_symtab_datum*)range;
2865 } else {
2866 new_arg->arg_str = pc->data;
2867 }
2868
2869 break;
2870 }
2871 case CIL_IPADDR: {
2872 if (pc->cl_head != NULL) {
2873 struct cil_ipaddr *ipaddr = NULL;
2874 struct cil_tree_node *addr_node = NULL;
2875 cil_ipaddr_init(&ipaddr);
2876
2877 rc = cil_fill_ipaddr(pc->cl_head, ipaddr);
2878 if (rc != SEPOL_OK) {
2879 cil_log(CIL_ERR, "Failed to create anonymous ip address, rc; %d\n", rc);
2880 cil_destroy_ipaddr(ipaddr);
2881 goto exit;
2882 }
2883 cil_tree_node_init(&addr_node);
2884 addr_node->flavor = CIL_IPADDR;
2885 addr_node->data = ipaddr;
2886 cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes,
2887 CIL_LIST_ITEM, addr_node);
2888 new_arg->arg = (struct cil_symtab_datum*)ipaddr;
2889 } else {
2890 new_arg->arg_str = pc->data;
2891 }
2892
2893 break;
2894 }
2895 case CIL_CLASS:
2896 new_arg->arg_str = pc->data;
2897 break;
2898 case CIL_MAP_CLASS:
2899 new_arg->arg_str = pc->data;
2900 break;
2901 case CIL_CLASSPERMISSION: {
2902 if (pc->cl_head != NULL) {
2903 struct cil_classpermission *cp = NULL;
2904 struct cil_tree_node *cp_node = NULL;
2905
2906 cil_classpermission_init(&cp);
2907 rc = cil_fill_classperms_list(pc, &cp->classperms);
2908 if (rc != SEPOL_OK) {
2909 cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
2910 cil_destroy_classpermission(cp);
2911 goto exit;
2912 }
2913 cil_tree_node_init(&cp_node);
2914 cp_node->flavor = CIL_CLASSPERMISSION;
2915 cp_node->data = cp;
2916 cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
2917 new_arg->arg = (struct cil_symtab_datum*)cp;
2918 } else {
2919 new_arg->arg_str = pc->data;
2920 }
2921 break;
2922 }
2923 default:
2924 cil_log(CIL_ERR, "Unexpected flavor: %d\n",
2925 (((struct cil_param*)item->data)->flavor));
2926 rc = SEPOL_ERR;
2927 goto exit;
2928 }
2929 new_arg->param_str = ((struct cil_param*)item->data)->str;
2930 new_arg->flavor = flavor;
2931
2932 cil_list_append(new_call->args, CIL_ARGS, new_arg);
2933
2934 pc = pc->next;
2935 }
2936
2937 if (pc != NULL) {
2938 cil_tree_log(current, CIL_ERR, "Unexpected arguments");
2939 rc = SEPOL_ERR;
2940 goto exit;
2941 }
2942 } else if (new_call->args_tree != NULL) {
2943 cil_tree_log(current, CIL_ERR, "Unexpected arguments");
2944 rc = SEPOL_ERR;
2945 goto exit;
2946 }
2947
2948 if (new_call->copied == 0) {
2949 new_call->copied = 1;
2950
2951 rc = cil_check_recursive_call(current, macro_node);
2952 if (rc != SEPOL_OK) {
2953 goto exit;
2954 }
2955
2956 rc = cil_copy_ast(db, macro_node, current);
2957 if (rc != SEPOL_OK) {
2958 cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc);
2959 goto exit;
2960 }
2961 }
2962
2963 return SEPOL_OK;
2964
2965 exit:
2966 return rc;
2967 }
2968
cil_resolve_call2(struct cil_tree_node * current,void * extra_args)2969 int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
2970 {
2971 struct cil_call *new_call = current->data;
2972 int rc = SEPOL_ERR;
2973 enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
2974 struct cil_list_item *item;
2975
2976 if (new_call->args == NULL) {
2977 rc = SEPOL_OK;
2978 goto exit;
2979 }
2980
2981 cil_list_for_each(item, new_call->args) {
2982 struct cil_args *arg = item->data;
2983 if (arg->arg == NULL && arg->arg_str == NULL) {
2984 cil_log(CIL_ERR, "Arguments not created correctly\n");
2985 rc = SEPOL_ERR;
2986 goto exit;
2987 }
2988
2989 switch (arg->flavor) {
2990 case CIL_NAME:
2991 if (arg->arg != NULL) {
2992 continue; /* No need to resolve */
2993 } else {
2994 sym_index = CIL_SYM_NAMES;
2995 }
2996 break;
2997 case CIL_LEVEL:
2998 if (arg->arg_str == NULL && arg->arg != NULL) {
2999 continue; // anonymous, no need to resolve
3000 } else {
3001 sym_index = CIL_SYM_LEVELS;
3002 }
3003 break;
3004 case CIL_LEVELRANGE:
3005 if (arg->arg_str == NULL && arg->arg != NULL) {
3006 continue; // anonymous, no need to resolve
3007 } else {
3008 sym_index = CIL_SYM_LEVELRANGES;
3009 }
3010 break;
3011 case CIL_CATSET:
3012 if (arg->arg_str == NULL && arg->arg != NULL) {
3013 continue; // anonymous, no need to resolve
3014 } else {
3015 sym_index = CIL_SYM_CATS;
3016 }
3017 break;
3018 case CIL_IPADDR:
3019 if (arg->arg_str == NULL && arg->arg != NULL) {
3020 continue; // anonymous, no need to resolve
3021 } else {
3022 sym_index = CIL_SYM_IPADDRS;
3023 }
3024 break;
3025 case CIL_CLASSPERMISSION:
3026 if (arg->arg_str == NULL && arg->arg != NULL) {
3027 continue;
3028 } else {
3029 sym_index = CIL_SYM_CLASSPERMSETS;
3030 }
3031 break;
3032 case CIL_TYPE:
3033 if (arg->arg_str == NULL && arg->arg != NULL) {
3034 continue; // anonymous, no need to resolve
3035 } else {
3036 sym_index = CIL_SYM_TYPES;
3037 }
3038 break;
3039 case CIL_ROLE:
3040 sym_index = CIL_SYM_ROLES;
3041 break;
3042 case CIL_USER:
3043 sym_index = CIL_SYM_USERS;
3044 break;
3045 case CIL_SENS:
3046 sym_index = CIL_SYM_SENS;
3047 break;
3048 case CIL_CAT:
3049 sym_index = CIL_SYM_CATS;
3050 break;
3051 case CIL_CLASS:
3052 case CIL_MAP_CLASS:
3053 sym_index = CIL_SYM_CLASSES;
3054 break;
3055 case CIL_BOOL:
3056 sym_index = CIL_SYM_BOOLS;
3057 break;
3058 default:
3059 rc = SEPOL_ERR;
3060 goto exit;
3061 }
3062
3063 if (sym_index != CIL_SYM_UNKNOWN) {
3064 rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
3065 if (rc != SEPOL_OK) {
3066 goto exit;
3067 }
3068 }
3069 }
3070
3071 return SEPOL_OK;
3072
3073 exit:
3074 return rc;
3075 }
3076
cil_resolve_name_call_args(struct cil_call * call,char * name,enum cil_sym_index sym_index,struct cil_symtab_datum ** datum)3077 int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
3078 {
3079 struct cil_list_item *item;
3080 enum cil_sym_index param_index = CIL_SYM_UNKNOWN;
3081 int rc = SEPOL_ERR;
3082
3083 if (call == NULL || name == NULL) {
3084 goto exit;
3085 }
3086
3087 if (call->args == NULL) {
3088 goto exit;
3089 }
3090
3091 cil_list_for_each(item, call->args) {
3092 struct cil_args * arg = item->data;
3093 rc = cil_flavor_to_symtab_index(arg->flavor, ¶m_index);
3094 if (param_index == sym_index) {
3095 if (name == arg->param_str) {
3096 *datum = arg->arg;
3097 rc = SEPOL_OK;
3098 goto exit;
3099 }
3100 }
3101 }
3102
3103 return SEPOL_ERR;
3104
3105 exit:
3106 return rc;
3107 }
3108
cil_resolve_expr(enum cil_flavor expr_type,struct cil_list * str_expr,struct cil_list ** datum_expr,struct cil_tree_node * parent,void * extra_args)3109 int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, void *extra_args)
3110 {
3111 int rc = SEPOL_ERR;
3112 struct cil_list_item *curr;
3113 struct cil_symtab_datum *res_datum = NULL;
3114 enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
3115
3116 switch (str_expr->flavor) {
3117 case CIL_BOOL:
3118 sym_index = CIL_SYM_BOOLS;
3119 break;
3120 case CIL_TUNABLE:
3121 sym_index = CIL_SYM_TUNABLES;
3122 break;
3123 case CIL_TYPE:
3124 sym_index = CIL_SYM_TYPES;
3125 break;
3126 case CIL_ROLE:
3127 sym_index = CIL_SYM_ROLES;
3128 break;
3129 case CIL_USER:
3130 sym_index = CIL_SYM_USERS;
3131 break;
3132 case CIL_CAT:
3133 sym_index = CIL_SYM_CATS;
3134 break;
3135 default:
3136 break;
3137 }
3138
3139 cil_list_init(datum_expr, str_expr->flavor);
3140
3141 cil_list_for_each(curr, str_expr) {
3142 switch (curr->flavor) {
3143 case CIL_STRING:
3144 rc = cil_resolve_name(parent, curr->data, sym_index, extra_args, &res_datum);
3145 if (rc != SEPOL_OK) {
3146 goto exit;
3147 }
3148
3149 if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
3150 cil_type_used(res_datum, CIL_ATTR_CONSTRAINT);
3151 }
3152
3153 cil_list_append(*datum_expr, CIL_DATUM, res_datum);
3154 break;
3155 case CIL_LIST: {
3156 struct cil_list *datum_sub_expr;
3157 rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args);
3158 if (rc != SEPOL_OK) {
3159 cil_list_destroy(&datum_sub_expr, CIL_TRUE);
3160 goto exit;
3161 }
3162 cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
3163 break;
3164 }
3165 default:
3166 cil_list_append(*datum_expr, curr->flavor, curr->data);
3167 break;
3168 }
3169 }
3170 return SEPOL_OK;
3171
3172 exit:
3173 return rc;
3174 }
3175
cil_resolve_boolif(struct cil_tree_node * current,void * extra_args)3176 int cil_resolve_boolif(struct cil_tree_node *current, void *extra_args)
3177 {
3178 int rc = SEPOL_ERR;
3179 struct cil_booleanif *bif = (struct cil_booleanif*)current->data;
3180
3181 rc = cil_resolve_expr(CIL_BOOLEANIF, bif->str_expr, &bif->datum_expr, current, extra_args);
3182 if (rc != SEPOL_OK) {
3183 goto exit;
3184 }
3185
3186 return SEPOL_OK;
3187
3188 exit:
3189 return rc;
3190 }
3191
3192 static int __cil_evaluate_tunable_expr(struct cil_list_item *curr);
3193
__cil_evaluate_tunable_expr_helper(struct cil_list_item * curr)3194 static int __cil_evaluate_tunable_expr_helper(struct cil_list_item *curr)
3195 {
3196 if (curr == NULL) {
3197 return CIL_FALSE;
3198 } else if (curr->flavor == CIL_DATUM) {
3199 struct cil_tunable *tun = curr->data;
3200 return tun->value;
3201 } else if (curr->flavor == CIL_LIST) {
3202 struct cil_list *l = curr->data;
3203 return __cil_evaluate_tunable_expr(l->head);
3204 } else {
3205 return CIL_FALSE;
3206 }
3207 }
3208
__cil_evaluate_tunable_expr(struct cil_list_item * curr)3209 static int __cil_evaluate_tunable_expr(struct cil_list_item *curr)
3210 {
3211 /* Assumes expression is well-formed */
3212
3213 if (curr == NULL) {
3214 return CIL_FALSE;
3215 } else if (curr->flavor == CIL_OP) {
3216 uint16_t v1, v2;
3217 enum cil_flavor op_flavor = (enum cil_flavor)curr->data;
3218
3219 v1 = __cil_evaluate_tunable_expr_helper(curr->next);
3220
3221 if (op_flavor == CIL_NOT) return !v1;
3222
3223 v2 = __cil_evaluate_tunable_expr_helper(curr->next->next);
3224
3225 if (op_flavor == CIL_AND) return (v1 && v2);
3226 else if (op_flavor == CIL_OR) return (v1 || v2);
3227 else if (op_flavor == CIL_XOR) return (v1 ^ v2);
3228 else if (op_flavor == CIL_EQ) return (v1 == v2);
3229 else if (op_flavor == CIL_NEQ) return (v1 != v2);
3230 else return CIL_FALSE;
3231 } else {
3232 uint16_t v;
3233 for (;curr; curr = curr->next) {
3234 v = __cil_evaluate_tunable_expr_helper(curr);
3235 if (v) return v;
3236 }
3237 return CIL_FALSE;
3238 }
3239 }
3240
cil_resolve_tunif(struct cil_tree_node * current,void * extra_args)3241 int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args)
3242 {
3243 struct cil_args_resolve *args = extra_args;
3244 struct cil_db *db = NULL;
3245 int rc = SEPOL_ERR;
3246 struct cil_tunableif *tif = (struct cil_tunableif*)current->data;
3247 uint16_t result = CIL_FALSE;
3248 struct cil_tree_node *true_node = NULL;
3249 struct cil_tree_node *false_node = NULL;
3250 struct cil_condblock *cb = NULL;
3251
3252 if (args != NULL) {
3253 db = args->db;
3254 }
3255
3256 rc = cil_resolve_expr(CIL_TUNABLEIF, tif->str_expr, &tif->datum_expr, current, extra_args);
3257 if (rc != SEPOL_OK) {
3258 goto exit;
3259 }
3260
3261 result = __cil_evaluate_tunable_expr(tif->datum_expr->head);
3262
3263 if (current->cl_head != NULL && current->cl_head->flavor == CIL_CONDBLOCK) {
3264 cb = current->cl_head->data;
3265 if (cb->flavor == CIL_CONDTRUE) {
3266 true_node = current->cl_head;
3267 } else if (cb->flavor == CIL_CONDFALSE) {
3268 false_node = current->cl_head;
3269 }
3270 }
3271
3272 if (current->cl_head != NULL && current->cl_head->next != NULL && current->cl_head->next->flavor == CIL_CONDBLOCK) {
3273 cb = current->cl_head->next->data;
3274 if (cb->flavor == CIL_CONDTRUE) {
3275 true_node = current->cl_head->next;
3276 } else if (cb->flavor == CIL_CONDFALSE) {
3277 false_node = current->cl_head->next;
3278 }
3279 }
3280
3281 if (result == CIL_TRUE) {
3282 if (true_node != NULL) {
3283 rc = cil_copy_ast(db, true_node, current->parent);
3284 if (rc != SEPOL_OK) {
3285 goto exit;
3286 }
3287 }
3288 } else {
3289 if (false_node != NULL) {
3290 rc = cil_copy_ast(db, false_node, current->parent);
3291 if (rc != SEPOL_OK) {
3292 goto exit;
3293 }
3294 }
3295 }
3296
3297 cil_tree_children_destroy(current);
3298 current->cl_head = NULL;
3299 current->cl_tail = NULL;
3300
3301 return SEPOL_OK;
3302
3303 exit:
3304 return rc;
3305 }
3306
cil_resolve_userattributeset(struct cil_tree_node * current,void * extra_args)3307 int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args)
3308 {
3309 int rc = SEPOL_ERR;
3310 struct cil_userattributeset *attrusers = current->data;
3311 struct cil_symtab_datum *attr_datum = NULL;
3312 struct cil_tree_node *attr_node = NULL;
3313 struct cil_userattribute *attr = NULL;
3314
3315 rc = cil_resolve_name(current, attrusers->attr_str, CIL_SYM_USERS, extra_args, &attr_datum);
3316 if (rc != SEPOL_OK) {
3317 goto exit;
3318 }
3319 attr_node = attr_datum->nodes->head->data;
3320
3321 if (attr_node->flavor != CIL_USERATTRIBUTE) {
3322 rc = SEPOL_ERR;
3323 cil_log(CIL_ERR, "Attribute user not an attribute\n");
3324 goto exit;
3325 }
3326 attr = (struct cil_userattribute*)attr_datum;
3327
3328 rc = cil_resolve_expr(CIL_USERATTRIBUTESET, attrusers->str_expr, &attrusers->datum_expr, current, extra_args);
3329 if (rc != SEPOL_OK) {
3330 goto exit;
3331 }
3332
3333 rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr);
3334 if (rc != SEPOL_OK) {
3335 goto exit;
3336 }
3337
3338 if (attr->expr_list == NULL) {
3339 cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE);
3340 }
3341
3342 cil_list_append(attr->expr_list, CIL_LIST, attrusers->datum_expr);
3343
3344 return SEPOL_OK;
3345
3346 exit:
3347 return rc;
3348 }
3349
__cil_resolve_ast_node(struct cil_tree_node * node,void * extra_args)3350 int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
3351 {
3352 int rc = SEPOL_OK;
3353 struct cil_args_resolve *args = extra_args;
3354 enum cil_pass pass = 0;
3355 struct cil_list *ins;
3356
3357 if (node == NULL || args == NULL) {
3358 goto exit;
3359 }
3360 ins = args->in_list;
3361
3362 pass = args->pass;
3363 switch (pass) {
3364 case CIL_PASS_TIF:
3365 if (node->flavor == CIL_TUNABLEIF) {
3366 rc = cil_resolve_tunif(node, args);
3367 }
3368 break;
3369 case CIL_PASS_IN:
3370 if (node->flavor == CIL_IN) {
3371 // due to ordering issues, in statements are just gathered here and
3372 // resolved together in cil_resolve_in_list once all are found
3373 cil_list_prepend(ins, CIL_NODE, node);
3374 }
3375 break;
3376 case CIL_PASS_BLKIN_LINK:
3377 if (node->flavor == CIL_BLOCKINHERIT) {
3378 rc = cil_resolve_blockinherit_link(node, args);
3379 }
3380 break;
3381 case CIL_PASS_BLKIN_COPY:
3382 if (node->flavor == CIL_BLOCK) {
3383 rc = cil_resolve_blockinherit_copy(node, args);
3384 }
3385 break;
3386 case CIL_PASS_BLKABS:
3387 if (node->flavor == CIL_BLOCKABSTRACT) {
3388 rc = cil_resolve_blockabstract(node, args);
3389 }
3390 break;
3391 case CIL_PASS_MACRO:
3392 if (node->flavor == CIL_CALL && args->macro != NULL) {
3393 rc = cil_resolve_call1(node, args);
3394 }
3395 break;
3396 case CIL_PASS_CALL1:
3397 if (node->flavor == CIL_CALL) {
3398 rc = cil_resolve_call1(node, args);
3399 }
3400 break;
3401 case CIL_PASS_CALL2:
3402 if (node->flavor == CIL_CALL) {
3403 rc = cil_resolve_call2(node, args);
3404 }
3405 break;
3406 case CIL_PASS_ALIAS1:
3407 switch (node->flavor) {
3408 case CIL_TYPEALIASACTUAL:
3409 rc = cil_resolve_aliasactual(node, args, CIL_TYPE, CIL_TYPEALIAS);
3410 break;
3411 case CIL_SENSALIASACTUAL:
3412 rc = cil_resolve_aliasactual(node, args, CIL_SENS, CIL_SENSALIAS);
3413 break;
3414 case CIL_CATALIASACTUAL:
3415 rc = cil_resolve_aliasactual(node, args, CIL_CAT, CIL_CATALIAS);
3416 break;
3417 default:
3418 break;
3419 }
3420 break;
3421 case CIL_PASS_ALIAS2:
3422 switch (node->flavor) {
3423 case CIL_TYPEALIAS:
3424 rc = cil_resolve_alias_to_actual(node, CIL_TYPE);
3425 break;
3426 case CIL_SENSALIAS:
3427 rc = cil_resolve_alias_to_actual(node, CIL_SENS);
3428 break;
3429 case CIL_CATALIAS:
3430 rc = cil_resolve_alias_to_actual(node, CIL_CAT);
3431 break;
3432 default:
3433 break;
3434 }
3435 break;
3436 case CIL_PASS_MISC1:
3437 switch (node->flavor) {
3438 case CIL_SIDORDER:
3439 rc = cil_resolve_sidorder(node, args);
3440 break;
3441 case CIL_CLASSORDER:
3442 rc = cil_resolve_classorder(node, args);
3443 break;
3444 case CIL_CATORDER:
3445 rc = cil_resolve_catorder(node, args);
3446 break;
3447 case CIL_SENSITIVITYORDER:
3448 rc = cil_resolve_sensitivityorder(node, args);
3449 break;
3450 case CIL_BOOLEANIF:
3451 rc = cil_resolve_boolif(node, args);
3452 break;
3453 default:
3454 break;
3455 }
3456 break;
3457 case CIL_PASS_MLS:
3458 switch (node->flavor) {
3459 case CIL_CATSET:
3460 rc = cil_resolve_catset(node, (struct cil_catset*)node->data, args);
3461 break;
3462 default:
3463 break;
3464 }
3465 break;
3466 case CIL_PASS_MISC2:
3467 switch (node->flavor) {
3468 case CIL_SENSCAT:
3469 rc = cil_resolve_senscat(node, args);
3470 break;
3471 case CIL_CLASSCOMMON:
3472 rc = cil_resolve_classcommon(node, args);
3473 break;
3474 default:
3475 break;
3476 }
3477 break;
3478 case CIL_PASS_MISC3:
3479 switch (node->flavor) {
3480 case CIL_TYPEATTRIBUTESET:
3481 rc = cil_resolve_typeattributeset(node, args);
3482 break;
3483 case CIL_EXPANDTYPEATTRIBUTE:
3484 rc = cil_resolve_expandtypeattribute(node, args);
3485 break;
3486 case CIL_TYPEBOUNDS:
3487 rc = cil_resolve_bounds(node, args, CIL_TYPE, CIL_TYPEATTRIBUTE);
3488 break;
3489 case CIL_TYPEPERMISSIVE:
3490 rc = cil_resolve_typepermissive(node, args);
3491 break;
3492 case CIL_NAMETYPETRANSITION:
3493 rc = cil_resolve_nametypetransition(node, args);
3494 break;
3495 case CIL_RANGETRANSITION:
3496 rc = cil_resolve_rangetransition(node, args);
3497 break;
3498 case CIL_CLASSPERMISSIONSET:
3499 rc = cil_resolve_classpermissionset(node, (struct cil_classpermissionset*)node->data, args);
3500 break;
3501 case CIL_CLASSMAPPING:
3502 rc = cil_resolve_classmapping(node, args);
3503 break;
3504 case CIL_AVRULE:
3505 case CIL_AVRULEX:
3506 rc = cil_resolve_avrule(node, args);
3507 break;
3508 case CIL_PERMISSIONX:
3509 rc = cil_resolve_permissionx(node, (struct cil_permissionx*)node->data, args);
3510 break;
3511 case CIL_TYPE_RULE:
3512 rc = cil_resolve_type_rule(node, args);
3513 break;
3514 case CIL_USERROLE:
3515 rc = cil_resolve_userrole(node, args);
3516 break;
3517 case CIL_USERLEVEL:
3518 rc = cil_resolve_userlevel(node, args);
3519 break;
3520 case CIL_USERRANGE:
3521 rc = cil_resolve_userrange(node, args);
3522 break;
3523 case CIL_USERBOUNDS:
3524 rc = cil_resolve_bounds(node, args, CIL_USER, CIL_USERATTRIBUTE);
3525 break;
3526 case CIL_USERPREFIX:
3527 rc = cil_resolve_userprefix(node, args);
3528 break;
3529 case CIL_SELINUXUSER:
3530 case CIL_SELINUXUSERDEFAULT:
3531 rc = cil_resolve_selinuxuser(node, args);
3532 break;
3533 case CIL_ROLEATTRIBUTESET:
3534 rc = cil_resolve_roleattributeset(node, args);
3535 break;
3536 case CIL_ROLETYPE:
3537 rc = cil_resolve_roletype(node, args);
3538 break;
3539 case CIL_ROLETRANSITION:
3540 rc = cil_resolve_roletransition(node, args);
3541 break;
3542 case CIL_ROLEALLOW:
3543 rc = cil_resolve_roleallow(node, args);
3544 break;
3545 case CIL_ROLEBOUNDS:
3546 rc = cil_resolve_bounds(node, args, CIL_ROLE, CIL_ROLEATTRIBUTE);
3547 break;
3548 case CIL_LEVEL:
3549 rc = cil_resolve_level(node, (struct cil_level*)node->data, args);
3550 break;
3551 case CIL_LEVELRANGE:
3552 rc = cil_resolve_levelrange(node, (struct cil_levelrange*)node->data, args);
3553 break;
3554 case CIL_CONSTRAIN:
3555 rc = cil_resolve_constrain(node, args);
3556 break;
3557 case CIL_MLSCONSTRAIN:
3558 rc = cil_resolve_constrain(node, args);
3559 break;
3560 case CIL_VALIDATETRANS:
3561 case CIL_MLSVALIDATETRANS:
3562 rc = cil_resolve_validatetrans(node, args);
3563 break;
3564 case CIL_CONTEXT:
3565 rc = cil_resolve_context(node, (struct cil_context*)node->data, args);
3566 break;
3567 case CIL_FILECON:
3568 rc = cil_resolve_filecon(node, args);
3569 break;
3570 case CIL_PORTCON:
3571 rc = cil_resolve_portcon(node, args);
3572 break;
3573 case CIL_NODECON:
3574 rc = cil_resolve_nodecon(node, args);
3575 break;
3576 case CIL_GENFSCON:
3577 rc = cil_resolve_genfscon(node, args);
3578 break;
3579 case CIL_NETIFCON:
3580 rc = cil_resolve_netifcon(node, args);
3581 break;
3582 case CIL_PIRQCON:
3583 rc = cil_resolve_pirqcon(node, args);
3584 break;
3585 case CIL_IOMEMCON:
3586 rc = cil_resolve_iomemcon(node, args);
3587 break;
3588 case CIL_IOPORTCON:
3589 rc = cil_resolve_ioportcon(node, args);
3590 break;
3591 case CIL_PCIDEVICECON:
3592 rc = cil_resolve_pcidevicecon(node, args);
3593 break;
3594 case CIL_DEVICETREECON:
3595 rc = cil_resolve_devicetreecon(node, args);
3596 break;
3597 case CIL_FSUSE:
3598 rc = cil_resolve_fsuse(node, args);
3599 break;
3600 case CIL_SIDCONTEXT:
3601 rc = cil_resolve_sidcontext(node, args);
3602 break;
3603 case CIL_DEFAULTUSER:
3604 case CIL_DEFAULTROLE:
3605 case CIL_DEFAULTTYPE:
3606 rc = cil_resolve_default(node, args);
3607 break;
3608 case CIL_DEFAULTRANGE:
3609 rc = cil_resolve_defaultrange(node, args);
3610 break;
3611 case CIL_USERATTRIBUTESET:
3612 rc = cil_resolve_userattributeset(node, args);
3613 break;
3614 default:
3615 break;
3616 }
3617 break;
3618 default:
3619 break;
3620 }
3621
3622 return rc;
3623
3624 exit:
3625 return rc;
3626 }
3627
__cil_resolve_ast_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)3628 int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
3629 {
3630 int rc = SEPOL_ERR;
3631 struct cil_args_resolve *args = extra_args;
3632 enum cil_pass pass = args->pass;
3633 struct cil_tree_node *optstack = args->optstack;
3634 struct cil_tree_node *boolif = args->boolif;
3635 struct cil_tree_node *blockstack = args->blockstack;
3636 struct cil_tree_node *macro = args->macro;
3637
3638 if (node == NULL) {
3639 goto exit;
3640 }
3641
3642 if (optstack != NULL) {
3643 if (node->flavor == CIL_TUNABLE || node->flavor == CIL_MACRO) {
3644 /* tuanbles and macros are not allowed in optionals*/
3645 cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node));
3646 rc = SEPOL_ERR;
3647 goto exit;
3648 }
3649 }
3650
3651 if (blockstack != NULL) {
3652 if (node->flavor == CIL_CAT || node->flavor == CIL_SENS) {
3653 cil_tree_log(node, CIL_ERR, "%s statement is not allowed in blocks", cil_node_to_string(node));
3654 rc = SEPOL_ERR;
3655 goto exit;
3656 }
3657 }
3658
3659 if (macro != NULL) {
3660 if (node->flavor == CIL_BLOCKINHERIT ||
3661 node->flavor == CIL_BLOCK ||
3662 node->flavor == CIL_BLOCKABSTRACT ||
3663 node->flavor == CIL_MACRO) {
3664 cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node));
3665 rc = SEPOL_ERR;
3666 goto exit;
3667 }
3668 }
3669
3670 if (boolif != NULL) {
3671 if (!(node->flavor == CIL_CONDBLOCK ||
3672 node->flavor == CIL_AVRULE ||
3673 node->flavor == CIL_TYPE_RULE ||
3674 node->flavor == CIL_CALL ||
3675 node->flavor == CIL_TUNABLEIF ||
3676 node->flavor == CIL_NAMETYPETRANSITION)) {
3677 if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
3678 cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif)", cil_node_to_string(node));
3679 } else {
3680 cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node));
3681 }
3682 rc = SEPOL_ERR;
3683 goto exit;
3684 }
3685 }
3686
3687 if (node->flavor == CIL_MACRO) {
3688 if (pass != CIL_PASS_TIF && pass != CIL_PASS_MACRO) {
3689 *finished = CIL_TREE_SKIP_HEAD;
3690 rc = SEPOL_OK;
3691 goto exit;
3692 }
3693 }
3694
3695 if (node->flavor == CIL_BLOCK && ((((struct cil_block*)node->data)->is_abstract == CIL_TRUE) && (pass > CIL_PASS_BLKABS))) {
3696 *finished = CIL_TREE_SKIP_HEAD;
3697 rc = SEPOL_OK;
3698 goto exit;
3699 }
3700
3701 rc = __cil_resolve_ast_node(node, extra_args);
3702 if (rc == SEPOL_ENOENT) {
3703 enum cil_log_level lvl = CIL_ERR;
3704
3705 if (optstack != NULL) {
3706 lvl = CIL_WARN;
3707
3708 struct cil_optional *opt = (struct cil_optional *)optstack->data;
3709 struct cil_tree_node *opt_node = opt->datum.nodes->head->data;
3710 cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name);
3711 /* disable an optional if something failed to resolve */
3712 opt->enabled = CIL_FALSE;
3713 rc = SEPOL_OK;
3714 }
3715
3716 cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
3717 goto exit;
3718 }
3719
3720 return rc;
3721
3722 exit:
3723 return rc;
3724 }
3725
__cil_resolve_ast_first_child_helper(struct cil_tree_node * current,void * extra_args)3726 int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *extra_args)
3727 {
3728 int rc = SEPOL_ERR;
3729 struct cil_args_resolve *args = extra_args;
3730 struct cil_tree_node *optstack = NULL;
3731 struct cil_tree_node *parent = NULL;
3732 struct cil_tree_node *blockstack = NULL;
3733 struct cil_tree_node *new = NULL;
3734
3735 if (current == NULL || extra_args == NULL) {
3736 goto exit;
3737 }
3738
3739 optstack = args->optstack;
3740 parent = current->parent;
3741 blockstack = args->blockstack;
3742
3743 if (parent->flavor == CIL_OPTIONAL || parent->flavor == CIL_BLOCK) {
3744 /* push this node onto a stack */
3745 cil_tree_node_init(&new);
3746
3747 new->data = parent->data;
3748 new->flavor = parent->flavor;
3749
3750 if (parent->flavor == CIL_OPTIONAL) {
3751 if (optstack != NULL) {
3752 optstack->parent = new;
3753 new->cl_head = optstack;
3754 }
3755 args->optstack = new;
3756 } else if (parent->flavor == CIL_BLOCK) {
3757 if (blockstack != NULL) {
3758 blockstack->parent = new;
3759 new->cl_head = blockstack;
3760 }
3761 args->blockstack = new;
3762 }
3763 } else if (parent->flavor == CIL_BOOLEANIF) {
3764 args->boolif = parent;
3765 } else if (parent->flavor == CIL_MACRO) {
3766 args->macro = parent;
3767 }
3768
3769 return SEPOL_OK;
3770
3771 exit:
3772 return rc;
3773
3774 }
3775
__cil_resolve_ast_last_child_helper(struct cil_tree_node * current,void * extra_args)3776 int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *extra_args)
3777 {
3778 int rc = SEPOL_ERR;
3779 struct cil_args_resolve *args = extra_args;
3780 struct cil_tree_node *parent = NULL;
3781 struct cil_tree_node *blockstack = NULL;
3782
3783 if (current == NULL || extra_args == NULL) {
3784 goto exit;
3785 }
3786
3787 parent = current->parent;
3788
3789 if (parent->flavor == CIL_MACRO) {
3790 args->macro = NULL;
3791 } else if (parent->flavor == CIL_OPTIONAL) {
3792 struct cil_tree_node *optstack;
3793
3794 if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) {
3795 *(args->changed) = CIL_TRUE;
3796 cil_tree_children_destroy(parent);
3797 }
3798
3799 /* pop off the stack */
3800 optstack = args->optstack;
3801 args->optstack = optstack->cl_head;
3802 if (optstack->cl_head) {
3803 optstack->cl_head->parent = NULL;
3804 }
3805 free(optstack);
3806 } else if (parent->flavor == CIL_BOOLEANIF) {
3807 args->boolif = NULL;
3808 } else if (parent->flavor == CIL_BLOCK) {
3809 /* pop off the stack */
3810 blockstack = args->blockstack;
3811 args->blockstack = blockstack->cl_head;
3812 if (blockstack->cl_head) {
3813 blockstack->cl_head->parent = NULL;
3814 }
3815 free(blockstack);
3816 }
3817
3818 return SEPOL_OK;
3819
3820 exit:
3821 return rc;
3822 }
3823
cil_destroy_tree_node_stack(struct cil_tree_node * curr)3824 static void cil_destroy_tree_node_stack(struct cil_tree_node *curr)
3825 {
3826 struct cil_tree_node *next;
3827 while (curr != NULL) {
3828 next = curr->cl_head;
3829 free(curr);
3830 curr = next;
3831 }
3832 }
3833
cil_resolve_ast(struct cil_db * db,struct cil_tree_node * current)3834 int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
3835 {
3836 int rc = SEPOL_ERR;
3837 struct cil_args_resolve extra_args;
3838 enum cil_pass pass = CIL_PASS_TIF;
3839 uint32_t changed = 0;
3840
3841 if (db == NULL || current == NULL) {
3842 return rc;
3843 }
3844
3845 extra_args.db = db;
3846 extra_args.pass = pass;
3847 extra_args.changed = &changed;
3848 extra_args.last_resolved_name = NULL;
3849 extra_args.optstack = NULL;
3850 extra_args.boolif= NULL;
3851 extra_args.macro = NULL;
3852 extra_args.sidorder_lists = NULL;
3853 extra_args.classorder_lists = NULL;
3854 extra_args.unordered_classorder_lists = NULL;
3855 extra_args.catorder_lists = NULL;
3856 extra_args.sensitivityorder_lists = NULL;
3857 extra_args.in_list = NULL;
3858 extra_args.blockstack = NULL;
3859
3860 cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
3861 cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
3862 cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
3863 cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
3864 cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
3865 cil_list_init(&extra_args.in_list, CIL_IN);
3866 for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) {
3867 extra_args.pass = pass;
3868 rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args);
3869 if (rc != SEPOL_OK) {
3870 cil_log(CIL_INFO, "Pass %i of resolution failed\n", pass);
3871 goto exit;
3872 }
3873
3874 if (pass == CIL_PASS_IN) {
3875 rc = cil_resolve_in_list(&extra_args);
3876 if (rc != SEPOL_OK) {
3877 goto exit;
3878 }
3879 cil_list_destroy(&extra_args.in_list, CIL_FALSE);
3880 }
3881
3882 if (pass == CIL_PASS_MISC1) {
3883 db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists, NULL);
3884 if (db->sidorder == NULL) {
3885 rc = SEPOL_ERR;
3886 goto exit;
3887 }
3888 db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists, &extra_args.unordered_classorder_lists);
3889 if (db->classorder == NULL) {
3890 rc = SEPOL_ERR;
3891 goto exit;
3892 }
3893 db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists, NULL);
3894 if (db->catorder == NULL) {
3895 rc = SEPOL_ERR;
3896 goto exit;
3897 }
3898 cil_set_cat_values(db->catorder, db);
3899 db->sensitivityorder = __cil_ordered_lists_merge_all(&extra_args.sensitivityorder_lists, NULL);
3900 if (db->sensitivityorder == NULL) {
3901 rc = SEPOL_ERR;
3902 goto exit;
3903 }
3904
3905 rc = __cil_verify_ordered(current, CIL_SID);
3906 if (rc != SEPOL_OK) {
3907 goto exit;
3908 }
3909
3910 rc = __cil_verify_ordered(current, CIL_CLASS);
3911 if (rc != SEPOL_OK) {
3912 goto exit;
3913 }
3914
3915 rc = __cil_verify_ordered(current, CIL_CAT);
3916 if (rc != SEPOL_OK) {
3917 goto exit;
3918 }
3919
3920 rc = __cil_verify_ordered(current, CIL_SENS);
3921 if (rc != SEPOL_OK) {
3922 goto exit;
3923 }
3924 }
3925
3926 if (changed && (pass > CIL_PASS_CALL1)) {
3927 /* Need to re-resolve because an optional was disabled that contained
3928 * one or more declarations. We only need to reset to the call1 pass
3929 * because things done in the preceeding passes aren't allowed in
3930 * optionals, and thus can't be disabled.
3931 * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment
3932 * it to CIL_PASS_CALL2
3933 */
3934 cil_log(CIL_INFO, "Resetting declarations\n");
3935
3936 if (pass >= CIL_PASS_MISC1) {
3937 __cil_ordered_lists_reset(&extra_args.sidorder_lists);
3938 __cil_ordered_lists_reset(&extra_args.classorder_lists);
3939 __cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
3940 __cil_ordered_lists_reset(&extra_args.catorder_lists);
3941 __cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
3942 cil_list_destroy(&db->sidorder, CIL_FALSE);
3943 cil_list_destroy(&db->classorder, CIL_FALSE);
3944 cil_list_destroy(&db->catorder, CIL_FALSE);
3945 cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
3946 }
3947
3948 pass = CIL_PASS_CALL1;
3949
3950 rc = cil_reset_ast(current);
3951 if (rc != SEPOL_OK) {
3952 cil_log(CIL_ERR, "Failed to reset declarations\n");
3953 goto exit;
3954 }
3955 }
3956
3957 /* reset the arguments */
3958 changed = 0;
3959 while (extra_args.optstack != NULL) {
3960 cil_destroy_tree_node_stack(extra_args.optstack);
3961 extra_args.optstack = NULL;
3962 }
3963 while (extra_args.blockstack!= NULL) {
3964 cil_destroy_tree_node_stack(extra_args.blockstack);
3965 extra_args.blockstack = NULL;
3966 }
3967 }
3968
3969 rc = __cil_verify_initsids(db->sidorder);
3970 if (rc != SEPOL_OK) {
3971 goto exit;
3972 }
3973
3974 rc = SEPOL_OK;
3975 exit:
3976 cil_destroy_tree_node_stack(extra_args.optstack);
3977 cil_destroy_tree_node_stack(extra_args.blockstack);
3978 __cil_ordered_lists_destroy(&extra_args.sidorder_lists);
3979 __cil_ordered_lists_destroy(&extra_args.classorder_lists);
3980 __cil_ordered_lists_destroy(&extra_args.catorder_lists);
3981 __cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists);
3982 __cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists);
3983 cil_list_destroy(&extra_args.in_list, CIL_FALSE);
3984
3985 return rc;
3986 }
3987
__cil_resolve_name_with_root(struct cil_db * db,char * name,enum cil_sym_index sym_index,struct cil_symtab_datum ** datum)3988 static int __cil_resolve_name_with_root(struct cil_db *db, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
3989 {
3990 symtab_t *symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
3991
3992 return cil_symtab_get_datum(symtab, name, datum);
3993 }
3994
__cil_resolve_name_with_parents(struct cil_tree_node * node,char * name,enum cil_sym_index sym_index,struct cil_symtab_datum ** datum)3995 static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
3996 {
3997 int rc = SEPOL_ERR;
3998 symtab_t *symtab = NULL;
3999
4000 while (node != NULL && rc != SEPOL_OK) {
4001 switch (node->flavor) {
4002 case CIL_ROOT:
4003 goto exit;
4004 break;
4005 case CIL_BLOCK:
4006 symtab = &((struct cil_block*)node->data)->symtab[sym_index];
4007 rc = cil_symtab_get_datum(symtab, name, datum);
4008 break;
4009 case CIL_BLOCKINHERIT: {
4010 struct cil_blockinherit *inherit = node->data;
4011 rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum);
4012 if (rc != SEPOL_OK) {
4013 /* Continue search in original block's parent */
4014 rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum);
4015 goto exit;
4016 }
4017 }
4018 break;
4019 case CIL_MACRO: {
4020 struct cil_macro *macro = node->data;
4021 symtab = ¯o->symtab[sym_index];
4022 rc = cil_symtab_get_datum(symtab, name, datum);
4023 }
4024 break;
4025 case CIL_CALL: {
4026 struct cil_call *call = node->data;
4027 rc = cil_resolve_name_call_args(call, name, sym_index, datum);
4028 if (rc != SEPOL_OK) {
4029 /* Continue search in macro's parent */
4030 rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
4031 }
4032 }
4033 break;
4034 case CIL_IN:
4035 /* In block symtabs only exist before resolving the AST */
4036 case CIL_CONDBLOCK:
4037 /* Cond block symtabs only exist before resolving the AST */
4038 default:
4039 break;
4040 }
4041
4042 node = node->parent;
4043 }
4044
4045 exit:
4046 return rc;
4047 }
4048
__cil_resolve_name_helper(struct cil_db * db,struct cil_tree_node * node,char * name,enum cil_sym_index sym_index,struct cil_symtab_datum ** datum)4049 static int __cil_resolve_name_helper(struct cil_db *db, struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum)
4050 {
4051 int rc = SEPOL_ERR;
4052
4053 rc = __cil_resolve_name_with_parents(node, name, sym_index, datum);
4054 if (rc != SEPOL_OK) {
4055 rc = __cil_resolve_name_with_root(db, name, sym_index, datum);
4056 }
4057 return rc;
4058 }
4059
cil_resolve_name(struct cil_tree_node * ast_node,char * name,enum cil_sym_index sym_index,void * extra_args,struct cil_symtab_datum ** datum)4060 int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum)
4061 {
4062 int rc = SEPOL_ERR;
4063 struct cil_args_resolve *args = extra_args;
4064 struct cil_db *db = args->db;
4065 struct cil_tree_node *node = NULL;
4066
4067 if (name == NULL) {
4068 cil_log(CIL_ERR, "Invalid call to cil_resolve_name\n");
4069 goto exit;
4070 }
4071
4072 *datum = NULL;
4073
4074 if (strchr(name,'.') == NULL) {
4075 /* No '.' in name */
4076 rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum);
4077 if (rc != SEPOL_OK) {
4078 goto exit;
4079 }
4080 } else {
4081 char *sp = NULL;
4082 char *name_dup = cil_strdup(name);
4083 char *current = strtok_r(name_dup, ".", &sp);
4084 char *next = strtok_r(NULL, ".", &sp);
4085 symtab_t *symtab = NULL;
4086
4087 if (current == NULL) {
4088 /* Only dots */
4089 cil_tree_log(ast_node, CIL_ERR, "Invalid name %s", name);
4090 free(name_dup);
4091 goto exit;
4092 }
4093
4094 node = ast_node;
4095 if (*name == '.') {
4096 /* Leading '.' */
4097 symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_BLOCKS];
4098 } else {
4099 rc = __cil_resolve_name_helper(db, node->parent, current, CIL_SYM_BLOCKS, datum);
4100 if (rc != SEPOL_OK) {
4101 free(name_dup);
4102 goto exit;
4103 }
4104 symtab = (*datum)->symtab;
4105 }
4106 /* Keep looking up blocks by name until only last part of name remains */
4107 while (next != NULL) {
4108 rc = cil_symtab_get_datum(symtab, current, datum);
4109 if (rc != SEPOL_OK) {
4110 free(name_dup);
4111 goto exit;
4112 }
4113 node = NODE(*datum);
4114 if (node->flavor == CIL_BLOCK) {
4115 symtab = &((struct cil_block*)node->data)->symtab[CIL_SYM_BLOCKS];
4116 } else {
4117 if (ast_node->flavor != CIL_IN) {
4118 cil_log(CIL_WARN, "Can only use %s name for name resolution in \"in\" blocks\n", cil_node_to_string(node));
4119 free(name_dup);
4120 rc = SEPOL_ERR;
4121 goto exit;
4122 }
4123 if (node->flavor == CIL_MACRO) {
4124 struct cil_macro *macro = node->data;
4125 symtab = ¯o->symtab[sym_index];
4126 } else {
4127 /* optional */
4128 symtab = (*datum)->symtab;
4129 }
4130 }
4131 current = next;
4132 next = strtok_r(NULL, ".", &sp);
4133 }
4134 symtab = &(symtab[sym_index]);
4135 rc = cil_symtab_get_datum(symtab, current, datum);
4136 free(name_dup);
4137 if (rc != SEPOL_OK) {
4138 goto exit;
4139 }
4140 }
4141
4142 rc = SEPOL_OK;
4143
4144 exit:
4145 if (rc != SEPOL_OK) {
4146 *datum = NULL;
4147 }
4148
4149 if (*datum != NULL) {
4150 /* If this datum is an alias, then return the actual node
4151 * This depends on aliases already being processed
4152 */
4153 node = NODE(*datum);
4154 if (node->flavor == CIL_TYPEALIAS || node->flavor == CIL_SENSALIAS
4155 || node->flavor == CIL_CATALIAS) {
4156 struct cil_alias *alias = (struct cil_alias *)(*datum);
4157 if (alias->actual) {
4158 *datum = alias->actual;
4159 }
4160 }
4161 }
4162
4163 args->last_resolved_name = name;
4164
4165 return rc;
4166 }
4167