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