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_CLASS: {
    343 		struct cil_class *class = node->data;
    344 		if (class->datum.nodes->head->data == node) {
    345 			// Multiple nodes can point to the same datum. Only count once.
    346 			db->num_classes++;
    347 		}
    348 		break;
    349 	}
    350 	case CIL_TYPE: {
    351 		struct cil_type *type = node->data;
    352 		if (type->datum.nodes->head->data == node) {
    353 			// Multiple nodes can point to the same datum. Only count once.
    354 			type->value = db->num_types;
    355 			db->num_types++;
    356 			db->num_types_and_attrs++;
    357 		}
    358 		break;
    359 	}
    360 	case CIL_TYPEATTRIBUTE: {
    361 		struct cil_typeattribute *attr = node->data;
    362 		if (attr->datum.nodes->head->data == node) {
    363 			// Multiple nodes can point to the same datum. Only count once.
    364 			db->num_types_and_attrs++;
    365 		}
    366 		break;
    367 	}
    368 
    369 	case CIL_ROLE: {
    370 		struct cil_role *role = node->data;
    371 		if (role->datum.nodes->head->data == node) {
    372 			// Multiple nodes can point to the same datum. Only count once.
    373 			role->value = db->num_roles;
    374 			db->num_roles++;
    375 		}
    376 		break;
    377 	}
    378 	case CIL_USER: {
    379 		struct cil_user *user = node->data;
    380 		if (user->datum.nodes->head->data == node) {
    381 			// multiple AST nodes can point to the same cil_user data (like if
    382 			// copied from a macro). This check ensures we only count the
    383 			// duplicates once
    384 			user->value = db->num_users;
    385 			db->num_users++;
    386 		}
    387 		break;
    388 	}
    389 	case CIL_NETIFCON:
    390 		db->netifcon->count++;
    391 		break;
    392 	case CIL_GENFSCON:
    393 		db->genfscon->count++;
    394 		break;
    395 	case CIL_FILECON:
    396 		db->filecon->count++;
    397 		break;
    398 	case CIL_NODECON:
    399 		db->nodecon->count++;
    400 		break;
    401 	case CIL_PORTCON:
    402 		db->portcon->count++;
    403 		break;
    404 	case CIL_PIRQCON:
    405 		db->pirqcon->count++;
    406 		break;
    407 	case CIL_IOMEMCON:
    408 		db->iomemcon->count++;
    409 		break;
    410 	case CIL_IOPORTCON:
    411 		db->ioportcon->count++;
    412 		break;
    413 	case CIL_PCIDEVICECON:
    414 		db->pcidevicecon->count++;
    415 		break;
    416 	case CIL_DEVICETREECON:
    417 		db->devicetreecon->count++;
    418 		break;
    419 	case CIL_FSUSE:
    420 		db->fsuse->count++;
    421 		break;
    422 	default:
    423 		break;
    424 	}
    425 
    426 	return SEPOL_OK;
    427 }
    428 
    429 static int __cil_post_db_array_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
    430 {
    431 	struct cil_db *db = extra_args;
    432 
    433 	switch(node->flavor) {
    434 	case CIL_BLOCK: {
    435 		struct cil_block *blk = node->data;
    436 		if (blk->is_abstract == CIL_TRUE) {
    437 			*finished = CIL_TREE_SKIP_HEAD;
    438 		}
    439 		break;
    440 	}
    441 	case CIL_MACRO:
    442 		*finished = CIL_TREE_SKIP_HEAD;
    443 		break;
    444 	case CIL_TYPE: {
    445 		struct cil_type *type = node->data;
    446 		if (db->val_to_type == NULL) {
    447 			db->val_to_type = cil_malloc(sizeof(*db->val_to_type) * db->num_types);
    448 		}
    449 		db->val_to_type[type->value] = type;
    450 		break;
    451 	}
    452 	case CIL_ROLE: {
    453 		struct cil_role *role = node->data;
    454 		if (db->val_to_role == NULL) {
    455 			db->val_to_role = cil_malloc(sizeof(*db->val_to_role) * db->num_roles);
    456 		}
    457 		db->val_to_role[role->value] = role;
    458 		break;
    459 	}
    460 	case CIL_USER: {
    461 		struct cil_user *user= node->data;
    462 		if (db->val_to_user == NULL) {
    463 			db->val_to_user = cil_malloc(sizeof(*db->val_to_user) * db->num_users);
    464 		}
    465 		db->val_to_user[user->value] = user;
    466 		break;
    467 	}
    468 	case CIL_USERPREFIX: {
    469 		cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data);
    470 		break;
    471 	}
    472 	case CIL_SELINUXUSER: {
    473 		cil_list_prepend(db->selinuxusers, CIL_SELINUXUSER, node->data);
    474 		break;
    475 	}
    476 	case CIL_SELINUXUSERDEFAULT: {
    477 		cil_list_append(db->selinuxusers, CIL_SELINUXUSERDEFAULT, node->data);
    478 		break;
    479 	}
    480 	case CIL_NETIFCON: {
    481 		struct cil_sort *sort = db->netifcon;
    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_FSUSE: {
    492 		struct cil_sort *sort = db->fsuse;
    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_GENFSCON: {
    503 		struct cil_sort *sort = db->genfscon;
    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_FILECON: {
    514 		struct cil_sort *sort = db->filecon;
    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_NODECON: {
    525 		struct cil_sort *sort = db->nodecon;
    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_PORTCON: {
    536 		struct cil_sort *sort = db->portcon;
    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_PIRQCON: {
    547 		struct cil_sort *sort = db->pirqcon;
    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_IOMEMCON: {
    558 		struct cil_sort *sort = db->iomemcon;
    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 	case CIL_IOPORTCON: {
    569 		struct cil_sort *sort = db->ioportcon;
    570 		uint32_t count = sort->count;
    571 		uint32_t i = sort->index;
    572 		if (sort->array == NULL) {
    573 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    574 		}
    575 		sort->array[i] = node->data;
    576 		sort->index++;
    577 		break;
    578 	}
    579 	case CIL_PCIDEVICECON: {
    580 		struct cil_sort *sort = db->pcidevicecon;
    581 		uint32_t count = sort->count;
    582 		uint32_t i = sort->index;
    583 		if (sort->array == NULL) {
    584 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    585 		}
    586 		sort->array[i] = node->data;
    587 		sort->index++;
    588 		break;
    589 	}
    590 	case CIL_DEVICETREECON: {
    591 		struct cil_sort *sort = db->devicetreecon;
    592 		uint32_t count = sort->count;
    593 		uint32_t i = sort->index;
    594 		if (sort->array == NULL) {
    595 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    596 		}
    597 		sort->array[i] = node->data;
    598 		sort->index++;
    599 		break;
    600 	}
    601 	default:
    602 		break;
    603 	}
    604 
    605 	return SEPOL_OK;
    606 }
    607 
    608 static int __evaluate_type_expression(struct cil_typeattribute *attr, struct cil_db *db)
    609 {
    610 	int rc;
    611 
    612 	attr->types = cil_malloc(sizeof(*attr->types));
    613 	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->types, db->num_types, db);
    614 	if (rc != SEPOL_OK) {
    615 		cil_log(CIL_ERR, "Failed to expand type attribute to bitmap\n");
    616 		ebitmap_destroy(attr->types);
    617 		free(attr->types);
    618 		attr->types = NULL;
    619 	}
    620 	return rc;
    621 }
    622 
    623 static int __cil_type_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
    624 {
    625 	int rc = SEPOL_ERR;
    626 	struct cil_tree_node *node = datum->nodes->head->data;
    627 
    628 	ebitmap_init(bitmap);
    629 
    630 	if (node->flavor == CIL_TYPEATTRIBUTE) {
    631 		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
    632 		if (attr->types == NULL) {
    633 			rc = __evaluate_type_expression(attr, db);
    634 			if (rc != SEPOL_OK) goto exit;
    635 		}
    636 		ebitmap_union(bitmap, attr->types);
    637 	} else if (node->flavor == CIL_TYPEALIAS) {
    638 		struct cil_alias *alias = (struct cil_alias *)datum;
    639 		struct cil_type *type = alias->actual;
    640 		if (ebitmap_set_bit(bitmap, type->value, 1)) {
    641 			cil_log(CIL_ERR, "Failed to set type bit\n");
    642 			ebitmap_destroy(bitmap);
    643 			goto exit;
    644 		}
    645 	} else {
    646 		struct cil_type *type = (struct cil_type *)datum;
    647 		if (ebitmap_set_bit(bitmap, type->value, 1)) {
    648 			cil_log(CIL_ERR, "Failed to set type bit\n");
    649 			ebitmap_destroy(bitmap);
    650 			goto exit;
    651 		}
    652 	}
    653 
    654 	return SEPOL_OK;
    655 
    656 exit:
    657 	return rc;
    658 }
    659 
    660 static int __evaluate_user_expression(struct cil_userattribute *attr, struct cil_db *db)
    661 {
    662 	int rc;
    663 
    664 	attr->users = cil_malloc(sizeof(*attr->users));
    665 	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->users, db->num_users, db);
    666 	if (rc != SEPOL_OK) {
    667 		cil_log(CIL_ERR, "Failed to expand user attribute to bitmap\n");
    668 		ebitmap_destroy(attr->users);
    669 		free(attr->users);
    670 		attr->users = NULL;
    671 	}
    672 	return rc;
    673 }
    674 
    675 static int __cil_user_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
    676 {
    677 	int rc = SEPOL_ERR;
    678 	struct cil_tree_node *node = datum->nodes->head->data;
    679 	struct cil_userattribute *attr = NULL;
    680 	struct cil_user *user = NULL;
    681 
    682 	ebitmap_init(bitmap);
    683 
    684 	if (node->flavor == CIL_USERATTRIBUTE) {
    685 		attr = (struct cil_userattribute *)datum;
    686 		if (attr->users == NULL) {
    687 			rc = __evaluate_user_expression(attr, db);
    688 			if (rc != SEPOL_OK) {
    689 				goto exit;
    690 			}
    691 		}
    692 		ebitmap_union(bitmap, attr->users);
    693 	} else {
    694 		user = (struct cil_user *)datum;
    695 		if (ebitmap_set_bit(bitmap, user->value, 1)) {
    696 			cil_log(CIL_ERR, "Failed to set user bit\n");
    697 			ebitmap_destroy(bitmap);
    698 			goto exit;
    699 		}
    700 	}
    701 
    702 	return SEPOL_OK;
    703 
    704 exit:
    705 	return rc;
    706 }
    707 
    708 static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db)
    709 {
    710 	int rc;
    711 
    712 	attr->roles = cil_malloc(sizeof(*attr->roles));
    713 	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->roles, db->num_roles, db);
    714 	if (rc != SEPOL_OK) {
    715 		cil_log(CIL_ERR, "Failed to expand role attribute to bitmap\n");
    716 		ebitmap_destroy(attr->roles);
    717 		free(attr->roles);
    718 		attr->roles = NULL;
    719 	}
    720 	return rc;
    721 }
    722 
    723 static int __cil_role_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
    724 {
    725 	int rc = SEPOL_ERR;
    726 	struct cil_tree_node *node = datum->nodes->head->data;
    727 
    728 	ebitmap_init(bitmap);
    729 
    730 	if (node->flavor == CIL_ROLEATTRIBUTE) {
    731 		struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
    732 		if (attr->roles == NULL) {
    733 			rc = __evaluate_role_expression(attr, db);
    734 			if (rc != SEPOL_OK) goto exit;
    735 		}
    736 		ebitmap_union(bitmap, attr->roles);
    737 	} else {
    738 		struct cil_role *role = (struct cil_role *)datum;
    739 		if (ebitmap_set_bit(bitmap, role->value, 1)) {
    740 			cil_log(CIL_ERR, "Failed to set role bit\n");
    741 			ebitmap_destroy(bitmap);
    742 			goto exit;
    743 		}
    744 	}
    745 
    746 	return SEPOL_OK;
    747 
    748 exit:
    749 	return rc;
    750 }
    751 
    752 static int __evaluate_permissionx_expression(struct cil_permissionx *permx, struct cil_db *db)
    753 {
    754 	int rc;
    755 
    756 	permx->perms = cil_malloc(sizeof(*permx->perms));
    757 	ebitmap_init(permx->perms);
    758 
    759 	rc = __cil_expr_to_bitmap(permx->expr_str, permx->perms, 0x10000, db); // max is one more than 0xFFFF
    760 	if (rc != SEPOL_OK) {
    761 		cil_log(CIL_ERR, "Failed to expand permissionx expression\n");
    762 		ebitmap_destroy(permx->perms);
    763 		free(permx->perms);
    764 		permx->perms = NULL;
    765 	}
    766 
    767 	return rc;
    768 }
    769 
    770 static int __cil_permx_str_to_int(char *permx_str, uint16_t *val)
    771 {
    772 	char *endptr = NULL;
    773 	long lval = strtol(permx_str, &endptr, 0);
    774 
    775 	if (*endptr != '\0') {
    776 		cil_log(CIL_ERR, "permissionx value %s not valid number\n", permx_str);
    777 		goto exit;
    778 	}
    779 	if (lval < 0x0000 || lval > 0xFFFF) {
    780 		cil_log(CIL_ERR, "permissionx value %s must be between 0x0000 and 0xFFFF\n", permx_str);
    781 		goto exit;
    782 	}
    783 
    784 	*val = (uint16_t)lval;
    785 
    786 	return SEPOL_OK;
    787 
    788 exit:
    789 	return SEPOL_ERR;
    790 }
    791 
    792 static int __cil_permx_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
    793 {
    794 	int rc = SEPOL_ERR;
    795 	uint16_t val;
    796 
    797 	ebitmap_init(bitmap);
    798 
    799 	rc = __cil_permx_str_to_int((char*)datum, &val);
    800 	if (rc != SEPOL_OK) {
    801 		goto exit;
    802 	}
    803 
    804 	if (ebitmap_set_bit(bitmap, (unsigned int)val, 1)) {
    805 		cil_log(CIL_ERR, "Failed to set permissionx bit\n");
    806 		ebitmap_destroy(bitmap);
    807 		goto exit;
    808 	}
    809 
    810 	return SEPOL_OK;
    811 
    812 exit:
    813 	return rc;
    814 }
    815 
    816 static int __cil_perm_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
    817 {
    818 	struct cil_perm *perm = (struct cil_perm *)datum;
    819 	unsigned int value = perm->value;
    820 
    821 	ebitmap_init(bitmap);
    822 	if (ebitmap_set_bit(bitmap, value, 1)) {
    823 		cil_log(CIL_INFO, "Failed to set perm bit\n");
    824 		ebitmap_destroy(bitmap);
    825 		return SEPOL_ERR;
    826 	}
    827 
    828 	return SEPOL_OK;
    829 }
    830 
    831 static int __evaluate_cat_expression(struct cil_cats *cats, struct cil_db *db)
    832 {
    833 	int rc = SEPOL_ERR;
    834 	ebitmap_t bitmap;
    835 	struct cil_list *new;
    836 	struct cil_list_item *curr;
    837 
    838 	if (cats->evaluated == CIL_TRUE) {
    839 		return SEPOL_OK;
    840 	}
    841 
    842 	if (cil_verify_is_list(cats->datum_expr, CIL_CAT)) {
    843 		return SEPOL_OK;
    844 	}
    845 
    846 	ebitmap_init(&bitmap);
    847 	rc = __cil_expr_to_bitmap(cats->datum_expr, &bitmap, db->num_cats, db);
    848 	if (rc != SEPOL_OK) {
    849 		cil_log(CIL_ERR, "Failed to expand category expression to bitmap\n");
    850 		ebitmap_destroy(&bitmap);
    851 		goto exit;
    852 	}
    853 
    854 	cil_list_init(&new, CIL_CAT);
    855 
    856 	cil_list_for_each(curr, db->catorder) {
    857 		struct cil_cat *cat = curr->data;
    858 		if (ebitmap_get_bit(&bitmap, cat->value)) {
    859 			cil_list_append(new, CIL_DATUM, cat);
    860 		}
    861 	}
    862 
    863 	ebitmap_destroy(&bitmap);
    864 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
    865 	if (new->head != NULL) {
    866 		cats->datum_expr = new;
    867 	} else {
    868 		/* empty list */
    869 		cil_list_destroy(&new, CIL_FALSE);
    870 		cats->datum_expr = NULL;
    871 	}
    872 
    873 	cats->evaluated = CIL_TRUE;
    874 
    875 	return SEPOL_OK;
    876 
    877 exit:
    878 	return rc;
    879 }
    880 
    881 static int __cil_cat_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
    882 {
    883 	int rc = SEPOL_ERR;
    884 	struct cil_tree_node *node = datum->nodes->head->data;
    885 
    886 	ebitmap_init(bitmap);
    887 
    888 	if (node->flavor == CIL_CATSET) {
    889 		struct cil_catset *catset = (struct cil_catset *)datum;
    890 		struct cil_list_item *curr;
    891 		if (catset->cats->evaluated == CIL_FALSE) {
    892 			rc = __evaluate_cat_expression(catset->cats, db);
    893 			if (rc != SEPOL_OK) goto exit;
    894 		}
    895 		for (curr = catset->cats->datum_expr->head; curr; curr = curr->next) {
    896 			struct cil_cat *cat = (struct cil_cat *)curr->data;
    897 			if (ebitmap_set_bit(bitmap, cat->value, 1)) {
    898 				cil_log(CIL_ERR, "Failed to set cat bit\n");
    899 				ebitmap_destroy(bitmap);
    900 				goto exit;
    901 			}
    902 		}
    903 	} else if (node->flavor == CIL_CATALIAS) {
    904 		struct cil_alias *alias = (struct cil_alias *)datum;
    905 		struct cil_cat *cat = alias->actual;
    906 		if (ebitmap_set_bit(bitmap, cat->value, 1)) {
    907 			cil_log(CIL_ERR, "Failed to set cat bit\n");
    908 			ebitmap_destroy(bitmap);
    909 			goto exit;
    910 		}
    911 	} else {
    912 		struct cil_cat *cat = (struct cil_cat *)datum;
    913 		if (ebitmap_set_bit(bitmap, cat->value, 1)) {
    914 			cil_log(CIL_ERR, "Failed to set cat bit\n");
    915 			ebitmap_destroy(bitmap);
    916 			goto exit;
    917 		}
    918 	}
    919 
    920 	return SEPOL_OK;
    921 
    922 exit:
    923 	return rc;
    924 }
    925 
    926 static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
    927 {
    928 	int rc = SEPOL_ERR;
    929 	struct cil_symtab_datum *d1 = i1->data;
    930 	struct cil_symtab_datum *d2 = i2->data;
    931 	struct cil_tree_node *n1 = d1->nodes->head->data;
    932 	struct cil_tree_node *n2 = d2->nodes->head->data;
    933 	struct cil_cat *c1 = (struct cil_cat *)d1;
    934 	struct cil_cat *c2 = (struct cil_cat *)d2;
    935 	int i;
    936 
    937 	if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) {
    938 		cil_log(CIL_ERR, "Category sets cannont be used in a category range\n");
    939 		goto exit;
    940 	}
    941 
    942 	if (n1->flavor == CIL_CATALIAS) {
    943 		struct cil_alias *alias = (struct cil_alias *)d1;
    944 		c1 = alias->actual;
    945 	}
    946 
    947 	if (n2->flavor == CIL_CATALIAS) {
    948 		struct cil_alias *alias = (struct cil_alias *)d2;
    949 		c2 = alias->actual;
    950 	}
    951 
    952 	for (i = c1->value; i <= c2->value; i++) {
    953 		if (ebitmap_set_bit(bitmap, i, 1)) {
    954 			cil_log(CIL_ERR, "Failed to set cat bit\n");
    955 			ebitmap_destroy(bitmap);
    956 			goto exit;
    957 		}
    958 	}
    959 
    960 	return SEPOL_OK;
    961 
    962 exit:
    963 	return rc;
    964 }
    965 
    966 static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
    967 {
    968 	int rc = SEPOL_ERR;
    969 	char *p1 = i1->data;
    970 	char *p2 = i2->data;
    971 	uint16_t v1;
    972 	uint16_t v2;
    973 	uint32_t i;
    974 
    975 	rc = __cil_permx_str_to_int(p1, &v1);
    976 	if (rc != SEPOL_OK) {
    977 		goto exit;
    978 	}
    979 
    980 	rc = __cil_permx_str_to_int(p2, &v2);
    981 	if (rc != SEPOL_OK) {
    982 		goto exit;
    983 	}
    984 
    985 	for (i = v1; i <= v2; i++) {
    986 		if (ebitmap_set_bit(bitmap, i, 1)) {
    987 			cil_log(CIL_ERR, "Failed to set permissionx bit\n");
    988 			ebitmap_destroy(bitmap);
    989 			goto exit;
    990 		}
    991 	}
    992 
    993 	return SEPOL_OK;
    994 
    995 exit:
    996 	return rc;
    997 }
    998 
    999 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)
   1000 {
   1001 	int rc = SEPOL_ERR;
   1002 
   1003 	if (curr->flavor == CIL_DATUM) {
   1004 		switch (flavor) {
   1005 		case CIL_TYPE:
   1006 			rc = __cil_type_to_bitmap(curr->data, bitmap, db);
   1007 			break;
   1008 		case CIL_ROLE:
   1009 			rc = __cil_role_to_bitmap(curr->data, bitmap, db);
   1010 			break;
   1011 		case CIL_USER:
   1012 			rc = __cil_user_to_bitmap(curr->data, bitmap, db);
   1013 			break;
   1014 		case CIL_PERM:
   1015 			rc = __cil_perm_to_bitmap(curr->data, bitmap, db);
   1016 			break;
   1017 		case CIL_CAT:
   1018 			rc = __cil_cat_to_bitmap(curr->data, bitmap, db);
   1019 			break;
   1020 		default:
   1021 			rc = SEPOL_ERR;
   1022 		}
   1023 	} else if (curr->flavor == CIL_LIST) {
   1024 		struct cil_list *l = curr->data;
   1025 		ebitmap_init(bitmap);
   1026 		rc = __cil_expr_to_bitmap(l, bitmap, max, db);
   1027 		if (rc != SEPOL_OK) {
   1028 			ebitmap_destroy(bitmap);
   1029 		}
   1030 	} else if (flavor == CIL_PERMISSIONX) {
   1031 		// permissionx expressions aren't resolved into anything, so curr->flavor
   1032 		// is just a CIL_STRING, not a CIL_DATUM, so just check on flavor for those
   1033 		rc = __cil_permx_to_bitmap(curr->data, bitmap, db);
   1034 	}
   1035 
   1036 	return rc;
   1037 }
   1038 
   1039 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db)
   1040 {
   1041 	int rc = SEPOL_ERR;
   1042 	struct cil_list_item *curr;
   1043 	enum cil_flavor flavor;
   1044 	ebitmap_t tmp, b1, b2;
   1045 
   1046 	if (expr == NULL || expr->head == NULL) {
   1047 		return SEPOL_OK;
   1048 	}
   1049 
   1050 	curr = expr->head;
   1051 	flavor = expr->flavor;
   1052 
   1053 	if (curr->flavor == CIL_OP) {
   1054 		enum cil_flavor op = (enum cil_flavor)curr->data;
   1055 
   1056 		if (op == CIL_ALL) {
   1057 			ebitmap_init(&b1); /* all zeros */
   1058 			rc = ebitmap_not(&tmp, &b1, max);
   1059 			ebitmap_destroy(&b1);
   1060 			if (rc != SEPOL_OK) {
   1061 				cil_log(CIL_INFO, "Failed to expand 'all' operator\n");
   1062 				ebitmap_destroy(&tmp);
   1063 				goto exit;
   1064 			}
   1065 		} else if (op == CIL_RANGE) {
   1066 			if (flavor == CIL_CAT) {
   1067 				ebitmap_init(&tmp);
   1068 				rc = __cil_cat_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
   1069 				if (rc != SEPOL_OK) {
   1070 					cil_log(CIL_INFO, "Failed to expand category range\n");
   1071 					ebitmap_destroy(&tmp);
   1072 					goto exit;
   1073 				}
   1074 			} else if (flavor == CIL_PERMISSIONX) {
   1075 				ebitmap_init(&tmp);
   1076 				rc = __cil_permissionx_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
   1077 				if (rc != SEPOL_OK) {
   1078 					cil_log(CIL_INFO, "Failed to expand category range\n");
   1079 					ebitmap_destroy(&tmp);
   1080 					goto exit;
   1081 				}
   1082 			} else {
   1083 				cil_log(CIL_INFO, "Range operation only supported for categories permissionx\n");
   1084 				rc = SEPOL_ERR;
   1085 				goto exit;
   1086 			}
   1087 		} else {
   1088 			rc = __cil_expr_to_bitmap_helper(curr->next, flavor, &b1, max, db);
   1089 			if (rc != SEPOL_OK) {
   1090 				cil_log(CIL_INFO, "Failed to get first operand bitmap\n");
   1091 				goto exit;
   1092 			}
   1093 
   1094 			if (op == CIL_NOT) {
   1095 				rc = ebitmap_not(&tmp, &b1, max);
   1096 				ebitmap_destroy(&b1);
   1097 				if (rc != SEPOL_OK) {
   1098 					cil_log(CIL_INFO, "Failed to NOT bitmap\n");
   1099 					ebitmap_destroy(&tmp);
   1100 					goto exit;
   1101 				}
   1102 			} else {
   1103 				rc = __cil_expr_to_bitmap_helper(curr->next->next, flavor, &b2, max, db);
   1104 				if (rc != SEPOL_OK) {
   1105 					cil_log(CIL_INFO, "Failed to get second operand bitmap\n");
   1106 					goto exit;
   1107 				}
   1108 
   1109 				if (op == CIL_OR) {
   1110 					rc = ebitmap_or(&tmp, &b1, &b2);
   1111 				} else if (op == CIL_AND) {
   1112 					rc = ebitmap_and(&tmp, &b1, &b2);
   1113 				} else if (op == CIL_XOR) {
   1114 					rc = ebitmap_xor(&tmp, &b1, &b2);
   1115 				} else {
   1116 					rc = SEPOL_ERR;
   1117 				}
   1118 				ebitmap_destroy(&b1);
   1119 				ebitmap_destroy(&b2);
   1120 				if (rc != SEPOL_OK) {
   1121 					cil_log(CIL_INFO, "Failed to apply operator to bitmaps\n");
   1122 					ebitmap_destroy(&tmp);
   1123 					goto exit;
   1124 				}
   1125 			}
   1126 		}
   1127 	} else {
   1128 		ebitmap_init(&tmp);
   1129 		for (;curr; curr = curr->next) {
   1130 			rc = __cil_expr_to_bitmap_helper(curr, flavor, &b2, max, db);
   1131 			if (rc != SEPOL_OK) {
   1132 				cil_log(CIL_INFO, "Failed to get operand in list\n");
   1133 				ebitmap_destroy(&tmp);
   1134 				goto exit;
   1135 			}
   1136 			b1 = tmp;
   1137 			rc = ebitmap_or(&tmp, &b1, &b2);
   1138 			ebitmap_destroy(&b1);
   1139 			ebitmap_destroy(&b2);
   1140 			if (rc != SEPOL_OK) {
   1141 				cil_log(CIL_INFO, "Failed to OR operands in list\n");
   1142 				ebitmap_destroy(&tmp);
   1143 				goto exit;
   1144 			}
   1145 
   1146 		}
   1147 	}
   1148 
   1149 	ebitmap_union(out, &tmp);
   1150 	ebitmap_destroy(&tmp);
   1151 
   1152 	return SEPOL_OK;
   1153 
   1154 exit:
   1155 	return rc;
   1156 }
   1157 
   1158 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db)
   1159 {
   1160 	int rc = SEPOL_ERR;
   1161 	struct cil_list_item *expr;
   1162 
   1163 	ebitmap_init(out);
   1164 
   1165 	if (expr_list == NULL) {
   1166 		return SEPOL_OK;
   1167 	}
   1168 
   1169 	cil_list_for_each(expr, expr_list) {
   1170 		ebitmap_t bitmap;
   1171 		struct cil_list *l = (struct cil_list *)expr->data;
   1172 		ebitmap_init(&bitmap);
   1173 		rc = __cil_expr_to_bitmap(l, &bitmap, max, db);
   1174 		if (rc != SEPOL_OK) {
   1175 			cil_log(CIL_INFO, "Failed to expand expression list to bitmap\n");
   1176 			ebitmap_destroy(&bitmap);
   1177 			goto exit;
   1178 		}
   1179 		ebitmap_union(out, &bitmap);
   1180 		ebitmap_destroy(&bitmap);
   1181 	}
   1182 
   1183 	return SEPOL_OK;
   1184 
   1185 exit:
   1186 	return SEPOL_ERR;
   1187 }
   1188 
   1189 static int __cil_post_db_attr_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
   1190 {
   1191 	int rc = SEPOL_ERR;
   1192 	struct cil_db *db = extra_args;
   1193 
   1194 	switch (node->flavor) {
   1195 	case CIL_BLOCK: {
   1196 		struct cil_block *blk = node->data;
   1197 		if (blk->is_abstract == CIL_TRUE) {
   1198 			*finished = CIL_TREE_SKIP_HEAD;
   1199 		}
   1200 		break;
   1201 	}
   1202 	case CIL_MACRO: {
   1203 		*finished = CIL_TREE_SKIP_HEAD;
   1204 		break;
   1205 	}
   1206 	case CIL_TYPEATTRIBUTE: {
   1207 		struct cil_typeattribute *attr = node->data;
   1208 		if (attr->types == NULL) {
   1209 			rc = __evaluate_type_expression(attr, db);
   1210 			if (rc != SEPOL_OK) goto exit;
   1211 		}
   1212 		break;
   1213 	}
   1214 	case CIL_ROLEATTRIBUTE: {
   1215 		struct cil_roleattribute *attr = node->data;
   1216 		if (attr->roles == NULL) {
   1217 			rc = __evaluate_role_expression(attr, db);
   1218 			if (rc != SEPOL_OK) goto exit;
   1219 		}
   1220 		break;
   1221 	}
   1222 	case CIL_AVRULEX: {
   1223 		struct cil_avrule *rule = node->data;
   1224 		if (rule->perms.x.permx_str == NULL) {
   1225 			rc = __evaluate_permissionx_expression(rule->perms.x.permx, db);
   1226 			if (rc != SEPOL_OK) goto exit;
   1227 		}
   1228 		break;
   1229 	}
   1230 	case CIL_PERMISSIONX: {
   1231 		struct cil_permissionx *permx = node->data;
   1232 		rc = __evaluate_permissionx_expression(permx, db);
   1233 		if (rc != SEPOL_OK) goto exit;
   1234 		break;
   1235 	}
   1236 	case CIL_USERATTRIBUTE: {
   1237 		struct cil_userattribute *attr = node->data;
   1238 		if (attr->users == NULL) {
   1239 			rc = __evaluate_user_expression(attr, db);
   1240 			if (rc != SEPOL_OK) {
   1241 				goto exit;
   1242 			}
   1243 		}
   1244 		break;
   1245 	}
   1246 	default:
   1247 		break;
   1248 	}
   1249 
   1250 	return SEPOL_OK;
   1251 
   1252 exit:
   1253 	return rc;
   1254 }
   1255 
   1256 static int __cil_role_assign_types(struct cil_role *role, struct cil_symtab_datum *datum)
   1257 {
   1258 	struct cil_tree_node *node = datum->nodes->head->data;
   1259 
   1260 	if (role->types == NULL) {
   1261 		role->types = cil_malloc(sizeof(*role->types));
   1262 		ebitmap_init(role->types);
   1263 	}
   1264 
   1265 	if (node->flavor == CIL_TYPE) {
   1266 		struct cil_type *type = (struct cil_type *)datum;
   1267 		if (ebitmap_set_bit(role->types, type->value, 1)) {
   1268 			cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
   1269 			goto exit;
   1270 		}
   1271 	} else if (node->flavor == CIL_TYPEALIAS) {
   1272 		struct cil_alias *alias = (struct cil_alias *)datum;
   1273 		struct cil_type *type = alias->actual;
   1274 		if (ebitmap_set_bit(role->types, type->value, 1)) {
   1275 			cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
   1276 			goto exit;
   1277 		}
   1278 	} else if (node->flavor == CIL_TYPEATTRIBUTE) {
   1279 		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
   1280 		ebitmap_union(role->types, attr->types);
   1281 	}
   1282 
   1283 	return SEPOL_OK;
   1284 
   1285 exit:
   1286 	return SEPOL_ERR;
   1287 }
   1288 
   1289 static int __cil_post_db_roletype_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
   1290 {
   1291 	int rc = SEPOL_ERR;
   1292 	struct cil_db *db = extra_args;
   1293 
   1294 	switch (node->flavor) {
   1295 	case CIL_BLOCK: {
   1296 		struct cil_block *blk = node->data;
   1297 		if (blk->is_abstract == CIL_TRUE) {
   1298 			*finished = CIL_TREE_SKIP_HEAD;
   1299 		}
   1300 		break;
   1301 	}
   1302 	case CIL_MACRO: {
   1303 		*finished = CIL_TREE_SKIP_HEAD;
   1304 		break;
   1305 	}
   1306 	case CIL_ROLETYPE: {
   1307 		struct cil_roletype *roletype = node->data;
   1308 		struct cil_symtab_datum *role_datum = roletype->role;
   1309 		struct cil_symtab_datum *type_datum = roletype->type;
   1310 		struct cil_tree_node *role_node = role_datum->nodes->head->data;
   1311 
   1312 		if (role_node->flavor == CIL_ROLEATTRIBUTE) {
   1313 			struct cil_roleattribute *attr = roletype->role;
   1314 			ebitmap_node_t *rnode;
   1315 			unsigned int i;
   1316 
   1317 			ebitmap_for_each_bit(attr->roles, rnode, i) {
   1318 				struct cil_role *role = NULL;
   1319 
   1320 				if (!ebitmap_get_bit(attr->roles, i)) {
   1321 					continue;
   1322 				}
   1323 
   1324 				role = db->val_to_role[i];
   1325 
   1326 				rc = __cil_role_assign_types(role, type_datum);
   1327 				if (rc != SEPOL_OK) {
   1328 					goto exit;
   1329 				}
   1330 			}
   1331 		} else {
   1332 			struct cil_role *role = roletype->role;
   1333 
   1334 			rc = __cil_role_assign_types(role, type_datum);
   1335 			if (rc != SEPOL_OK) {
   1336 				goto exit;
   1337 			}
   1338 		}
   1339 		break;
   1340 	}
   1341 	default:
   1342 		break;
   1343 	}
   1344 
   1345 	return SEPOL_OK;
   1346 exit:
   1347 	cil_log(CIL_INFO, "cil_post_db_roletype_helper failed\n");
   1348 	return rc;
   1349 }
   1350 
   1351 static int __cil_user_assign_roles(struct cil_user *user, struct cil_symtab_datum *datum)
   1352 {
   1353 	struct cil_tree_node *node = datum->nodes->head->data;
   1354 	struct cil_role *role = NULL;
   1355 	struct cil_roleattribute *attr = NULL;
   1356 
   1357 	if (user->roles == NULL) {
   1358 		user->roles = cil_malloc(sizeof(*user->roles));
   1359 		ebitmap_init(user->roles);
   1360 	}
   1361 
   1362 	if (node->flavor == CIL_ROLE) {
   1363 		role = (struct cil_role *)datum;
   1364 		if (ebitmap_set_bit(user->roles, role->value, 1)) {
   1365 			cil_log(CIL_INFO, "Failed to set bit in user roles bitmap\n");
   1366 			goto exit;
   1367 		}
   1368 	} else if (node->flavor == CIL_ROLEATTRIBUTE) {
   1369 		attr = (struct cil_roleattribute *)datum;
   1370 		ebitmap_union(user->roles, attr->roles);
   1371 	}
   1372 
   1373 	return SEPOL_OK;
   1374 
   1375 exit:
   1376 	return SEPOL_ERR;
   1377 }
   1378 
   1379 static int __cil_post_db_userrole_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
   1380 {
   1381 	int rc = SEPOL_ERR;
   1382 	struct cil_db *db = extra_args;
   1383 	struct cil_block *blk = NULL;
   1384 	struct cil_userrole *userrole = NULL;
   1385 	struct cil_symtab_datum *user_datum = NULL;
   1386 	struct cil_symtab_datum *role_datum = NULL;
   1387 	struct cil_tree_node *user_node = NULL;
   1388 	struct cil_userattribute *u_attr = NULL;
   1389 	unsigned int i;
   1390 	struct cil_user *user = NULL;
   1391 	ebitmap_node_t *unode = NULL;
   1392 
   1393 	switch (node->flavor) {
   1394 	case CIL_BLOCK: {
   1395 		blk = node->data;
   1396 		if (blk->is_abstract == CIL_TRUE) {
   1397 			*finished = CIL_TREE_SKIP_HEAD;
   1398 		}
   1399 		break;
   1400 	}
   1401 	case CIL_MACRO: {
   1402 		*finished = CIL_TREE_SKIP_HEAD;
   1403 		break;
   1404 	}
   1405 	case CIL_USERROLE: {
   1406 		userrole = node->data;
   1407 		user_datum = userrole->user;
   1408 		role_datum = userrole->role;
   1409 		user_node = user_datum->nodes->head->data;
   1410 
   1411 		if (user_node->flavor == CIL_USERATTRIBUTE) {
   1412 			u_attr = userrole->user;
   1413 
   1414 			ebitmap_for_each_bit(u_attr->users, unode, i) {
   1415 				if (!ebitmap_get_bit(u_attr->users, i)) {
   1416 					continue;
   1417 				}
   1418 
   1419 				user = db->val_to_user[i];
   1420 
   1421 				rc = __cil_user_assign_roles(user, role_datum);
   1422 				if (rc != SEPOL_OK) {
   1423 					goto exit;
   1424 				}
   1425 			}
   1426 		} else {
   1427 			user = userrole->user;
   1428 
   1429 			rc = __cil_user_assign_roles(user, role_datum);
   1430 			if (rc != SEPOL_OK) {
   1431 				goto exit;
   1432 			}
   1433 		}
   1434 
   1435 		break;
   1436 	}
   1437 	default:
   1438 		break;
   1439 	}
   1440 
   1441 	return SEPOL_OK;
   1442 exit:
   1443 	cil_log(CIL_INFO, "cil_post_db_userrole_helper failed\n");
   1444 	return rc;
   1445 }
   1446 
   1447 static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db)
   1448 {
   1449 	if (level->cats != NULL) {
   1450 		return __evaluate_cat_expression(level->cats, db);
   1451 	}
   1452 
   1453 	return SEPOL_OK;
   1454 }
   1455 
   1456 static int __evaluate_levelrange_expression(struct cil_levelrange *levelrange, struct cil_db *db)
   1457 {
   1458 	int rc = SEPOL_OK;
   1459 
   1460 	if (levelrange->low != NULL && levelrange->low->cats != NULL) {
   1461 		rc =  __evaluate_cat_expression(levelrange->low->cats, db);
   1462 		if (rc != SEPOL_OK) {
   1463 			goto exit;
   1464 		}
   1465 	}
   1466 	if (levelrange->high != NULL && levelrange->high->cats != NULL) {
   1467 		rc = __evaluate_cat_expression(levelrange->high->cats, db);
   1468 		if (rc != SEPOL_OK) {
   1469 			goto exit;
   1470 		}
   1471 	}
   1472 
   1473 exit:
   1474 	return rc;
   1475 }
   1476 
   1477 static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   1478 {
   1479 	int rc = SEPOL_ERR;
   1480 	struct cil_db *db = extra_args;
   1481 
   1482 	switch (node->flavor) {
   1483 	case CIL_BLOCK: {
   1484 		struct cil_block *blk = node->data;
   1485 		if (blk->is_abstract == CIL_TRUE) {
   1486 			*finished = CIL_TREE_SKIP_HEAD;
   1487 		}
   1488 		break;
   1489 	}
   1490 	case CIL_MACRO: {
   1491 		*finished = CIL_TREE_SKIP_HEAD;
   1492 		break;
   1493 	}
   1494 	case CIL_CATSET: {
   1495 		struct cil_catset *catset = node->data;
   1496 		rc = __evaluate_cat_expression(catset->cats, db);
   1497 		if (rc != SEPOL_OK) {
   1498 			goto exit;
   1499 		}
   1500 		break;
   1501 	}
   1502 	case CIL_SENSCAT: {
   1503 		struct cil_senscat *senscat = node->data;
   1504 		rc = __evaluate_cat_expression(senscat->cats, db);
   1505 		if (rc != SEPOL_OK) {
   1506 			goto exit;
   1507 		}
   1508 		break;
   1509 	}
   1510 	case CIL_LEVEL: {
   1511 		rc = __evaluate_level_expression(node->data, db);
   1512 		if (rc != SEPOL_OK) {
   1513 			goto exit;
   1514 		}
   1515 		break;
   1516 	}
   1517 	case CIL_LEVELRANGE: {
   1518 		rc = __evaluate_levelrange_expression(node->data, db);
   1519 		if (rc != SEPOL_OK) {
   1520 			goto exit;
   1521 		}
   1522 		break;
   1523 	}
   1524 	case CIL_USER: {
   1525 		struct cil_user *user = node->data;
   1526 		rc = __evaluate_level_expression(user->dftlevel, db);
   1527 		if (rc != SEPOL_OK) {
   1528 			goto exit;
   1529 		}
   1530 		rc = __evaluate_levelrange_expression(user->range, db);
   1531 		if (rc != SEPOL_OK) {
   1532 			goto exit;
   1533 		}
   1534 		break;
   1535 	}
   1536 	case CIL_SELINUXUSERDEFAULT:
   1537 	case CIL_SELINUXUSER: {
   1538 		struct cil_selinuxuser *selinuxuser = node->data;
   1539 		rc = __evaluate_levelrange_expression(selinuxuser->range, db);
   1540 		if (rc != SEPOL_OK) {
   1541 			goto exit;
   1542 		}
   1543 		break;
   1544 	}
   1545 	case CIL_RANGETRANSITION: {
   1546 		struct cil_rangetransition *rangetrans = node->data;
   1547 		rc = __evaluate_levelrange_expression(rangetrans->range, db);
   1548 		if (rc != SEPOL_OK) {
   1549 			goto exit;
   1550 		}
   1551 		break;
   1552 	}
   1553 	case CIL_CONTEXT: {
   1554 		struct cil_context *context = node->data;
   1555 		rc = __evaluate_levelrange_expression(context->range, db);
   1556 		if (rc != SEPOL_OK) {
   1557 			goto exit;
   1558 		}
   1559 		break;
   1560 	}
   1561 	case CIL_SIDCONTEXT: {
   1562 		struct cil_sidcontext *sidcontext = node->data;
   1563 		rc = __evaluate_levelrange_expression(sidcontext->context->range, db);
   1564 		if (rc != SEPOL_OK) {
   1565 			goto exit;
   1566 		}
   1567 		break;
   1568 	}
   1569 	case CIL_FILECON: {
   1570 		struct cil_filecon *filecon = node->data;
   1571 		if (filecon->context) {
   1572 			rc = __evaluate_levelrange_expression(filecon->context->range, db);
   1573 			if (rc != SEPOL_OK) {
   1574 				goto exit;
   1575 			}
   1576 		}
   1577 		break;
   1578 	}
   1579 	case CIL_PORTCON: {
   1580 		struct cil_portcon *portcon = node->data;
   1581 		rc = __evaluate_levelrange_expression(portcon->context->range, db);
   1582 		if (rc != SEPOL_OK) {
   1583 			goto exit;
   1584 		}
   1585 		break;
   1586 	}
   1587 	case CIL_NODECON: {
   1588 		struct cil_nodecon *nodecon = node->data;
   1589 		rc = __evaluate_levelrange_expression(nodecon->context->range, db);
   1590 		if (rc != SEPOL_OK) {
   1591 			goto exit;
   1592 		}
   1593 		break;
   1594 	}
   1595 	case CIL_GENFSCON: {
   1596 		struct cil_genfscon *genfscon = node->data;
   1597 		rc = __evaluate_levelrange_expression(genfscon->context->range, db);
   1598 		if (rc != SEPOL_OK) {
   1599 			goto exit;
   1600 		}
   1601 		break;
   1602 	}
   1603 	case CIL_NETIFCON: {
   1604 		struct cil_netifcon *netifcon = node->data;
   1605 		rc = __evaluate_levelrange_expression(netifcon->if_context->range, db);
   1606 		if (rc != SEPOL_OK) {
   1607 			goto exit;
   1608 		}
   1609 		rc = __evaluate_levelrange_expression(netifcon->packet_context->range, db);
   1610 		if (rc != SEPOL_OK) {
   1611 			goto exit;
   1612 		}
   1613 		break;
   1614 	}
   1615 	case CIL_PIRQCON: {
   1616 		struct cil_pirqcon *pirqcon = node->data;
   1617 		rc = __evaluate_levelrange_expression(pirqcon->context->range, db);
   1618 		if (rc != SEPOL_OK) {
   1619 			goto exit;
   1620 		}
   1621 		break;
   1622 	}
   1623 	case CIL_IOMEMCON: {
   1624 		struct cil_iomemcon *iomemcon = node->data;
   1625 		rc = __evaluate_levelrange_expression(iomemcon->context->range, db);
   1626 		if (rc != SEPOL_OK) {
   1627 			goto exit;
   1628 		}
   1629 		break;
   1630 	}
   1631 	case CIL_IOPORTCON: {
   1632 		struct cil_ioportcon *ioportcon = node->data;
   1633 		rc = __evaluate_levelrange_expression(ioportcon->context->range, db);
   1634 		if (rc != SEPOL_OK) {
   1635 			goto exit;
   1636 		}
   1637 		break;
   1638 	}
   1639 	case CIL_PCIDEVICECON: {
   1640 		struct cil_pcidevicecon *pcidevicecon = node->data;
   1641 		rc = __evaluate_levelrange_expression(pcidevicecon->context->range, db);
   1642 		if (rc != SEPOL_OK) {
   1643 			goto exit;
   1644 		}
   1645 		break;
   1646 	}
   1647 	case CIL_DEVICETREECON: {
   1648 		struct cil_devicetreecon *devicetreecon = node->data;
   1649 		rc = __evaluate_levelrange_expression(devicetreecon->context->range, db);
   1650 		if (rc != SEPOL_OK) {
   1651 			goto exit;
   1652 		}
   1653 		break;
   1654 	}
   1655 	case CIL_FSUSE: {
   1656 		struct cil_fsuse *fsuse = node->data;
   1657 		rc = __evaluate_levelrange_expression(fsuse->context->range, db);
   1658 		if (rc != SEPOL_OK) {
   1659 			goto exit;
   1660 		}
   1661 		break;
   1662 	}
   1663 	default:
   1664 		break;
   1665 	}
   1666 
   1667 	return SEPOL_OK;
   1668 
   1669 exit:
   1670 	return rc;
   1671 }
   1672 
   1673 struct perm_to_list {
   1674 	enum cil_flavor flavor;
   1675 	ebitmap_t *perms;
   1676 	struct cil_list *new_list;
   1677 };
   1678 
   1679 static int __perm_bits_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
   1680 {
   1681 	struct perm_to_list *perm_args = (struct perm_to_list *)args;
   1682 	ebitmap_t *perms = perm_args->perms;
   1683 	struct cil_list *new_list = perm_args->new_list;
   1684 	struct cil_perm *perm = (struct cil_perm *)d;
   1685 	unsigned int value = perm->value;
   1686 
   1687 	if (!ebitmap_get_bit(perms, value)) {
   1688 		return SEPOL_OK;
   1689 	}
   1690 
   1691 	cil_list_append(new_list, CIL_DATUM, d);
   1692 
   1693 	return SEPOL_OK;
   1694 }
   1695 
   1696 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)
   1697 {
   1698 	int rc = SEPOL_ERR;
   1699 	struct perm_to_list args;
   1700 	ebitmap_t bitmap;
   1701 
   1702 	if (cil_verify_is_list(perms, CIL_PERM)) {
   1703 		return SEPOL_OK;
   1704 	}
   1705 
   1706 	ebitmap_init(&bitmap);
   1707 	rc = __cil_expr_to_bitmap(perms, &bitmap, num_perms, db);
   1708 	if (rc != SEPOL_OK) {
   1709 		ebitmap_destroy(&bitmap);
   1710 		goto exit;
   1711 	}
   1712 
   1713 	cil_list_init(new_list, flavor);
   1714 
   1715 	args.flavor = flavor;
   1716 	args.perms = &bitmap;
   1717 	args.new_list = *new_list;
   1718 
   1719 	cil_symtab_map(class_symtab, __perm_bits_to_list, &args);
   1720 
   1721 	if (common_symtab != NULL) {
   1722 		cil_symtab_map(common_symtab, __perm_bits_to_list, &args);
   1723 	}
   1724 
   1725 	ebitmap_destroy(&bitmap);
   1726 	return SEPOL_OK;
   1727 
   1728 exit:
   1729 	return rc;
   1730 }
   1731 
   1732 static int __evaluate_classperms(struct cil_classperms *cp, struct cil_db *db)
   1733 {
   1734 	int rc = SEPOL_ERR;
   1735 	struct cil_class *class = cp->class;
   1736 	struct cil_class *common = class->common;
   1737 	symtab_t *common_symtab = NULL;
   1738 	struct cil_list *new_list = NULL;
   1739 
   1740 	if (common) {
   1741 		common_symtab = &common->perms;
   1742 	}
   1743 
   1744 	rc = __evaluate_perm_expression(cp->perms, CIL_PERM, &class->perms, common_symtab, class->num_perms, &new_list, db);
   1745 	if (rc != SEPOL_OK) {
   1746 		goto exit;
   1747 	}
   1748 
   1749 	if (new_list == NULL) {
   1750 		return SEPOL_OK;
   1751 	}
   1752 
   1753 	cil_list_destroy(&cp->perms, CIL_FALSE);
   1754 
   1755 	cp->perms = new_list;
   1756 
   1757 	return SEPOL_OK;
   1758 
   1759 exit:
   1760 	return rc;
   1761 }
   1762 
   1763 static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db *db)
   1764 {
   1765 	int rc = SEPOL_ERR;
   1766 	struct cil_list_item *curr;
   1767 
   1768 	cil_list_for_each(curr, classperms) {
   1769 		if (curr->flavor == CIL_CLASSPERMS) {
   1770 			struct cil_classperms *cp = curr->data;
   1771 			if (FLAVOR(cp->class) == CIL_CLASS) {
   1772 				rc = __evaluate_classperms(cp, db);
   1773 				if (rc != SEPOL_OK) {
   1774 					goto exit;
   1775 				}
   1776 			} else { /* MAP */
   1777 				struct cil_list_item *i = NULL;
   1778 				cil_list_for_each(i, cp->perms) {
   1779 					struct cil_perm *cmp = i->data;
   1780 					rc = __evaluate_classperms_list(cmp->classperms, db);
   1781 					if (rc != SEPOL_OK) {
   1782 						goto exit;
   1783 					}
   1784 				}
   1785 			}
   1786 		} else { /* SET */
   1787 			struct cil_classperms_set *cp_set = curr->data;
   1788 			struct cil_classpermission *cp = cp_set->set;
   1789 			rc = __evaluate_classperms_list(cp->classperms, db);
   1790 			if (rc != SEPOL_OK) {
   1791 				goto exit;
   1792 			}
   1793 		}
   1794 	}
   1795 
   1796 	return SEPOL_OK;
   1797 
   1798 exit:
   1799 	return rc;
   1800 }
   1801 
   1802 struct class_map_args {
   1803 	struct cil_db *db;
   1804 	int rc;
   1805 };
   1806 
   1807 static int __evaluate_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
   1808 {
   1809 	struct class_map_args *map_args = args;
   1810 	struct cil_perm *cmp = (struct cil_perm *)d;
   1811 
   1812 	int rc = __evaluate_classperms_list(cmp->classperms, map_args->db);
   1813 
   1814 	if (rc != SEPOL_OK) {
   1815 		map_args->rc = rc;
   1816 	}
   1817 
   1818 	return SEPOL_OK;
   1819 }
   1820 
   1821 static int __evaluate_map_class(struct cil_class *mc, struct cil_db *db)
   1822 {
   1823 	struct class_map_args map_args;
   1824 
   1825 	map_args.db = db;
   1826 	map_args.rc = SEPOL_OK;
   1827 	cil_symtab_map(&mc->perms, __evaluate_map_perm_classperms, &map_args);
   1828 
   1829 	return map_args.rc;
   1830 }
   1831 
   1832 static int __cil_post_db_classperms_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   1833 {
   1834 	int rc = SEPOL_ERR;
   1835 	struct cil_db *db = extra_args;
   1836 
   1837 	switch (node->flavor) {
   1838 	case CIL_BLOCK: {
   1839 		struct cil_block *blk = node->data;
   1840 		if (blk->is_abstract == CIL_TRUE) {
   1841 			*finished = CIL_TREE_SKIP_HEAD;
   1842 		}
   1843 		break;
   1844 	}
   1845 	case CIL_MACRO:
   1846 		*finished = CIL_TREE_SKIP_HEAD;
   1847 		break;
   1848 	case CIL_MAP_CLASS: {
   1849 		rc = __evaluate_map_class(node->data, db);
   1850 		if (rc != SEPOL_OK) {
   1851 			goto exit;
   1852 		}
   1853 		break;
   1854 	}
   1855 	case CIL_CLASSPERMISSION: {
   1856 		struct cil_classpermission *cp = node->data;
   1857 		rc = __evaluate_classperms_list(cp->classperms, db);
   1858 		if (rc != SEPOL_OK) {
   1859 			goto exit;
   1860 		}
   1861 		break;
   1862 	}
   1863 	case CIL_AVRULE: {
   1864 		struct cil_avrule *avrule = node->data;
   1865 		rc = __evaluate_classperms_list(avrule->perms.classperms, db);
   1866 		if (rc != SEPOL_OK) {
   1867 			goto exit;
   1868 		}
   1869 		break;
   1870 	}
   1871 	case CIL_CONSTRAIN:
   1872 	case CIL_MLSCONSTRAIN: {
   1873 		struct cil_constrain *constrain = node->data;
   1874 		rc = __evaluate_classperms_list(constrain->classperms, db);
   1875 		if (rc != SEPOL_OK) {
   1876 			goto exit;
   1877 		}
   1878 		break;
   1879 	}
   1880 	default:
   1881 		break;
   1882 	}
   1883 
   1884 	return SEPOL_OK;
   1885 
   1886 exit:
   1887 	return rc;
   1888 }
   1889 
   1890 static int cil_post_db(struct cil_db *db)
   1891 {
   1892 	int rc = SEPOL_ERR;
   1893 
   1894 	rc = cil_tree_walk(db->ast->root, __cil_post_db_count_helper, NULL, NULL, db);
   1895 	if (rc != SEPOL_OK) {
   1896 		cil_log(CIL_INFO, "Failure during cil databse count helper\n");
   1897 		goto exit;
   1898 	}
   1899 
   1900 	rc = cil_tree_walk(db->ast->root, __cil_post_db_array_helper, NULL, NULL, db);
   1901 	if (rc != SEPOL_OK) {
   1902 		cil_log(CIL_INFO, "Failure during cil database array helper\n");
   1903 		goto exit;
   1904 	}
   1905 
   1906 	rc = cil_tree_walk(db->ast->root, __cil_post_db_attr_helper, NULL, NULL, db);
   1907 	if (rc != SEPOL_OK) {
   1908 		cil_log(CIL_INFO, "Failed to create attribute bitmaps\n");
   1909 		goto exit;
   1910 	}
   1911 
   1912 	rc = cil_tree_walk(db->ast->root, __cil_post_db_roletype_helper, NULL, NULL, db);
   1913 	if (rc != SEPOL_OK) {
   1914 		cil_log(CIL_INFO, "Failed during roletype association\n");
   1915 		goto exit;
   1916 	}
   1917 
   1918 	rc = cil_tree_walk(db->ast->root, __cil_post_db_userrole_helper, NULL, NULL, db);
   1919 	if (rc != SEPOL_OK) {
   1920 		cil_log(CIL_INFO, "Failed during userrole association\n");
   1921 		goto exit;
   1922 	}
   1923 
   1924 	rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db);
   1925 	if (rc != SEPOL_OK) {
   1926 		cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n");
   1927 		goto exit;
   1928 	}
   1929 
   1930 	rc = cil_tree_walk(db->ast->root, __cil_post_db_cat_helper, NULL, NULL, db);
   1931 	if (rc != SEPOL_OK) {
   1932 		cil_log(CIL_INFO, "Failed to evaluate category expressions\n");
   1933 		goto exit;
   1934 	}
   1935 
   1936 	qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
   1937 	qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
   1938 	qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
   1939 	qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
   1940 	qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
   1941 	qsort(db->filecon->array, db->filecon->count, sizeof(db->filecon->array), cil_post_filecon_compare);
   1942 	qsort(db->pirqcon->array, db->pirqcon->count, sizeof(db->pirqcon->array), cil_post_pirqcon_compare);
   1943 	qsort(db->iomemcon->array, db->iomemcon->count, sizeof(db->iomemcon->array), cil_post_iomemcon_compare);
   1944 	qsort(db->ioportcon->array, db->ioportcon->count, sizeof(db->ioportcon->array), cil_post_ioportcon_compare);
   1945 	qsort(db->pcidevicecon->array, db->pcidevicecon->count, sizeof(db->pcidevicecon->array), cil_post_pcidevicecon_compare);
   1946 	qsort(db->devicetreecon->array, db->devicetreecon->count, sizeof(db->devicetreecon->array), cil_post_devicetreecon_compare);
   1947 
   1948 exit:
   1949 	return rc;
   1950 }
   1951 
   1952 static int cil_post_verify(struct cil_db *db)
   1953 {
   1954 	int rc = SEPOL_ERR;
   1955 	int avrule_cnt = 0;
   1956 	int handleunknown = -1;
   1957 	int mls = -1;
   1958 	int nseuserdflt = 0;
   1959 	int pass = 0;
   1960 	struct cil_args_verify extra_args;
   1961 	struct cil_complex_symtab csymtab;
   1962 
   1963 	cil_complex_symtab_init(&csymtab, CIL_CLASS_SYM_SIZE);
   1964 
   1965 	extra_args.db = db;
   1966 	extra_args.csymtab = &csymtab;
   1967 	extra_args.avrule_cnt = &avrule_cnt;
   1968 	extra_args.handleunknown = &handleunknown;
   1969 	extra_args.mls = &mls;
   1970 	extra_args.nseuserdflt = &nseuserdflt;
   1971 	extra_args.pass = &pass;
   1972 
   1973 	for (pass = 0; pass < 2; pass++) {
   1974 		rc = cil_tree_walk(db->ast->root, __cil_verify_helper, NULL, NULL, &extra_args);
   1975 		if (rc != SEPOL_OK) {
   1976 			cil_log(CIL_ERR, "Failed to verify cil database\n");
   1977 			goto exit;
   1978 		}
   1979 	}
   1980 
   1981 	if (db->handle_unknown == -1) {
   1982 		if (handleunknown == -1) {
   1983 			db->handle_unknown = SEPOL_DENY_UNKNOWN;
   1984 		} else {
   1985 			db->handle_unknown = handleunknown;
   1986 		}
   1987 	}
   1988 
   1989 	if (db->mls == -1) {
   1990 		if (mls == -1) {
   1991 			db->mls = CIL_FALSE;
   1992 		} else {
   1993 			db->mls = mls;
   1994 		}
   1995 	}
   1996 
   1997 	if (avrule_cnt == 0) {
   1998 		cil_log(CIL_ERR, "Policy must include at least one avrule\n");
   1999 		rc = SEPOL_ERR;
   2000 		goto exit;
   2001 	}
   2002 
   2003 	if (nseuserdflt > 1) {
   2004 		cil_log(CIL_ERR, "Policy cannot contain more than one selinuxuserdefault, found: %d\n", nseuserdflt);
   2005 		rc = SEPOL_ERR;
   2006 		goto exit;
   2007 	}
   2008 
   2009 exit:
   2010 	cil_complex_symtab_destroy(&csymtab);
   2011 	return rc;
   2012 }
   2013 
   2014 static int cil_pre_verify(struct cil_db *db)
   2015 {
   2016 	int rc = SEPOL_ERR;
   2017 	struct cil_args_verify extra_args;
   2018 
   2019 	extra_args.db = db;
   2020 
   2021 	rc = cil_tree_walk(db->ast->root, __cil_pre_verify_helper, NULL, NULL, &extra_args);
   2022 	if (rc != SEPOL_OK) {
   2023 		cil_log(CIL_ERR, "Failed to verify cil database\n");
   2024 		goto exit;
   2025 	}
   2026 
   2027 exit:
   2028 	return rc;
   2029 }
   2030 
   2031 int cil_post_process(struct cil_db *db)
   2032 {
   2033 	int rc = SEPOL_ERR;
   2034 
   2035 	rc = cil_pre_verify(db);
   2036 	if (rc != SEPOL_OK) {
   2037 		cil_log(CIL_ERR, "Failed to verify cil database\n");
   2038 		goto exit;
   2039 	}
   2040 
   2041 	rc = cil_post_db(db);
   2042 	if (rc != SEPOL_OK) {
   2043 		cil_log(CIL_ERR, "Failed post db handling\n");
   2044 		goto exit;
   2045 	}
   2046 
   2047 	rc = cil_post_verify(db);
   2048 	if (rc != SEPOL_OK) {
   2049 		cil_log(CIL_ERR, "Failed to verify cil database\n");
   2050 		goto exit;
   2051 	}
   2052 
   2053 exit:
   2054 	return rc;
   2055 
   2056 }
   2057