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