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