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