Home | History | Annotate | Download | only in src
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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