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 #include <stdint.h>
34 #include <unistd.h>
35
36 #include <sepol/policydb/conditional.h>
37 #include <sepol/errcodes.h>
38
39 #include "cil_internal.h"
40 #include "cil_flavor.h"
41 #include "cil_log.h"
42 #include "cil_mem.h"
43 #include "cil_tree.h"
44 #include "cil_list.h"
45 #include "cil_post.h"
46 #include "cil_policy.h"
47 #include "cil_verify.h"
48 #include "cil_symtab.h"
49
50 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
51 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
52
cil_verify_is_list(struct cil_list * list,enum cil_flavor flavor)53 static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
54 {
55 struct cil_list_item *curr;
56
57 cil_list_for_each(curr, list) {
58 switch (curr->flavor) {
59 case CIL_LIST:
60 return CIL_FALSE;
61 break;
62 case CIL_OP:
63 return CIL_FALSE;
64 break;
65 default:
66 if (flavor == CIL_CAT) {
67 struct cil_symtab_datum *d = curr->data;
68 struct cil_tree_node *n = d->nodes->head->data;
69 if (n->flavor == CIL_CATSET) {
70 return CIL_FALSE;
71 }
72 }
73 break;
74 }
75 }
76 return CIL_TRUE;
77 }
78
cil_post_fc_fill_data(struct fc_data * fc,char * path)79 void cil_post_fc_fill_data(struct fc_data *fc, char *path)
80 {
81 int c = 0;
82 fc->meta = 0;
83 fc->stem_len = 0;
84 fc->str_len = 0;
85
86 while (path[c] != '\0') {
87 switch (path[c]) {
88 case '.':
89 case '^':
90 case '$':
91 case '?':
92 case '*':
93 case '+':
94 case '|':
95 case '[':
96 case '(':
97 case '{':
98 fc->meta = 1;
99 break;
100 case '\\':
101 c++;
102 default:
103 if (!fc->meta) {
104 fc->stem_len++;
105 }
106 break;
107 }
108 fc->str_len++;
109 c++;
110 }
111 }
112
cil_post_filecon_compare(const void * a,const void * b)113 int cil_post_filecon_compare(const void *a, const void *b)
114 {
115 int rc = 0;
116 struct cil_filecon *a_filecon = *(struct cil_filecon**)a;
117 struct cil_filecon *b_filecon = *(struct cil_filecon**)b;
118 struct fc_data *a_data = cil_malloc(sizeof(*a_data));
119 struct fc_data *b_data = cil_malloc(sizeof(*b_data));
120 char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1);
121 a_path[0] = '\0';
122 char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1);
123 b_path[0] = '\0';
124 strcat(a_path, a_filecon->path_str);
125 strcat(b_path, b_filecon->path_str);
126 cil_post_fc_fill_data(a_data, a_path);
127 cil_post_fc_fill_data(b_data, b_path);
128 if (a_data->meta && !b_data->meta) {
129 rc = -1;
130 } else if (b_data->meta && !a_data->meta) {
131 rc = 1;
132 } else if (a_data->stem_len < b_data->stem_len) {
133 rc = -1;
134 } else if (b_data->stem_len < a_data->stem_len) {
135 rc = 1;
136 } else if (a_data->str_len < b_data->str_len) {
137 rc = -1;
138 } else if (b_data->str_len < a_data->str_len) {
139 rc = 1;
140 } else if (a_filecon->type < b_filecon->type) {
141 rc = -1;
142 } else if (b_filecon->type < a_filecon->type) {
143 rc = 1;
144 }
145
146 free(a_path);
147 free(b_path);
148 free(a_data);
149 free(b_data);
150
151 return rc;
152 }
153
cil_post_portcon_compare(const void * a,const void * b)154 int cil_post_portcon_compare(const void *a, const void *b)
155 {
156 int rc = SEPOL_ERR;
157 struct cil_portcon *aportcon = *(struct cil_portcon**)a;
158 struct cil_portcon *bportcon = *(struct cil_portcon**)b;
159
160 rc = (aportcon->port_high - aportcon->port_low)
161 - (bportcon->port_high - bportcon->port_low);
162 if (rc == 0) {
163 if (aportcon->port_low < bportcon->port_low) {
164 rc = -1;
165 } else if (bportcon->port_low < aportcon->port_low) {
166 rc = 1;
167 }
168 }
169
170 return rc;
171 }
172
cil_post_genfscon_compare(const void * a,const void * b)173 int cil_post_genfscon_compare(const void *a, const void *b)
174 {
175 int rc = SEPOL_ERR;
176 struct cil_genfscon *agenfscon = *(struct cil_genfscon**)a;
177 struct cil_genfscon *bgenfscon = *(struct cil_genfscon**)b;
178
179 rc = strcmp(agenfscon->fs_str, bgenfscon->fs_str);
180 if (rc == 0) {
181 rc = strcmp(agenfscon->path_str, bgenfscon->path_str);
182 }
183
184 return rc;
185 }
186
cil_post_netifcon_compare(const void * a,const void * b)187 int cil_post_netifcon_compare(const void *a, const void *b)
188 {
189 struct cil_netifcon *anetifcon = *(struct cil_netifcon**)a;
190 struct cil_netifcon *bnetifcon = *(struct cil_netifcon**)b;
191
192 return strcmp(anetifcon->interface_str, bnetifcon->interface_str);
193 }
194
cil_post_nodecon_compare(const void * a,const void * b)195 int cil_post_nodecon_compare(const void *a, const void *b)
196 {
197 struct cil_nodecon *anodecon;
198 struct cil_nodecon *bnodecon;
199 anodecon = *(struct cil_nodecon**)a;
200 bnodecon = *(struct cil_nodecon**)b;
201
202 /* sort ipv4 before ipv6 */
203 if (anodecon->addr->family != bnodecon->addr->family) {
204 if (anodecon->addr->family == AF_INET) {
205 return -1;
206 } else {
207 return 1;
208 }
209 }
210
211 /* most specific netmask goes first, then order by ip addr */
212 if (anodecon->addr->family == AF_INET) {
213 int rc = memcmp(&anodecon->mask->ip.v4, &bnodecon->mask->ip.v4, sizeof(anodecon->mask->ip.v4));
214 if (rc != 0) {
215 return -1 * rc;
216 }
217 return memcmp(&anodecon->addr->ip.v4, &bnodecon->addr->ip.v4, sizeof(anodecon->addr->ip.v4));
218 } else {
219 int rc = memcmp(&anodecon->mask->ip.v6, &bnodecon->mask->ip.v6, sizeof(anodecon->mask->ip.v6));
220 if (rc != 0) {
221 return -1 * rc;
222 }
223 return memcmp(&anodecon->addr->ip.v6, &bnodecon->addr->ip.v6, sizeof(anodecon->addr->ip.v6));
224 }
225 }
226
cil_post_pirqcon_compare(const void * a,const void * b)227 int cil_post_pirqcon_compare(const void *a, const void *b)
228 {
229 int rc = SEPOL_ERR;
230 struct cil_pirqcon *apirqcon = *(struct cil_pirqcon**)a;
231 struct cil_pirqcon *bpirqcon = *(struct cil_pirqcon**)b;
232
233 if (apirqcon->pirq < bpirqcon->pirq) {
234 rc = -1;
235 } else if (bpirqcon->pirq < apirqcon->pirq) {
236 rc = 1;
237 } else {
238 rc = 0;
239 }
240
241 return rc;
242 }
243
cil_post_iomemcon_compare(const void * a,const void * b)244 int cil_post_iomemcon_compare(const void *a, const void *b)
245 {
246 int rc = SEPOL_ERR;
247 struct cil_iomemcon *aiomemcon = *(struct cil_iomemcon**)a;
248 struct cil_iomemcon *biomemcon = *(struct cil_iomemcon**)b;
249
250 rc = (aiomemcon->iomem_high - aiomemcon->iomem_low)
251 - (biomemcon->iomem_high - biomemcon->iomem_low);
252 if (rc == 0) {
253 if (aiomemcon->iomem_low < biomemcon->iomem_low) {
254 rc = -1;
255 } else if (biomemcon->iomem_low < aiomemcon->iomem_low) {
256 rc = 1;
257 }
258 }
259
260 return rc;
261 }
262
cil_post_ioportcon_compare(const void * a,const void * b)263 int cil_post_ioportcon_compare(const void *a, const void *b)
264 {
265 int rc = SEPOL_ERR;
266 struct cil_ioportcon *aioportcon = *(struct cil_ioportcon**)a;
267 struct cil_ioportcon *bioportcon = *(struct cil_ioportcon**)b;
268
269 rc = (aioportcon->ioport_high - aioportcon->ioport_low)
270 - (bioportcon->ioport_high - bioportcon->ioport_low);
271 if (rc == 0) {
272 if (aioportcon->ioport_low < bioportcon->ioport_low) {
273 rc = -1;
274 } else if (bioportcon->ioport_low < aioportcon->ioport_low) {
275 rc = 1;
276 }
277 }
278
279 return rc;
280 }
281
cil_post_pcidevicecon_compare(const void * a,const void * b)282 int cil_post_pcidevicecon_compare(const void *a, const void *b)
283 {
284 int rc = SEPOL_ERR;
285 struct cil_pcidevicecon *apcidevicecon = *(struct cil_pcidevicecon**)a;
286 struct cil_pcidevicecon *bpcidevicecon = *(struct cil_pcidevicecon**)b;
287
288 if (apcidevicecon->dev < bpcidevicecon->dev) {
289 rc = -1;
290 } else if (bpcidevicecon->dev < apcidevicecon->dev) {
291 rc = 1;
292 } else {
293 rc = 0;
294 }
295
296 return rc;
297 }
298
cil_post_devicetreecon_compare(const void * a,const void * b)299 int cil_post_devicetreecon_compare(const void *a, const void *b)
300 {
301 int rc = SEPOL_ERR;
302 struct cil_devicetreecon *adevicetreecon = *(struct cil_devicetreecon**)a;
303 struct cil_devicetreecon *bdevicetreecon = *(struct cil_devicetreecon**)b;
304
305 rc = strcmp(adevicetreecon->path, bdevicetreecon->path);
306
307 return rc;
308 }
309
cil_post_fsuse_compare(const void * a,const void * b)310 int cil_post_fsuse_compare(const void *a, const void *b)
311 {
312 int rc;
313 struct cil_fsuse *afsuse;
314 struct cil_fsuse *bfsuse;
315 afsuse = *(struct cil_fsuse**)a;
316 bfsuse = *(struct cil_fsuse**)b;
317 if (afsuse->type < bfsuse->type) {
318 rc = -1;
319 } else if (bfsuse->type < afsuse->type) {
320 rc = 1;
321 } else {
322 rc = strcmp(afsuse->fs_str, bfsuse->fs_str);
323 }
324 return rc;
325 }
326
__cil_post_db_count_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)327 static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
328 {
329 struct cil_db *db = extra_args;
330
331 switch(node->flavor) {
332 case CIL_BLOCK: {
333 struct cil_block *blk = node->data;
334 if (blk->is_abstract == CIL_TRUE) {
335 *finished = CIL_TREE_SKIP_HEAD;
336 }
337 break;
338 }
339 case CIL_MACRO:
340 *finished = CIL_TREE_SKIP_HEAD;
341 break;
342 case CIL_TYPE: {
343 struct cil_type *type = node->data;
344 if (type->datum.nodes->head->data == node) {
345 // multiple AST nodes can point to the same cil_type data (like if
346 // copied from a macro). This check ensures we only count the
347 // duplicates once
348 type->value = db->num_types;
349 db->num_types++;
350 }
351 break;
352 }
353 case CIL_ROLE: {
354 struct cil_role *role = node->data;
355 if (role->datum.nodes->head->data == node) {
356 // multiple AST nodes can point to the same cil_role data (like if
357 // copied from a macro). This check ensures we only count the
358 // duplicates once
359 role->value = db->num_roles;
360 db->num_roles++;
361 }
362 break;
363 }
364 case CIL_NETIFCON:
365 db->netifcon->count++;
366 break;
367 case CIL_GENFSCON:
368 db->genfscon->count++;
369 break;
370 case CIL_FILECON:
371 db->filecon->count++;
372 break;
373 case CIL_NODECON:
374 db->nodecon->count++;
375 break;
376 case CIL_PORTCON:
377 db->portcon->count++;
378 break;
379 case CIL_PIRQCON:
380 db->pirqcon->count++;
381 break;
382 case CIL_IOMEMCON:
383 db->iomemcon->count++;
384 break;
385 case CIL_IOPORTCON:
386 db->ioportcon->count++;
387 break;
388 case CIL_PCIDEVICECON:
389 db->pcidevicecon->count++;
390 break;
391 case CIL_DEVICETREECON:
392 db->devicetreecon->count++;
393 break;
394 case CIL_FSUSE:
395 db->fsuse->count++;
396 break;
397 default:
398 break;
399 }
400
401 return SEPOL_OK;
402 }
403
__cil_post_db_array_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)404 static int __cil_post_db_array_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
405 {
406 struct cil_db *db = extra_args;
407
408 switch(node->flavor) {
409 case CIL_BLOCK: {
410 struct cil_block *blk = node->data;
411 if (blk->is_abstract == CIL_TRUE) {
412 *finished = CIL_TREE_SKIP_HEAD;
413 }
414 break;
415 }
416 case CIL_MACRO:
417 *finished = CIL_TREE_SKIP_HEAD;
418 break;
419 case CIL_TYPE: {
420 struct cil_type *type = node->data;
421 if (db->val_to_type == NULL) {
422 db->val_to_type = cil_malloc(sizeof(*db->val_to_type) * db->num_types);
423 }
424 db->val_to_type[type->value] = type;
425 break;
426 }
427 case CIL_ROLE: {
428 struct cil_role *role = node->data;
429 if (db->val_to_role == NULL) {
430 db->val_to_role = cil_malloc(sizeof(*db->val_to_role) * db->num_roles);
431 }
432 db->val_to_role[role->value] = role;
433 break;
434 }
435 case CIL_USERPREFIX: {
436 cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data);
437 break;
438 }
439 case CIL_SELINUXUSER: {
440 cil_list_prepend(db->selinuxusers, CIL_SELINUXUSER, node->data);
441 break;
442 }
443 case CIL_SELINUXUSERDEFAULT: {
444 cil_list_append(db->selinuxusers, CIL_SELINUXUSERDEFAULT, node->data);
445 break;
446 }
447 case CIL_NETIFCON: {
448 struct cil_sort *sort = db->netifcon;
449 uint32_t count = sort->count;
450 uint32_t i = sort->index;
451 if (sort->array == NULL) {
452 sort->array = cil_malloc(sizeof(*sort->array)*count);
453 }
454 sort->array[i] = node->data;
455 sort->index++;
456 break;
457 }
458 case CIL_FSUSE: {
459 struct cil_sort *sort = db->fsuse;
460 uint32_t count = sort->count;
461 uint32_t i = sort->index;
462 if (sort->array == NULL) {
463 sort->array = cil_malloc(sizeof(*sort->array)*count);
464 }
465 sort->array[i] = node->data;
466 sort->index++;
467 break;
468 }
469 case CIL_GENFSCON: {
470 struct cil_sort *sort = db->genfscon;
471 uint32_t count = sort->count;
472 uint32_t i = sort->index;
473 if (sort->array == NULL) {
474 sort->array = cil_malloc(sizeof(*sort->array)*count);
475 }
476 sort->array[i] = node->data;
477 sort->index++;
478 break;
479 }
480 case CIL_FILECON: {
481 struct cil_sort *sort = db->filecon;
482 uint32_t count = sort->count;
483 uint32_t i = sort->index;
484 if (sort->array == NULL) {
485 sort->array = cil_malloc(sizeof(*sort->array)*count);
486 }
487 sort->array[i] = node->data;
488 sort->index++;
489 break;
490 }
491 case CIL_NODECON: {
492 struct cil_sort *sort = db->nodecon;
493 uint32_t count = sort->count;
494 uint32_t i = sort->index;
495 if (sort->array == NULL) {
496 sort->array = cil_malloc(sizeof(*sort->array)*count);
497 }
498 sort->array[i] = node->data;
499 sort->index++;
500 break;
501 }
502 case CIL_PORTCON: {
503 struct cil_sort *sort = db->portcon;
504 uint32_t count = sort->count;
505 uint32_t i = sort->index;
506 if (sort->array == NULL) {
507 sort->array = cil_malloc(sizeof(*sort->array)*count);
508 }
509 sort->array[i] = node->data;
510 sort->index++;
511 break;
512 }
513 case CIL_PIRQCON: {
514 struct cil_sort *sort = db->pirqcon;
515 uint32_t count = sort->count;
516 uint32_t i = sort->index;
517 if (sort->array == NULL) {
518 sort->array = cil_malloc(sizeof(*sort->array)*count);
519 }
520 sort->array[i] = node->data;
521 sort->index++;
522 break;
523 }
524 case CIL_IOMEMCON: {
525 struct cil_sort *sort = db->iomemcon;
526 uint32_t count = sort->count;
527 uint32_t i = sort->index;
528 if (sort->array == NULL) {
529 sort->array = cil_malloc(sizeof(*sort->array)*count);
530 }
531 sort->array[i] = node->data;
532 sort->index++;
533 break;
534 }
535 case CIL_IOPORTCON: {
536 struct cil_sort *sort = db->ioportcon;
537 uint32_t count = sort->count;
538 uint32_t i = sort->index;
539 if (sort->array == NULL) {
540 sort->array = cil_malloc(sizeof(*sort->array)*count);
541 }
542 sort->array[i] = node->data;
543 sort->index++;
544 break;
545 }
546 case CIL_PCIDEVICECON: {
547 struct cil_sort *sort = db->pcidevicecon;
548 uint32_t count = sort->count;
549 uint32_t i = sort->index;
550 if (sort->array == NULL) {
551 sort->array = cil_malloc(sizeof(*sort->array)*count);
552 }
553 sort->array[i] = node->data;
554 sort->index++;
555 break;
556 }
557 case CIL_DEVICETREECON: {
558 struct cil_sort *sort = db->devicetreecon;
559 uint32_t count = sort->count;
560 uint32_t i = sort->index;
561 if (sort->array == NULL) {
562 sort->array = cil_malloc(sizeof(*sort->array)*count);
563 }
564 sort->array[i] = node->data;
565 sort->index++;
566 break;
567 }
568 default:
569 break;
570 }
571
572 return SEPOL_OK;
573 }
574
__evaluate_type_expression(struct cil_typeattribute * attr,struct cil_db * db)575 static int __evaluate_type_expression(struct cil_typeattribute *attr, struct cil_db *db)
576 {
577 int rc;
578
579 attr->types = cil_malloc(sizeof(*attr->types));
580 rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->types, db->num_types, db);
581 if (rc != SEPOL_OK) {
582 cil_log(CIL_ERR, "Failed to expand type attribute to bitmap\n");
583 ebitmap_destroy(attr->types);
584 free(attr->types);
585 attr->types = NULL;
586 }
587 return rc;
588 }
589
__cil_type_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)590 static int __cil_type_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
591 {
592 int rc = SEPOL_ERR;
593 struct cil_tree_node *node = datum->nodes->head->data;
594
595 ebitmap_init(bitmap);
596
597 if (node->flavor == CIL_TYPEATTRIBUTE) {
598 struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
599 if (attr->types == NULL) {
600 rc = __evaluate_type_expression(attr, db);
601 if (rc != SEPOL_OK) goto exit;
602 }
603 ebitmap_union(bitmap, attr->types);
604 } else if (node->flavor == CIL_TYPEALIAS) {
605 struct cil_alias *alias = (struct cil_alias *)datum;
606 struct cil_type *type = alias->actual;
607 if (ebitmap_set_bit(bitmap, type->value, 1)) {
608 cil_log(CIL_ERR, "Failed to set type bit\n");
609 ebitmap_destroy(bitmap);
610 goto exit;
611 }
612 } else {
613 struct cil_type *type = (struct cil_type *)datum;
614 if (ebitmap_set_bit(bitmap, type->value, 1)) {
615 cil_log(CIL_ERR, "Failed to set type bit\n");
616 ebitmap_destroy(bitmap);
617 goto exit;
618 }
619 }
620
621 return SEPOL_OK;
622
623 exit:
624 return rc;
625 }
626
__evaluate_role_expression(struct cil_roleattribute * attr,struct cil_db * db)627 static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db)
628 {
629 int rc;
630
631 attr->roles = cil_malloc(sizeof(*attr->roles));
632 rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->roles, db->num_roles, db);
633 if (rc != SEPOL_OK) {
634 cil_log(CIL_ERR, "Failed to expand role attribute to bitmap\n");
635 ebitmap_destroy(attr->roles);
636 free(attr->roles);
637 attr->roles = NULL;
638 }
639 return rc;
640 }
641
__cil_role_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)642 static int __cil_role_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
643 {
644 int rc = SEPOL_ERR;
645 struct cil_tree_node *node = datum->nodes->head->data;
646
647 ebitmap_init(bitmap);
648
649 if (node->flavor == CIL_ROLEATTRIBUTE) {
650 struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
651 if (attr->roles == NULL) {
652 rc = __evaluate_role_expression(attr, db);
653 if (rc != SEPOL_OK) goto exit;
654 }
655 ebitmap_union(bitmap, attr->roles);
656 } else {
657 struct cil_role *role = (struct cil_role *)datum;
658 if (ebitmap_set_bit(bitmap, role->value, 1)) {
659 cil_log(CIL_ERR, "Failed to set role bit\n");
660 ebitmap_destroy(bitmap);
661 goto exit;
662 }
663 }
664
665 return SEPOL_OK;
666
667 exit:
668 return rc;
669 }
670
__cil_perm_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)671 static int __cil_perm_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
672 {
673 struct cil_perm *perm = (struct cil_perm *)datum;
674 unsigned int value = perm->value;
675
676 ebitmap_init(bitmap);
677 if (ebitmap_set_bit(bitmap, value, 1)) {
678 cil_log(CIL_INFO, "Failed to set perm bit\n");
679 ebitmap_destroy(bitmap);
680 return SEPOL_ERR;
681 }
682
683 return SEPOL_OK;
684 }
685
__evaluate_cat_expression(struct cil_cats * cats,struct cil_db * db)686 static int __evaluate_cat_expression(struct cil_cats *cats, struct cil_db *db)
687 {
688 int rc = SEPOL_ERR;
689 ebitmap_t bitmap;
690 struct cil_list *new;
691 struct cil_list_item *curr;
692
693 if (cats->evaluated == CIL_TRUE) {
694 return SEPOL_OK;
695 }
696
697 if (cil_verify_is_list(cats->datum_expr, CIL_CAT)) {
698 return SEPOL_OK;
699 }
700
701 ebitmap_init(&bitmap);
702 rc = __cil_expr_to_bitmap(cats->datum_expr, &bitmap, db->num_cats, db);
703 if (rc != SEPOL_OK) {
704 cil_log(CIL_ERR, "Failed to expand category expression to bitmap\n");
705 ebitmap_destroy(&bitmap);
706 goto exit;
707 }
708
709 cil_list_init(&new, CIL_CAT);
710
711 cil_list_for_each(curr, db->catorder) {
712 struct cil_cat *cat = curr->data;
713 if (ebitmap_get_bit(&bitmap, cat->value)) {
714 cil_list_append(new, CIL_DATUM, cat);
715 }
716 }
717
718 ebitmap_destroy(&bitmap);
719 cil_list_destroy(&cats->datum_expr, CIL_FALSE);
720 if (new->head != NULL) {
721 cats->datum_expr = new;
722 } else {
723 /* empty list */
724 cil_list_destroy(&new, CIL_FALSE);
725 cats->datum_expr = NULL;
726 }
727
728 cats->evaluated = CIL_TRUE;
729
730 return SEPOL_OK;
731
732 exit:
733 return rc;
734 }
735
__cil_cat_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)736 static int __cil_cat_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
737 {
738 int rc = SEPOL_ERR;
739 struct cil_tree_node *node = datum->nodes->head->data;
740
741 ebitmap_init(bitmap);
742
743 if (node->flavor == CIL_CATSET) {
744 struct cil_catset *catset = (struct cil_catset *)datum;
745 struct cil_list_item *curr;
746 if (catset->cats->evaluated == CIL_FALSE) {
747 rc = __evaluate_cat_expression(catset->cats, db);
748 if (rc != SEPOL_OK) goto exit;
749 }
750 for (curr = catset->cats->datum_expr->head; curr; curr = curr->next) {
751 struct cil_cat *cat = (struct cil_cat *)curr->data;
752 if (ebitmap_set_bit(bitmap, cat->value, 1)) {
753 cil_log(CIL_ERR, "Failed to set cat bit\n");
754 ebitmap_destroy(bitmap);
755 goto exit;
756 }
757 }
758 } else if (node->flavor == CIL_CATALIAS) {
759 struct cil_alias *alias = (struct cil_alias *)datum;
760 struct cil_cat *cat = alias->actual;
761 if (ebitmap_set_bit(bitmap, cat->value, 1)) {
762 cil_log(CIL_ERR, "Failed to set cat bit\n");
763 ebitmap_destroy(bitmap);
764 goto exit;
765 }
766 } else {
767 struct cil_cat *cat = (struct cil_cat *)datum;
768 if (ebitmap_set_bit(bitmap, cat->value, 1)) {
769 cil_log(CIL_ERR, "Failed to set cat bit\n");
770 ebitmap_destroy(bitmap);
771 goto exit;
772 }
773 }
774
775 return SEPOL_OK;
776
777 exit:
778 return rc;
779 }
780
__cil_expr_range_to_bitmap_helper(struct cil_list_item * i1,struct cil_list_item * i2,ebitmap_t * bitmap)781 static int __cil_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
782 {
783 int rc = SEPOL_ERR;
784 struct cil_symtab_datum *d1 = i1->data;
785 struct cil_symtab_datum *d2 = i2->data;
786 struct cil_tree_node *n1 = d1->nodes->head->data;
787 struct cil_tree_node *n2 = d2->nodes->head->data;
788 struct cil_cat *c1 = (struct cil_cat *)d1;
789 struct cil_cat *c2 = (struct cil_cat *)d2;
790 int i;
791
792 if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) {
793 cil_log(CIL_ERR, "Category sets cannont be used in a category range\n");
794 goto exit;
795 }
796
797 if (n1->flavor == CIL_CATALIAS) {
798 struct cil_alias *alias = (struct cil_alias *)d1;
799 c1 = alias->actual;
800 }
801
802 if (n2->flavor == CIL_CATALIAS) {
803 struct cil_alias *alias = (struct cil_alias *)d2;
804 c2 = alias->actual;
805 }
806
807 for (i = c1->value; i <= c2->value; i++) {
808 if (ebitmap_set_bit(bitmap, i, 1)) {
809 cil_log(CIL_ERR, "Failed to set cat bit\n");
810 ebitmap_destroy(bitmap);
811 goto exit;
812 }
813 }
814
815 return SEPOL_OK;
816
817 exit:
818 return rc;
819 }
820
__cil_expr_to_bitmap_helper(struct cil_list_item * curr,enum cil_flavor flavor,ebitmap_t * bitmap,int max,struct cil_db * db)821 static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flavor flavor, ebitmap_t *bitmap, int max, struct cil_db *db)
822 {
823 int rc = SEPOL_ERR;
824
825 if (curr->flavor == CIL_DATUM) {
826 switch (flavor) {
827 case CIL_TYPE:
828 rc = __cil_type_to_bitmap(curr->data, bitmap, db);
829 break;
830 case CIL_ROLE:
831 rc = __cil_role_to_bitmap(curr->data, bitmap, db);
832 break;
833 case CIL_PERM:
834 rc = __cil_perm_to_bitmap(curr->data, bitmap, db);
835 break;
836 case CIL_CAT:
837 rc = __cil_cat_to_bitmap(curr->data, bitmap, db);
838 break;
839 default:
840 rc = SEPOL_ERR;
841 }
842 } else if (curr->flavor == CIL_LIST) {
843 struct cil_list *l = curr->data;
844 ebitmap_init(bitmap);
845 rc = __cil_expr_to_bitmap(l, bitmap, max, db);
846 if (rc != SEPOL_OK) {
847 ebitmap_destroy(bitmap);
848 }
849 }
850
851 return rc;
852 }
853
__cil_expr_to_bitmap(struct cil_list * expr,ebitmap_t * out,int max,struct cil_db * db)854 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db)
855 {
856 int rc = SEPOL_ERR;
857 struct cil_list_item *curr;
858 enum cil_flavor flavor;
859 ebitmap_t tmp, b1, b2;
860
861 if (expr == NULL || expr->head == NULL) {
862 return SEPOL_OK;
863 }
864
865 curr = expr->head;
866 flavor = expr->flavor;
867
868 if (curr->flavor == CIL_OP) {
869 enum cil_flavor op = (enum cil_flavor)curr->data;
870
871 if (op == CIL_ALL) {
872 ebitmap_init(&b1); /* all zeros */
873 rc = ebitmap_not(&tmp, &b1, max);
874 ebitmap_destroy(&b1);
875 if (rc != SEPOL_OK) {
876 cil_log(CIL_INFO, "Failed to expand 'all' operator\n");
877 ebitmap_destroy(&tmp);
878 goto exit;
879 }
880 } else if (op == CIL_RANGE) {
881 if (flavor != CIL_CAT) {
882 cil_log(CIL_INFO, "Range operation only supported for categories\n");
883 rc = SEPOL_ERR;
884 goto exit;
885 }
886 ebitmap_init(&tmp);
887 rc = __cil_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
888 if (rc != SEPOL_OK) {
889 cil_log(CIL_INFO, "Failed to expand category range\n");
890 ebitmap_destroy(&tmp);
891 goto exit;
892 }
893 } else {
894 rc = __cil_expr_to_bitmap_helper(curr->next, flavor, &b1, max, db);
895 if (rc != SEPOL_OK) {
896 cil_log(CIL_INFO, "Failed to get first operand bitmap\n");
897 goto exit;
898 }
899
900 if (op == CIL_NOT) {
901 rc = ebitmap_not(&tmp, &b1, max);
902 ebitmap_destroy(&b1);
903 if (rc != SEPOL_OK) {
904 cil_log(CIL_INFO, "Failed to NOT bitmap\n");
905 ebitmap_destroy(&tmp);
906 goto exit;
907 }
908 } else {
909 rc = __cil_expr_to_bitmap_helper(curr->next->next, flavor, &b2, max, db);
910 if (rc != SEPOL_OK) {
911 cil_log(CIL_INFO, "Failed to get second operand bitmap\n");
912 goto exit;
913 }
914
915 if (op == CIL_OR) {
916 rc = ebitmap_or(&tmp, &b1, &b2);
917 } else if (op == CIL_AND) {
918 rc = ebitmap_and(&tmp, &b1, &b2);
919 } else if (op == CIL_XOR) {
920 rc = ebitmap_xor(&tmp, &b1, &b2);
921 } else {
922 rc = SEPOL_ERR;
923 }
924 ebitmap_destroy(&b1);
925 ebitmap_destroy(&b2);
926 if (rc != SEPOL_OK) {
927 cil_log(CIL_INFO, "Failed to apply operator to bitmaps\n");
928 ebitmap_destroy(&tmp);
929 goto exit;
930 }
931 }
932 }
933 } else {
934 ebitmap_init(&tmp);
935 for (;curr; curr = curr->next) {
936 rc = __cil_expr_to_bitmap_helper(curr, flavor, &b2, max, db);
937 if (rc != SEPOL_OK) {
938 cil_log(CIL_INFO, "Failed to get operand in list\n");
939 ebitmap_destroy(&tmp);
940 goto exit;
941 }
942 b1 = tmp;
943 rc = ebitmap_or(&tmp, &b1, &b2);
944 ebitmap_destroy(&b1);
945 ebitmap_destroy(&b2);
946 if (rc != SEPOL_OK) {
947 cil_log(CIL_INFO, "Failed to OR operands in list\n");
948 ebitmap_destroy(&tmp);
949 goto exit;
950 }
951
952 }
953 }
954
955 ebitmap_union(out, &tmp);
956 ebitmap_destroy(&tmp);
957
958 return SEPOL_OK;
959
960 exit:
961 return rc;
962 }
963
__cil_expr_list_to_bitmap(struct cil_list * expr_list,ebitmap_t * out,int max,struct cil_db * db)964 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db)
965 {
966 int rc = SEPOL_ERR;
967 struct cil_list_item *expr;
968
969 ebitmap_init(out);
970
971 if (expr_list == NULL) {
972 return SEPOL_OK;
973 }
974
975 cil_list_for_each(expr, expr_list) {
976 ebitmap_t bitmap;
977 struct cil_list *l = (struct cil_list *)expr->data;
978 ebitmap_init(&bitmap);
979 rc = __cil_expr_to_bitmap(l, &bitmap, max, db);
980 if (rc != SEPOL_OK) {
981 cil_log(CIL_INFO, "Failed to expand expression list to bitmap\n");
982 ebitmap_destroy(&bitmap);
983 goto exit;
984 }
985 ebitmap_union(out, &bitmap);
986 ebitmap_destroy(&bitmap);
987 }
988
989 return SEPOL_OK;
990
991 exit:
992 return SEPOL_ERR;
993 }
994
__cil_post_db_attr_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)995 static int __cil_post_db_attr_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
996 {
997 int rc = SEPOL_ERR;
998 struct cil_db *db = extra_args;
999
1000 switch (node->flavor) {
1001 case CIL_BLOCK: {
1002 struct cil_block *blk = node->data;
1003 if (blk->is_abstract == CIL_TRUE) {
1004 *finished = CIL_TREE_SKIP_HEAD;
1005 }
1006 break;
1007 }
1008 case CIL_MACRO: {
1009 *finished = CIL_TREE_SKIP_HEAD;
1010 break;
1011 }
1012 case CIL_TYPEATTRIBUTE: {
1013 struct cil_typeattribute *attr = node->data;
1014 if (attr->types == NULL) {
1015 rc = __evaluate_type_expression(attr, db);
1016 if (rc != SEPOL_OK) goto exit;
1017 }
1018 break;
1019 }
1020 case CIL_ROLEATTRIBUTE: {
1021 struct cil_roleattribute *attr = node->data;
1022 if (attr->roles == NULL) {
1023 rc = __evaluate_role_expression(attr, db);
1024 if (rc != SEPOL_OK) goto exit;
1025 }
1026 break;
1027 }
1028 default:
1029 break;
1030 }
1031
1032 return SEPOL_OK;
1033
1034 exit:
1035 return rc;
1036 }
1037
__cil_role_assign_types(struct cil_role * role,struct cil_symtab_datum * datum)1038 static int __cil_role_assign_types(struct cil_role *role, struct cil_symtab_datum *datum)
1039 {
1040 struct cil_tree_node *node = datum->nodes->head->data;
1041
1042 if (role->types == NULL) {
1043 role->types = cil_malloc(sizeof(*role->types));
1044 ebitmap_init(role->types);
1045 }
1046
1047 if (node->flavor == CIL_TYPE) {
1048 struct cil_type *type = (struct cil_type *)datum;
1049 if (ebitmap_set_bit(role->types, type->value, 1)) {
1050 cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
1051 goto exit;
1052 }
1053 } else if (node->flavor == CIL_TYPEALIAS) {
1054 struct cil_alias *alias = (struct cil_alias *)datum;
1055 struct cil_type *type = alias->actual;
1056 if (ebitmap_set_bit(role->types, type->value, 1)) {
1057 cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
1058 goto exit;
1059 }
1060 } else if (node->flavor == CIL_TYPEATTRIBUTE) {
1061 struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
1062 ebitmap_union(role->types, attr->types);
1063 }
1064
1065 return SEPOL_OK;
1066
1067 exit:
1068 return SEPOL_ERR;
1069 }
1070
__cil_post_db_roletype_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1071 static int __cil_post_db_roletype_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
1072 {
1073 int rc = SEPOL_ERR;
1074 struct cil_db *db = extra_args;
1075
1076 switch (node->flavor) {
1077 case CIL_BLOCK: {
1078 struct cil_block *blk = node->data;
1079 if (blk->is_abstract == CIL_TRUE) {
1080 *finished = CIL_TREE_SKIP_HEAD;
1081 }
1082 break;
1083 }
1084 case CIL_MACRO: {
1085 *finished = CIL_TREE_SKIP_HEAD;
1086 break;
1087 }
1088 case CIL_ROLETYPE: {
1089 struct cil_roletype *roletype = node->data;
1090 struct cil_symtab_datum *role_datum = roletype->role;
1091 struct cil_symtab_datum *type_datum = roletype->type;
1092 struct cil_tree_node *role_node = role_datum->nodes->head->data;
1093
1094 if (role_node->flavor == CIL_ROLEATTRIBUTE) {
1095 struct cil_roleattribute *attr = roletype->role;
1096 ebitmap_node_t *rnode;
1097 unsigned int i;
1098
1099 ebitmap_for_each_bit(attr->roles, rnode, i) {
1100 struct cil_role *role = NULL;
1101
1102 if (!ebitmap_get_bit(attr->roles, i)) {
1103 continue;
1104 }
1105
1106 role = db->val_to_role[i];
1107
1108 rc = __cil_role_assign_types(role, type_datum);
1109 if (rc != SEPOL_OK) {
1110 goto exit;
1111 }
1112 }
1113 } else {
1114 struct cil_role *role = roletype->role;
1115
1116 rc = __cil_role_assign_types(role, type_datum);
1117 if (rc != SEPOL_OK) {
1118 goto exit;
1119 }
1120 }
1121 break;
1122 }
1123 default:
1124 break;
1125 }
1126
1127 return SEPOL_OK;
1128 exit:
1129 cil_log(CIL_INFO, "cil_post_db_roletype_helper failed\n");
1130 return rc;
1131 }
1132
__evaluate_level_expression(struct cil_level * level,struct cil_db * db)1133 static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db)
1134 {
1135 if (level->cats != NULL) {
1136 return __evaluate_cat_expression(level->cats, db);
1137 }
1138
1139 return SEPOL_OK;
1140 }
1141
__evaluate_levelrange_expression(struct cil_levelrange * levelrange,struct cil_db * db)1142 static int __evaluate_levelrange_expression(struct cil_levelrange *levelrange, struct cil_db *db)
1143 {
1144 int rc = SEPOL_OK;
1145
1146 if (levelrange->low != NULL && levelrange->low->cats != NULL) {
1147 rc = __evaluate_cat_expression(levelrange->low->cats, db);
1148 if (rc != SEPOL_OK) {
1149 goto exit;
1150 }
1151 }
1152 if (levelrange->high != NULL && levelrange->high->cats != NULL) {
1153 rc = __evaluate_cat_expression(levelrange->high->cats, db);
1154 if (rc != SEPOL_OK) {
1155 goto exit;
1156 }
1157 }
1158
1159 exit:
1160 return rc;
1161 }
1162
__cil_post_db_cat_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1163 static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1164 {
1165 int rc = SEPOL_ERR;
1166 struct cil_db *db = extra_args;
1167
1168 switch (node->flavor) {
1169 case CIL_BLOCK: {
1170 struct cil_block *blk = node->data;
1171 if (blk->is_abstract == CIL_TRUE) {
1172 *finished = CIL_TREE_SKIP_HEAD;
1173 }
1174 break;
1175 }
1176 case CIL_MACRO: {
1177 *finished = CIL_TREE_SKIP_HEAD;
1178 break;
1179 }
1180 case CIL_CATSET: {
1181 struct cil_catset *catset = node->data;
1182 rc = __evaluate_cat_expression(catset->cats, db);
1183 if (rc != SEPOL_OK) {
1184 goto exit;
1185 }
1186 break;
1187 }
1188 case CIL_SENSCAT: {
1189 struct cil_senscat *senscat = node->data;
1190 rc = __evaluate_cat_expression(senscat->cats, db);
1191 if (rc != SEPOL_OK) {
1192 goto exit;
1193 }
1194 break;
1195 }
1196 case CIL_LEVEL: {
1197 rc = __evaluate_level_expression(node->data, db);
1198 if (rc != SEPOL_OK) {
1199 goto exit;
1200 }
1201 break;
1202 }
1203 case CIL_LEVELRANGE: {
1204 rc = __evaluate_levelrange_expression(node->data, db);
1205 if (rc != SEPOL_OK) {
1206 goto exit;
1207 }
1208 break;
1209 }
1210 case CIL_USER: {
1211 struct cil_user *user = node->data;
1212 rc = __evaluate_level_expression(user->dftlevel, db);
1213 if (rc != SEPOL_OK) {
1214 goto exit;
1215 }
1216 rc = __evaluate_levelrange_expression(user->range, db);
1217 if (rc != SEPOL_OK) {
1218 goto exit;
1219 }
1220 break;
1221 }
1222 case CIL_SELINUXUSERDEFAULT:
1223 case CIL_SELINUXUSER: {
1224 struct cil_selinuxuser *selinuxuser = node->data;
1225 rc = __evaluate_levelrange_expression(selinuxuser->range, db);
1226 if (rc != SEPOL_OK) {
1227 goto exit;
1228 }
1229 break;
1230 }
1231 case CIL_RANGETRANSITION: {
1232 struct cil_rangetransition *rangetrans = node->data;
1233 rc = __evaluate_levelrange_expression(rangetrans->range, db);
1234 if (rc != SEPOL_OK) {
1235 goto exit;
1236 }
1237 break;
1238 }
1239 case CIL_CONTEXT: {
1240 struct cil_context *context = node->data;
1241 rc = __evaluate_levelrange_expression(context->range, db);
1242 if (rc != SEPOL_OK) {
1243 goto exit;
1244 }
1245 break;
1246 }
1247 case CIL_SIDCONTEXT: {
1248 struct cil_sidcontext *sidcontext = node->data;
1249 rc = __evaluate_levelrange_expression(sidcontext->context->range, db);
1250 if (rc != SEPOL_OK) {
1251 goto exit;
1252 }
1253 break;
1254 }
1255 case CIL_FILECON: {
1256 struct cil_filecon *filecon = node->data;
1257 if (filecon->context) {
1258 rc = __evaluate_levelrange_expression(filecon->context->range, db);
1259 if (rc != SEPOL_OK) {
1260 goto exit;
1261 }
1262 }
1263 break;
1264 }
1265 case CIL_PORTCON: {
1266 struct cil_portcon *portcon = node->data;
1267 rc = __evaluate_levelrange_expression(portcon->context->range, db);
1268 if (rc != SEPOL_OK) {
1269 goto exit;
1270 }
1271 break;
1272 }
1273 case CIL_NODECON: {
1274 struct cil_nodecon *nodecon = node->data;
1275 rc = __evaluate_levelrange_expression(nodecon->context->range, db);
1276 if (rc != SEPOL_OK) {
1277 goto exit;
1278 }
1279 break;
1280 }
1281 case CIL_GENFSCON: {
1282 struct cil_genfscon *genfscon = node->data;
1283 rc = __evaluate_levelrange_expression(genfscon->context->range, db);
1284 if (rc != SEPOL_OK) {
1285 goto exit;
1286 }
1287 break;
1288 }
1289 case CIL_NETIFCON: {
1290 struct cil_netifcon *netifcon = node->data;
1291 rc = __evaluate_levelrange_expression(netifcon->if_context->range, db);
1292 if (rc != SEPOL_OK) {
1293 goto exit;
1294 }
1295 rc = __evaluate_levelrange_expression(netifcon->packet_context->range, db);
1296 if (rc != SEPOL_OK) {
1297 goto exit;
1298 }
1299 break;
1300 }
1301 case CIL_PIRQCON: {
1302 struct cil_pirqcon *pirqcon = node->data;
1303 rc = __evaluate_levelrange_expression(pirqcon->context->range, db);
1304 if (rc != SEPOL_OK) {
1305 goto exit;
1306 }
1307 break;
1308 }
1309 case CIL_IOMEMCON: {
1310 struct cil_iomemcon *iomemcon = node->data;
1311 rc = __evaluate_levelrange_expression(iomemcon->context->range, db);
1312 if (rc != SEPOL_OK) {
1313 goto exit;
1314 }
1315 break;
1316 }
1317 case CIL_IOPORTCON: {
1318 struct cil_ioportcon *ioportcon = node->data;
1319 rc = __evaluate_levelrange_expression(ioportcon->context->range, db);
1320 if (rc != SEPOL_OK) {
1321 goto exit;
1322 }
1323 break;
1324 }
1325 case CIL_PCIDEVICECON: {
1326 struct cil_pcidevicecon *pcidevicecon = node->data;
1327 rc = __evaluate_levelrange_expression(pcidevicecon->context->range, db);
1328 if (rc != SEPOL_OK) {
1329 goto exit;
1330 }
1331 break;
1332 }
1333 case CIL_DEVICETREECON: {
1334 struct cil_devicetreecon *devicetreecon = node->data;
1335 rc = __evaluate_levelrange_expression(devicetreecon->context->range, db);
1336 if (rc != SEPOL_OK) {
1337 goto exit;
1338 }
1339 break;
1340 }
1341 case CIL_FSUSE: {
1342 struct cil_fsuse *fsuse = node->data;
1343 rc = __evaluate_levelrange_expression(fsuse->context->range, db);
1344 if (rc != SEPOL_OK) {
1345 goto exit;
1346 }
1347 break;
1348 }
1349 default:
1350 break;
1351 }
1352
1353 return SEPOL_OK;
1354
1355 exit:
1356 return rc;
1357 }
1358
1359 struct perm_to_list {
1360 enum cil_flavor flavor;
1361 ebitmap_t *perms;
1362 struct cil_list *new_list;
1363 };
1364
__perm_bits_to_list(hashtab_key_t k,hashtab_datum_t d,void * args)1365 static int __perm_bits_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1366 {
1367 struct perm_to_list *perm_args = (struct perm_to_list *)args;
1368 ebitmap_t *perms = perm_args->perms;
1369 struct cil_list *new_list = perm_args->new_list;
1370 struct cil_perm *perm = (struct cil_perm *)d;
1371 unsigned int value = perm->value;
1372
1373 if (!ebitmap_get_bit(perms, value)) {
1374 return SEPOL_OK;
1375 }
1376
1377 cil_list_append(new_list, CIL_DATUM, d);
1378
1379 return SEPOL_OK;
1380 }
1381
__evaluate_perm_expression(struct cil_list * perms,enum cil_flavor flavor,symtab_t * class_symtab,symtab_t * common_symtab,unsigned int num_perms,struct cil_list ** new_list,struct cil_db * db)1382 static int __evaluate_perm_expression(struct cil_list *perms, enum cil_flavor flavor, symtab_t *class_symtab, symtab_t *common_symtab, unsigned int num_perms, struct cil_list **new_list, struct cil_db *db)
1383 {
1384 int rc = SEPOL_ERR;
1385 struct perm_to_list args;
1386 ebitmap_t bitmap;
1387
1388 if (cil_verify_is_list(perms, CIL_PERM)) {
1389 return SEPOL_OK;
1390 }
1391
1392 ebitmap_init(&bitmap);
1393 rc = __cil_expr_to_bitmap(perms, &bitmap, num_perms, db);
1394 if (rc != SEPOL_OK) {
1395 ebitmap_destroy(&bitmap);
1396 goto exit;
1397 }
1398
1399 cil_list_init(new_list, flavor);
1400
1401 args.flavor = flavor;
1402 args.perms = &bitmap;
1403 args.new_list = *new_list;
1404
1405 cil_symtab_map(class_symtab, __perm_bits_to_list, &args);
1406
1407 if (common_symtab != NULL) {
1408 cil_symtab_map(common_symtab, __perm_bits_to_list, &args);
1409 }
1410
1411 ebitmap_destroy(&bitmap);
1412 return SEPOL_OK;
1413
1414 exit:
1415 return rc;
1416 }
1417
__evaluate_classperms(struct cil_classperms * cp,struct cil_db * db)1418 static int __evaluate_classperms(struct cil_classperms *cp, struct cil_db *db)
1419 {
1420 int rc = SEPOL_ERR;
1421 struct cil_class *class = cp->class;
1422 struct cil_class *common = class->common;
1423 symtab_t *common_symtab = NULL;
1424 struct cil_list *new_list = NULL;
1425
1426 if (common) {
1427 common_symtab = &common->perms;
1428 }
1429
1430 rc = __evaluate_perm_expression(cp->perms, CIL_PERM, &class->perms, common_symtab, class->num_perms, &new_list, db);
1431 if (rc != SEPOL_OK) {
1432 goto exit;
1433 }
1434
1435 if (new_list == NULL) {
1436 return SEPOL_OK;
1437 }
1438
1439 cil_list_destroy(&cp->perms, CIL_FALSE);
1440
1441 cp->perms = new_list;
1442
1443 return SEPOL_OK;
1444
1445 exit:
1446 return rc;
1447 }
1448
__evaluate_classperms_list(struct cil_list * classperms,struct cil_db * db)1449 static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db *db)
1450 {
1451 int rc = SEPOL_ERR;
1452 struct cil_list_item *curr;
1453
1454 cil_list_for_each(curr, classperms) {
1455 if (curr->flavor == CIL_CLASSPERMS) {
1456 struct cil_classperms *cp = curr->data;
1457 if (FLAVOR(cp->class) == CIL_CLASS) {
1458 rc = __evaluate_classperms(cp, db);
1459 if (rc != SEPOL_OK) {
1460 goto exit;
1461 }
1462 } else { /* MAP */
1463 struct cil_list_item *i = NULL;
1464 cil_list_for_each(i, cp->perms) {
1465 struct cil_perm *cmp = i->data;
1466 rc = __evaluate_classperms_list(cmp->classperms, db);
1467 if (rc != SEPOL_OK) {
1468 goto exit;
1469 }
1470 }
1471 }
1472 } else { /* SET */
1473 struct cil_classperms_set *cp_set = curr->data;
1474 struct cil_classpermission *cp = cp_set->set;
1475 rc = __evaluate_classperms_list(cp->classperms, db);
1476 if (rc != SEPOL_OK) {
1477 goto exit;
1478 }
1479 }
1480 }
1481
1482 return SEPOL_OK;
1483
1484 exit:
1485 return rc;
1486 }
1487
1488 struct class_map_args {
1489 struct cil_db *db;
1490 int rc;
1491 };
1492
__evaluate_map_perm_classperms(hashtab_key_t k,hashtab_datum_t d,void * args)1493 static int __evaluate_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1494 {
1495 struct class_map_args *map_args = args;
1496 struct cil_perm *cmp = (struct cil_perm *)d;
1497
1498 int rc = __evaluate_classperms_list(cmp->classperms, map_args->db);
1499
1500 if (rc != SEPOL_OK) {
1501 map_args->rc = rc;
1502 }
1503
1504 return SEPOL_OK;
1505 }
1506
__evaluate_map_class(struct cil_class * mc,struct cil_db * db)1507 static int __evaluate_map_class(struct cil_class *mc, struct cil_db *db)
1508 {
1509 struct class_map_args map_args;
1510
1511 map_args.db = db;
1512 map_args.rc = SEPOL_OK;
1513 cil_symtab_map(&mc->perms, __evaluate_map_perm_classperms, &map_args);
1514
1515 return map_args.rc;
1516 }
1517
__cil_post_db_classperms_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1518 static int __cil_post_db_classperms_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1519 {
1520 int rc = SEPOL_ERR;
1521 struct cil_db *db = extra_args;
1522
1523 switch (node->flavor) {
1524 case CIL_BLOCK: {
1525 struct cil_block *blk = node->data;
1526 if (blk->is_abstract == CIL_TRUE) {
1527 *finished = CIL_TREE_SKIP_HEAD;
1528 }
1529 break;
1530 }
1531 case CIL_MACRO:
1532 *finished = CIL_TREE_SKIP_HEAD;
1533 break;
1534 case CIL_MAP_CLASS: {
1535 rc = __evaluate_map_class(node->data, db);
1536 if (rc != SEPOL_OK) {
1537 goto exit;
1538 }
1539 break;
1540 }
1541 case CIL_CLASSPERMISSION: {
1542 struct cil_classpermission *cp = node->data;
1543 rc = __evaluate_classperms_list(cp->classperms, db);
1544 if (rc != SEPOL_OK) {
1545 goto exit;
1546 }
1547 break;
1548 }
1549 case CIL_AVRULE: {
1550 struct cil_avrule *avrule = node->data;
1551 rc = __evaluate_classperms_list(avrule->classperms, db);
1552 if (rc != SEPOL_OK) {
1553 goto exit;
1554 }
1555 break;
1556 }
1557 case CIL_CONSTRAIN:
1558 case CIL_MLSCONSTRAIN: {
1559 struct cil_constrain *constrain = node->data;
1560 rc = __evaluate_classperms_list(constrain->classperms, db);
1561 if (rc != SEPOL_OK) {
1562 goto exit;
1563 }
1564 break;
1565 }
1566 default:
1567 break;
1568 }
1569
1570 return SEPOL_OK;
1571
1572 exit:
1573 return rc;
1574 }
1575
cil_post_db(struct cil_db * db)1576 static int cil_post_db(struct cil_db *db)
1577 {
1578 int rc = SEPOL_ERR;
1579
1580 rc = cil_tree_walk(db->ast->root, __cil_post_db_count_helper, NULL, NULL, db);
1581 if (rc != SEPOL_OK) {
1582 cil_log(CIL_INFO, "Failure during cil databse count helper\n");
1583 goto exit;
1584 }
1585
1586 rc = cil_tree_walk(db->ast->root, __cil_post_db_array_helper, NULL, NULL, db);
1587 if (rc != SEPOL_OK) {
1588 cil_log(CIL_INFO, "Failure during cil database array helper\n");
1589 goto exit;
1590 }
1591
1592 rc = cil_tree_walk(db->ast->root, __cil_post_db_attr_helper, NULL, NULL, db);
1593 if (rc != SEPOL_OK) {
1594 cil_log(CIL_INFO, "Failed to create attribute bitmaps\n");
1595 goto exit;
1596 }
1597
1598 rc = cil_tree_walk(db->ast->root, __cil_post_db_roletype_helper, NULL, NULL, db);
1599 if (rc != SEPOL_OK) {
1600 cil_log(CIL_INFO, "Failed during roletype association\n");
1601 goto exit;
1602 }
1603
1604 rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db);
1605 if (rc != SEPOL_OK) {
1606 cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n");
1607 goto exit;
1608 }
1609
1610 rc = cil_tree_walk(db->ast->root, __cil_post_db_cat_helper, NULL, NULL, db);
1611 if (rc != SEPOL_OK) {
1612 cil_log(CIL_INFO, "Failed to evaluate category expressions\n");
1613 goto exit;
1614 }
1615
1616 qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
1617 qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
1618 qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
1619 qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
1620 qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
1621 qsort(db->filecon->array, db->filecon->count, sizeof(db->filecon->array), cil_post_filecon_compare);
1622 qsort(db->pirqcon->array, db->pirqcon->count, sizeof(db->pirqcon->array), cil_post_pirqcon_compare);
1623 qsort(db->iomemcon->array, db->iomemcon->count, sizeof(db->iomemcon->array), cil_post_iomemcon_compare);
1624 qsort(db->ioportcon->array, db->ioportcon->count, sizeof(db->ioportcon->array), cil_post_ioportcon_compare);
1625 qsort(db->pcidevicecon->array, db->pcidevicecon->count, sizeof(db->pcidevicecon->array), cil_post_pcidevicecon_compare);
1626 qsort(db->devicetreecon->array, db->devicetreecon->count, sizeof(db->devicetreecon->array), cil_post_devicetreecon_compare);
1627
1628 exit:
1629 return rc;
1630 }
1631
cil_post_verify(struct cil_db * db)1632 static int cil_post_verify(struct cil_db *db)
1633 {
1634 int rc = SEPOL_ERR;
1635 int avrule_cnt = 0;
1636 int handleunknown = -1;
1637 int mls = -1;
1638 int nseuserdflt = 0;
1639 int pass = 0;
1640 struct cil_args_verify extra_args;
1641 struct cil_complex_symtab csymtab;
1642
1643 cil_complex_symtab_init(&csymtab, CIL_CLASS_SYM_SIZE);
1644
1645 extra_args.db = db;
1646 extra_args.csymtab = &csymtab;
1647 extra_args.avrule_cnt = &avrule_cnt;
1648 extra_args.handleunknown = &handleunknown;
1649 extra_args.mls = &mls;
1650 extra_args.nseuserdflt = &nseuserdflt;
1651 extra_args.pass = &pass;
1652
1653 for (pass = 0; pass < 2; pass++) {
1654 rc = cil_tree_walk(db->ast->root, __cil_verify_helper, NULL, NULL, &extra_args);
1655 if (rc != SEPOL_OK) {
1656 cil_log(CIL_ERR, "Failed to verify cil database\n");
1657 goto exit;
1658 }
1659 }
1660
1661 if (db->handle_unknown == -1) {
1662 if (handleunknown == -1) {
1663 db->handle_unknown = SEPOL_DENY_UNKNOWN;
1664 } else {
1665 db->handle_unknown = handleunknown;
1666 }
1667 }
1668
1669 if (db->mls == -1) {
1670 if (mls == -1) {
1671 db->mls = CIL_FALSE;
1672 } else {
1673 db->mls = mls;
1674 }
1675 }
1676
1677 if (avrule_cnt == 0) {
1678 cil_log(CIL_ERR, "Policy must include at least one avrule\n");
1679 rc = SEPOL_ERR;
1680 goto exit;
1681 }
1682
1683 if (nseuserdflt > 1) {
1684 cil_log(CIL_ERR, "Policy cannot contain more than one selinuxuserdefault, found: %d\n", nseuserdflt);
1685 rc = SEPOL_ERR;
1686 goto exit;
1687 }
1688
1689 exit:
1690 cil_complex_symtab_destroy(&csymtab);
1691 return rc;
1692 }
1693
cil_post_process(struct cil_db * db)1694 int cil_post_process(struct cil_db *db)
1695 {
1696 int rc = SEPOL_ERR;
1697
1698 rc = cil_verify_no_classperms_loop(db);
1699 if (rc != SEPOL_OK) {
1700 goto exit;
1701 }
1702
1703 rc = cil_post_db(db);
1704 if (rc != SEPOL_OK) {
1705 cil_log(CIL_ERR, "Failed post db handling\n");
1706 goto exit;
1707 }
1708
1709 rc = cil_post_verify(db);
1710 if (rc != SEPOL_OK) {
1711 cil_log(CIL_ERR, "Failed to verify cil database\n");
1712 goto exit;
1713 }
1714
1715 exit:
1716 return rc;
1717
1718 }
1719