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 #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */
     51 #define TYPEATTR_INFIX "_typeattr_"        /* Also in libsepol/src/module_to_cil.c */
     52 
     53 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
     54 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
     55 
     56 static int cats_compare(struct cil_cats *a, struct cil_cats *b)
     57 {
     58 	struct cil_list_item *i, *j;
     59 	int rc;
     60 
     61 	if (a == b) return 0;
     62 	if (!a) return -1;
     63 	if (!b) return 1;
     64 
     65 	/* Expects cat expression to have been evaluated */
     66 	cil_list_for_each(i, a->datum_expr) {
     67 		cil_list_for_each(j, b->datum_expr) {
     68 			rc = strcmp(DATUM(i->data)->fqn, DATUM(j->data)->fqn);
     69 			if (!rc) return rc;
     70 		}
     71 	}
     72 	return 0;
     73 }
     74 
     75 static int level_compare(struct cil_level *a, struct cil_level *b)
     76 {
     77 	int rc;
     78 
     79 	if (a == b) return 0;
     80 	if (!a) return -1;
     81 	if (!b) return 1;
     82 
     83 	if (a->sens != b->sens) {
     84 		rc = strcmp(DATUM(a->sens)->fqn, DATUM(b->sens)->fqn);
     85 		if (rc != 0) return rc;
     86 	}
     87 	if (a->cats != b->cats) {
     88 		return cats_compare(a->cats, b->cats);
     89 	}
     90 	return 0;
     91 }
     92 
     93 static int range_compare(struct cil_levelrange *a, struct cil_levelrange *b)
     94 {
     95 	int rc;
     96 
     97 	if (a == b) return 0;
     98 	if (!a) return -1;
     99 	if (!b) return 1;
    100 
    101 	if (a->low != b->low) {
    102 		rc = level_compare(a->low, b->low);
    103 		if (rc != 0) return rc;
    104 	}
    105 	if (a->high != b->high) {
    106 		return level_compare(a->high, b->high);
    107 	}
    108 	return 0;
    109 }
    110 
    111 static int context_compare(struct cil_context *a, struct cil_context *b)
    112 {
    113 	int rc;
    114 
    115 	if (a->user != b->user) {
    116 		rc = strcmp(DATUM(a->user)->fqn, DATUM(b->user)->fqn);
    117 		if (rc != 0) return rc;
    118 	}
    119 	if (a->role != b->role) {
    120 		rc = strcmp(DATUM(a->role)->fqn, DATUM(b->role)->fqn);
    121 		if (rc != 0) return rc;
    122 	}
    123 	if (a->type != b->type) {
    124 		rc = strcmp(DATUM(a->type)->fqn, DATUM(b->type)->fqn);
    125 		if (rc != 0) return rc;
    126 	}
    127 	if (a->range != b->range) {
    128 		return range_compare(a->range, b->range);
    129 	}
    130 	return 0;
    131 }
    132 
    133 static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
    134 {
    135 	struct cil_list_item *curr;
    136 
    137 	cil_list_for_each(curr, list) {
    138 		switch (curr->flavor) {
    139 		case CIL_LIST:
    140 			return CIL_FALSE;
    141 			break;
    142 		case CIL_OP:
    143 			return CIL_FALSE;
    144 			break;
    145 		default:
    146 			if (flavor == CIL_CAT) {
    147 				struct cil_symtab_datum *d = curr->data;
    148 				struct cil_tree_node *n = d->nodes->head->data;
    149 				if (n->flavor == CIL_CATSET) {
    150 					return CIL_FALSE;
    151 				}
    152 			}
    153 			break;
    154 		}
    155 	}
    156 	return CIL_TRUE;
    157 }
    158 
    159 void cil_post_fc_fill_data(struct fc_data *fc, char *path)
    160 {
    161 	int c = 0;
    162 	fc->meta = 0;
    163 	fc->stem_len = 0;
    164 	fc->str_len = 0;
    165 
    166 	while (path[c] != '\0') {
    167 		switch (path[c]) {
    168 		case '.':
    169 		case '^':
    170 		case '$':
    171 		case '?':
    172 		case '*':
    173 		case '+':
    174 		case '|':
    175 		case '[':
    176 		case '(':
    177 		case '{':
    178 			fc->meta = 1;
    179 			break;
    180 		case '\\':
    181 			c++;
    182 			/* FALLTHRU */
    183 		default:
    184 			if (!fc->meta) {
    185 				fc->stem_len++;
    186 			}
    187 			break;
    188 		}
    189 		fc->str_len++;
    190 		c++;
    191 	}
    192 }
    193 
    194 int cil_post_filecon_compare(const void *a, const void *b)
    195 {
    196 	int rc = 0;
    197 	struct cil_filecon *a_filecon = *(struct cil_filecon**)a;
    198 	struct cil_filecon *b_filecon = *(struct cil_filecon**)b;
    199 	struct fc_data *a_data = cil_malloc(sizeof(*a_data));
    200 	struct fc_data *b_data = cil_malloc(sizeof(*b_data));
    201 	char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1);
    202 	a_path[0] = '\0';
    203 	char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1);
    204 	b_path[0] = '\0';
    205 	strcat(a_path, a_filecon->path_str);
    206 	strcat(b_path, b_filecon->path_str);
    207 	cil_post_fc_fill_data(a_data, a_path);
    208 	cil_post_fc_fill_data(b_data, b_path);
    209 	if (a_data->meta && !b_data->meta) {
    210 		rc = -1;
    211 	} else if (b_data->meta && !a_data->meta) {
    212 		rc = 1;
    213 	} else if (a_data->stem_len < b_data->stem_len) {
    214 		rc = -1;
    215 	} else if (b_data->stem_len < a_data->stem_len) {
    216 		rc = 1;
    217 	} else if (a_data->str_len < b_data->str_len) {
    218 		rc = -1;
    219 	} else if (b_data->str_len < a_data->str_len) {
    220 		rc = 1;
    221 	} else if (a_filecon->type < b_filecon->type) {
    222 		rc = -1;
    223 	} else if (b_filecon->type < a_filecon->type) {
    224 		rc = 1;
    225 	} else {
    226 		rc = strcmp(a_filecon->path_str, b_filecon->path_str);
    227 	}
    228 
    229 	free(a_path);
    230 	free(b_path);
    231 	free(a_data);
    232 	free(b_data);
    233 
    234 	return rc;
    235 }
    236 
    237 int cil_post_ibpkeycon_compare(const void *a, const void *b)
    238 {
    239 	int rc = SEPOL_ERR;
    240 	struct cil_ibpkeycon *aibpkeycon = *(struct cil_ibpkeycon **)a;
    241 	struct cil_ibpkeycon *bibpkeycon = *(struct cil_ibpkeycon **)b;
    242 
    243 	rc = strcmp(aibpkeycon->subnet_prefix_str, bibpkeycon->subnet_prefix_str);
    244 	if (rc)
    245 		return rc;
    246 
    247 	rc = (aibpkeycon->pkey_high - aibpkeycon->pkey_low)
    248 		- (bibpkeycon->pkey_high - bibpkeycon->pkey_low);
    249 	if (rc == 0) {
    250 		if (aibpkeycon->pkey_low < bibpkeycon->pkey_low)
    251 			rc = -1;
    252 		else if (bibpkeycon->pkey_low < aibpkeycon->pkey_low)
    253 			rc = 1;
    254 	}
    255 
    256 	return rc;
    257 }
    258 
    259 int cil_post_portcon_compare(const void *a, const void *b)
    260 {
    261 	int rc = SEPOL_ERR;
    262 	struct cil_portcon *aportcon = *(struct cil_portcon**)a;
    263 	struct cil_portcon *bportcon = *(struct cil_portcon**)b;
    264 
    265 	rc = (aportcon->port_high - aportcon->port_low)
    266 		- (bportcon->port_high - bportcon->port_low);
    267 	if (rc == 0) {
    268 		if (aportcon->port_low < bportcon->port_low) {
    269 			rc = -1;
    270 		} else if (bportcon->port_low < aportcon->port_low) {
    271 			rc = 1;
    272 		} else if (aportcon->proto < bportcon->proto) {
    273 			rc = -1;
    274 		} else if (aportcon->proto > bportcon->proto) {
    275 			rc = 1;
    276 		}
    277 	}
    278 
    279 	return rc;
    280 }
    281 
    282 int cil_post_genfscon_compare(const void *a, const void *b)
    283 {
    284 	int rc = SEPOL_ERR;
    285 	struct cil_genfscon *agenfscon = *(struct cil_genfscon**)a;
    286 	struct cil_genfscon *bgenfscon = *(struct cil_genfscon**)b;
    287 
    288 	rc = strcmp(agenfscon->fs_str, bgenfscon->fs_str);
    289 	if (rc == 0) {
    290 		rc = strcmp(agenfscon->path_str, bgenfscon->path_str);
    291 	}
    292 
    293 	return rc;
    294 }
    295 
    296 int cil_post_netifcon_compare(const void *a, const void *b)
    297 {
    298 	struct cil_netifcon *anetifcon = *(struct cil_netifcon**)a;
    299 	struct cil_netifcon *bnetifcon = *(struct cil_netifcon**)b;
    300 
    301 	return  strcmp(anetifcon->interface_str, bnetifcon->interface_str);
    302 }
    303 
    304 int cil_post_ibendportcon_compare(const void *a, const void *b)
    305 {
    306 	int rc = SEPOL_ERR;
    307 
    308 	struct cil_ibendportcon *aibendportcon = *(struct cil_ibendportcon **)a;
    309 	struct cil_ibendportcon *bibendportcon = *(struct cil_ibendportcon **)b;
    310 
    311 	rc = strcmp(aibendportcon->dev_name_str, bibendportcon->dev_name_str);
    312 	if (rc)
    313 		return rc;
    314 
    315 	if (aibendportcon->port < bibendportcon->port)
    316 		return -1;
    317 	else if (bibendportcon->port < aibendportcon->port)
    318 		return 1;
    319 
    320 	return rc;
    321 }
    322 
    323 int cil_post_nodecon_compare(const void *a, const void *b)
    324 {
    325 	struct cil_nodecon *anodecon;
    326 	struct cil_nodecon *bnodecon;
    327 	anodecon = *(struct cil_nodecon**)a;
    328 	bnodecon = *(struct cil_nodecon**)b;
    329 
    330 	/* sort ipv4 before ipv6 */
    331 	if (anodecon->addr->family != bnodecon->addr->family) {
    332 		if (anodecon->addr->family == AF_INET) {
    333 			return -1;
    334 		} else {
    335 			return 1;
    336 		}
    337 	}
    338 
    339 	/* most specific netmask goes first, then order by ip addr */
    340 	if (anodecon->addr->family == AF_INET) {
    341 		int rc = memcmp(&anodecon->mask->ip.v4, &bnodecon->mask->ip.v4, sizeof(anodecon->mask->ip.v4));
    342 		if (rc != 0) {
    343 			return -1 * rc;
    344 		}
    345 		return memcmp(&anodecon->addr->ip.v4, &bnodecon->addr->ip.v4, sizeof(anodecon->addr->ip.v4));
    346 	} else {
    347 		int rc = memcmp(&anodecon->mask->ip.v6, &bnodecon->mask->ip.v6, sizeof(anodecon->mask->ip.v6));
    348 		if (rc != 0) {
    349 			return -1 * rc;
    350 		}
    351 		return memcmp(&anodecon->addr->ip.v6, &bnodecon->addr->ip.v6, sizeof(anodecon->addr->ip.v6));
    352 	}
    353 }
    354 
    355 int cil_post_pirqcon_compare(const void *a, const void *b)
    356 {
    357 	int rc = SEPOL_ERR;
    358 	struct cil_pirqcon *apirqcon = *(struct cil_pirqcon**)a;
    359 	struct cil_pirqcon *bpirqcon = *(struct cil_pirqcon**)b;
    360 
    361 	if (apirqcon->pirq < bpirqcon->pirq) {
    362 		rc = -1;
    363 	} else if (bpirqcon->pirq < apirqcon->pirq) {
    364 		rc = 1;
    365 	} else {
    366 		rc = 0;
    367 	}
    368 
    369 	return rc;
    370 }
    371 
    372 int cil_post_iomemcon_compare(const void *a, const void *b)
    373 {
    374 	int rc = SEPOL_ERR;
    375 	struct cil_iomemcon *aiomemcon = *(struct cil_iomemcon**)a;
    376 	struct cil_iomemcon *biomemcon = *(struct cil_iomemcon**)b;
    377 
    378 	rc = (aiomemcon->iomem_high - aiomemcon->iomem_low)
    379 		- (biomemcon->iomem_high - biomemcon->iomem_low);
    380 	if (rc == 0) {
    381 		if (aiomemcon->iomem_low < biomemcon->iomem_low) {
    382 			rc = -1;
    383 		} else if (biomemcon->iomem_low < aiomemcon->iomem_low) {
    384 			rc = 1;
    385 		}
    386 	}
    387 
    388 	return rc;
    389 }
    390 
    391 int cil_post_ioportcon_compare(const void *a, const void *b)
    392 {
    393 	int rc = SEPOL_ERR;
    394 	struct cil_ioportcon *aioportcon = *(struct cil_ioportcon**)a;
    395 	struct cil_ioportcon *bioportcon = *(struct cil_ioportcon**)b;
    396 
    397 	rc = (aioportcon->ioport_high - aioportcon->ioport_low)
    398 		- (bioportcon->ioport_high - bioportcon->ioport_low);
    399 	if (rc == 0) {
    400 		if (aioportcon->ioport_low < bioportcon->ioport_low) {
    401 			rc = -1;
    402 		} else if (bioportcon->ioport_low < aioportcon->ioport_low) {
    403 			rc = 1;
    404 		}
    405 	}
    406 
    407 	return rc;
    408 }
    409 
    410 int cil_post_pcidevicecon_compare(const void *a, const void *b)
    411 {
    412 	int rc = SEPOL_ERR;
    413 	struct cil_pcidevicecon *apcidevicecon = *(struct cil_pcidevicecon**)a;
    414 	struct cil_pcidevicecon *bpcidevicecon = *(struct cil_pcidevicecon**)b;
    415 
    416 	if (apcidevicecon->dev < bpcidevicecon->dev) {
    417 		rc = -1;
    418 	} else if (bpcidevicecon->dev < apcidevicecon->dev) {
    419 		rc = 1;
    420 	} else {
    421 		rc = 0;
    422 	}
    423 
    424 	return rc;
    425 }
    426 
    427 int cil_post_devicetreecon_compare(const void *a, const void *b)
    428 {
    429 	int rc = SEPOL_ERR;
    430 	struct cil_devicetreecon *adevicetreecon = *(struct cil_devicetreecon**)a;
    431 	struct cil_devicetreecon *bdevicetreecon = *(struct cil_devicetreecon**)b;
    432 
    433 	rc = strcmp(adevicetreecon->path, bdevicetreecon->path);
    434 
    435 	return rc;
    436 }
    437 
    438 int cil_post_fsuse_compare(const void *a, const void *b)
    439 {
    440 	int rc;
    441 	struct cil_fsuse *afsuse;
    442 	struct cil_fsuse *bfsuse;
    443 	afsuse = *(struct cil_fsuse**)a;
    444 	bfsuse = *(struct cil_fsuse**)b;
    445 	if (afsuse->type < bfsuse->type) {
    446 		rc = -1;
    447 	} else if (bfsuse->type < afsuse->type) {
    448 		rc = 1;
    449 	} else {
    450 		rc = strcmp(afsuse->fs_str, bfsuse->fs_str);
    451 	}
    452 	return rc;
    453 }
    454 
    455 int cil_post_filecon_context_compare(const void *a, const void *b)
    456 {
    457 	struct cil_filecon *a_filecon = *(struct cil_filecon**)a;
    458 	struct cil_filecon *b_filecon = *(struct cil_filecon**)b;
    459 	return context_compare(a_filecon->context, b_filecon->context);
    460 }
    461 
    462 int cil_post_ibpkeycon_context_compare(const void *a, const void *b)
    463 {
    464 	struct cil_ibpkeycon *a_ibpkeycon = *(struct cil_ibpkeycon **)a;
    465 	struct cil_ibpkeycon *b_ibpkeycon = *(struct cil_ibpkeycon **)b;
    466 	return context_compare(a_ibpkeycon->context, b_ibpkeycon->context);
    467 }
    468 
    469 int cil_post_portcon_context_compare(const void *a, const void *b)
    470 {
    471 	struct cil_portcon *a_portcon = *(struct cil_portcon**)a;
    472 	struct cil_portcon *b_portcon = *(struct cil_portcon**)b;
    473 	return context_compare(a_portcon->context, b_portcon->context);
    474 }
    475 
    476 int cil_post_genfscon_context_compare(const void *a, const void *b)
    477 {
    478 	struct cil_genfscon *a_genfscon = *(struct cil_genfscon**)a;
    479 	struct cil_genfscon *b_genfscon = *(struct cil_genfscon**)b;
    480 	return context_compare(a_genfscon->context, b_genfscon->context);
    481 }
    482 
    483 int cil_post_netifcon_context_compare(const void *a, const void *b)
    484 {
    485 	int rc;
    486 	struct cil_netifcon *a_netifcon = *(struct cil_netifcon**)a;
    487 	struct cil_netifcon *b_netifcon = *(struct cil_netifcon**)b;
    488 	rc = context_compare(a_netifcon->if_context, b_netifcon->if_context);
    489 	if (rc != 0) {
    490 		return rc;
    491 	}
    492 	return context_compare(a_netifcon->packet_context, b_netifcon->packet_context);
    493 }
    494 
    495 int cil_post_ibendportcon_context_compare(const void *a, const void *b)
    496 {
    497 	struct cil_ibendportcon *a_ibendportcon = *(struct cil_ibendportcon **)a;
    498 	struct cil_ibendportcon *b_ibendportcon = *(struct cil_ibendportcon **)b;
    499 	return context_compare(a_ibendportcon->context, b_ibendportcon->context);
    500 }
    501 
    502 int cil_post_nodecon_context_compare(const void *a, const void *b)
    503 {
    504 	struct cil_nodecon *a_nodecon = *(struct cil_nodecon **)a;
    505 	struct cil_nodecon *b_nodecon = *(struct cil_nodecon **)b;
    506 	return context_compare(a_nodecon->context, b_nodecon->context);
    507 }
    508 
    509 int cil_post_pirqcon_context_compare(const void *a, const void *b)
    510 {
    511 	struct cil_pirqcon *a_pirqcon = *(struct cil_pirqcon**)a;
    512 	struct cil_pirqcon *b_pirqcon = *(struct cil_pirqcon**)b;
    513 	return context_compare(a_pirqcon->context, b_pirqcon->context);
    514 }
    515 
    516 int cil_post_iomemcon_context_compare(const void *a, const void *b)
    517 {
    518 	struct cil_iomemcon *a_iomemcon = *(struct cil_iomemcon**)a;
    519 	struct cil_iomemcon *b_iomemcon = *(struct cil_iomemcon**)b;
    520 	return context_compare(a_iomemcon->context, b_iomemcon->context);
    521 }
    522 
    523 int cil_post_ioportcon_context_compare(const void *a, const void *b)
    524 {
    525 	struct cil_ioportcon *a_ioportcon = *(struct cil_ioportcon**)a;
    526 	struct cil_ioportcon *b_ioportcon = *(struct cil_ioportcon**)b;
    527 	return context_compare(a_ioportcon->context, b_ioportcon->context);
    528 }
    529 
    530 int cil_post_pcidevicecon_context_compare(const void *a, const void *b)
    531 {
    532 	struct cil_pcidevicecon *a_pcidevicecon = *(struct cil_pcidevicecon**)a;
    533 	struct cil_pcidevicecon *b_pcidevicecon = *(struct cil_pcidevicecon**)b;
    534 	return context_compare(a_pcidevicecon->context, b_pcidevicecon->context);
    535 }
    536 
    537 int cil_post_devicetreecon_context_compare(const void *a, const void *b)
    538 {
    539 	struct cil_devicetreecon *a_devicetreecon = *(struct cil_devicetreecon**)a;
    540 	struct cil_devicetreecon *b_devicetreecon = *(struct cil_devicetreecon**)b;
    541 	return context_compare(a_devicetreecon->context, b_devicetreecon->context);
    542 }
    543 
    544 int cil_post_fsuse_context_compare(const void *a, const void *b)
    545 {
    546 	struct cil_fsuse *a_fsuse = *(struct cil_fsuse**)a;
    547 	struct cil_fsuse *b_fsuse = *(struct cil_fsuse**)b;
    548 	return context_compare(a_fsuse->context, b_fsuse->context);
    549 }
    550 
    551 static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
    552 {
    553 	struct cil_db *db = extra_args;
    554 
    555 	switch(node->flavor) {
    556 	case CIL_BLOCK: {
    557 		struct cil_block *blk = node->data;
    558 		if (blk->is_abstract == CIL_TRUE) {
    559 			*finished = CIL_TREE_SKIP_HEAD;
    560 		}
    561 		break;
    562 	}
    563 	case CIL_MACRO:
    564 		*finished = CIL_TREE_SKIP_HEAD;
    565 		break;
    566 	case CIL_CLASS: {
    567 		struct cil_class *class = node->data;
    568 		if (class->datum.nodes->head->data == node) {
    569 			// Multiple nodes can point to the same datum. Only count once.
    570 			db->num_classes++;
    571 		}
    572 		break;
    573 	}
    574 	case CIL_TYPE: {
    575 		struct cil_type *type = node->data;
    576 		if (type->datum.nodes->head->data == node) {
    577 			// Multiple nodes can point to the same datum. Only count once.
    578 			type->value = db->num_types;
    579 			db->num_types++;
    580 			db->num_types_and_attrs++;
    581 		}
    582 		break;
    583 	}
    584 	case CIL_TYPEATTRIBUTE: {
    585 		struct cil_typeattribute *attr = node->data;
    586 		if (attr->datum.nodes->head->data == node) {
    587 			// Multiple nodes can point to the same datum. Only count once.
    588 			db->num_types_and_attrs++;
    589 		}
    590 		break;
    591 	}
    592 
    593 	case CIL_ROLE: {
    594 		struct cil_role *role = node->data;
    595 		if (role->datum.nodes->head->data == node) {
    596 			// Multiple nodes can point to the same datum. Only count once.
    597 			role->value = db->num_roles;
    598 			db->num_roles++;
    599 		}
    600 		break;
    601 	}
    602 	case CIL_USER: {
    603 		struct cil_user *user = node->data;
    604 		if (user->datum.nodes->head->data == node) {
    605 			// multiple AST nodes can point to the same cil_user data (like if
    606 			// copied from a macro). This check ensures we only count the
    607 			// duplicates once
    608 			user->value = db->num_users;
    609 			db->num_users++;
    610 		}
    611 		break;
    612 	}
    613 	case CIL_NETIFCON:
    614 		db->netifcon->count++;
    615 		break;
    616 	case CIL_GENFSCON:
    617 		db->genfscon->count++;
    618 		break;
    619 	case CIL_FILECON:
    620 		db->filecon->count++;
    621 		break;
    622 	case CIL_NODECON:
    623 		db->nodecon->count++;
    624 		break;
    625 	case CIL_IBPKEYCON:
    626 		db->ibpkeycon->count++;
    627 		break;
    628 	case CIL_IBENDPORTCON:
    629 		db->ibendportcon->count++;
    630 		break;
    631 	case CIL_PORTCON:
    632 		db->portcon->count++;
    633 		break;
    634 	case CIL_PIRQCON:
    635 		db->pirqcon->count++;
    636 		break;
    637 	case CIL_IOMEMCON:
    638 		db->iomemcon->count++;
    639 		break;
    640 	case CIL_IOPORTCON:
    641 		db->ioportcon->count++;
    642 		break;
    643 	case CIL_PCIDEVICECON:
    644 		db->pcidevicecon->count++;
    645 		break;
    646 	case CIL_DEVICETREECON:
    647 		db->devicetreecon->count++;
    648 		break;
    649 	case CIL_FSUSE:
    650 		db->fsuse->count++;
    651 		break;
    652 	default:
    653 		break;
    654 	}
    655 
    656 	return SEPOL_OK;
    657 }
    658 
    659 static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
    660 {
    661 	struct cil_db *db = extra_args;
    662 
    663 	switch(node->flavor) {
    664 	case CIL_BLOCK: {
    665 		struct cil_block *blk = node->data;
    666 		if (blk->is_abstract == CIL_TRUE) {
    667 			*finished = CIL_TREE_SKIP_HEAD;
    668 		}
    669 		break;
    670 	}
    671 	case CIL_MACRO:
    672 		*finished = CIL_TREE_SKIP_HEAD;
    673 		break;
    674 	case CIL_TYPE: {
    675 		struct cil_type *type = node->data;
    676 		if (db->val_to_type == NULL) {
    677 			db->val_to_type = cil_malloc(sizeof(*db->val_to_type) * db->num_types);
    678 		}
    679 		db->val_to_type[type->value] = type;
    680 		break;
    681 	}
    682 	case CIL_ROLE: {
    683 		struct cil_role *role = node->data;
    684 		if (db->val_to_role == NULL) {
    685 			db->val_to_role = cil_malloc(sizeof(*db->val_to_role) * db->num_roles);
    686 		}
    687 		db->val_to_role[role->value] = role;
    688 		break;
    689 	}
    690 	case CIL_USER: {
    691 		struct cil_user *user= node->data;
    692 		if (db->val_to_user == NULL) {
    693 			db->val_to_user = cil_malloc(sizeof(*db->val_to_user) * db->num_users);
    694 		}
    695 		db->val_to_user[user->value] = user;
    696 		break;
    697 	}
    698 	case CIL_USERPREFIX: {
    699 		cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data);
    700 		break;
    701 	}
    702 	case CIL_SELINUXUSER: {
    703 		cil_list_prepend(db->selinuxusers, CIL_SELINUXUSER, node->data);
    704 		break;
    705 	}
    706 	case CIL_SELINUXUSERDEFAULT: {
    707 		cil_list_append(db->selinuxusers, CIL_SELINUXUSERDEFAULT, node->data);
    708 		break;
    709 	}
    710 	case CIL_NETIFCON: {
    711 		struct cil_sort *sort = db->netifcon;
    712 		uint32_t count = sort->count;
    713 		uint32_t i = sort->index;
    714 		if (sort->array == NULL) {
    715 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    716 		}
    717 		sort->array[i] = node->data;
    718 		sort->index++;
    719 		break;
    720 	}
    721 	case CIL_IBENDPORTCON: {
    722 		struct cil_sort *sort = db->ibendportcon;
    723 		uint32_t count = sort->count;
    724 		uint32_t i = sort->index;
    725 
    726 		if (!sort->array)
    727 			sort->array = cil_malloc(sizeof(*sort->array) * count);
    728 		sort->array[i] = node->data;
    729 		sort->index++;
    730 		break;
    731 	}
    732 	case CIL_FSUSE: {
    733 		struct cil_sort *sort = db->fsuse;
    734 		uint32_t count = sort->count;
    735 		uint32_t i = sort->index;
    736 		if (sort->array == NULL) {
    737 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    738 		}
    739 		sort->array[i] = node->data;
    740 		sort->index++;
    741 		break;
    742 	}
    743 	case CIL_GENFSCON: {
    744 		struct cil_sort *sort = db->genfscon;
    745 		uint32_t count = sort->count;
    746 		uint32_t i = sort->index;
    747 		if (sort->array == NULL) {
    748 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    749 		}
    750 		sort->array[i] = node->data;
    751 		sort->index++;
    752 		break;
    753 	}
    754 	case CIL_FILECON: {
    755 		struct cil_sort *sort = db->filecon;
    756 		uint32_t count = sort->count;
    757 		uint32_t i = sort->index;
    758 		if (sort->array == NULL) {
    759 		sort->array = cil_malloc(sizeof(*sort->array)*count);
    760 		}
    761 		sort->array[i] = node->data;
    762 		sort->index++;
    763 		break;
    764 	}
    765 	case CIL_NODECON: {
    766 		struct cil_sort *sort = db->nodecon;
    767 		uint32_t count = sort->count;
    768 		uint32_t i = sort->index;
    769 		if (sort->array == NULL) {
    770 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    771 		}
    772 		sort->array[i] = node->data;
    773 		sort->index++;
    774 		break;
    775 	}
    776 	case CIL_IBPKEYCON: {
    777 		struct cil_sort *sort = db->ibpkeycon;
    778 		uint32_t count = sort->count;
    779 		uint32_t i = sort->index;
    780 
    781 		if (!sort->array)
    782 			sort->array = cil_malloc(sizeof(*sort->array) * count);
    783 		sort->array[i] = node->data;
    784 		sort->index++;
    785 		break;
    786 	}
    787 	case CIL_PORTCON: {
    788 		struct cil_sort *sort = db->portcon;
    789 		uint32_t count = sort->count;
    790 		uint32_t i = sort->index;
    791 		if (sort->array == NULL) {
    792 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    793 		}
    794 		sort->array[i] = node->data;
    795 		sort->index++;
    796 		break;
    797 	}
    798 	case CIL_PIRQCON: {
    799 		struct cil_sort *sort = db->pirqcon;
    800 		uint32_t count = sort->count;
    801 		uint32_t i = sort->index;
    802 		if (sort->array == NULL) {
    803 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    804 		}
    805 		sort->array[i] = node->data;
    806 		sort->index++;
    807 		break;
    808 	}
    809 	case CIL_IOMEMCON: {
    810 		struct cil_sort *sort = db->iomemcon;
    811 		uint32_t count = sort->count;
    812 		uint32_t i = sort->index;
    813 		if (sort->array == NULL) {
    814 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    815 		}
    816 		sort->array[i] = node->data;
    817 		sort->index++;
    818 		break;
    819 	}
    820 	case CIL_IOPORTCON: {
    821 		struct cil_sort *sort = db->ioportcon;
    822 		uint32_t count = sort->count;
    823 		uint32_t i = sort->index;
    824 		if (sort->array == NULL) {
    825 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    826 		}
    827 		sort->array[i] = node->data;
    828 		sort->index++;
    829 		break;
    830 	}
    831 	case CIL_PCIDEVICECON: {
    832 		struct cil_sort *sort = db->pcidevicecon;
    833 		uint32_t count = sort->count;
    834 		uint32_t i = sort->index;
    835 		if (sort->array == NULL) {
    836 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    837 		}
    838 		sort->array[i] = node->data;
    839 		sort->index++;
    840 		break;
    841 	}
    842 	case CIL_DEVICETREECON: {
    843 		struct cil_sort *sort = db->devicetreecon;
    844 		uint32_t count = sort->count;
    845 		uint32_t i = sort->index;
    846 		if (sort->array == NULL) {
    847 			sort->array = cil_malloc(sizeof(*sort->array)*count);
    848 		}
    849 		sort->array[i] = node->data;
    850 		sort->index++;
    851 		break;
    852 	}
    853 	default:
    854 		break;
    855 	}
    856 
    857 	return SEPOL_OK;
    858 }
    859 
    860 static int __evaluate_type_expression(struct cil_typeattribute *attr, struct cil_db *db)
    861 {
    862 	int rc;
    863 
    864 	attr->types = cil_malloc(sizeof(*attr->types));
    865 	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->types, db->num_types, db);
    866 	if (rc != SEPOL_OK) {
    867 		cil_log(CIL_ERR, "Failed to expand type attribute to bitmap\n");
    868 		ebitmap_destroy(attr->types);
    869 		free(attr->types);
    870 		attr->types = NULL;
    871 	}
    872 	return rc;
    873 }
    874 
    875 static int __cil_type_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
    876 {
    877 	int rc = SEPOL_ERR;
    878 	struct cil_tree_node *node = datum->nodes->head->data;
    879 
    880 	ebitmap_init(bitmap);
    881 
    882 	if (node->flavor == CIL_TYPEATTRIBUTE) {
    883 		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
    884 		if (attr->types == NULL) {
    885 			rc = __evaluate_type_expression(attr, db);
    886 			if (rc != SEPOL_OK) goto exit;
    887 		}
    888 		ebitmap_union(bitmap, attr->types);
    889 	} else if (node->flavor == CIL_TYPEALIAS) {
    890 		struct cil_alias *alias = (struct cil_alias *)datum;
    891 		struct cil_type *type = alias->actual;
    892 		if (ebitmap_set_bit(bitmap, type->value, 1)) {
    893 			cil_log(CIL_ERR, "Failed to set type bit\n");
    894 			ebitmap_destroy(bitmap);
    895 			goto exit;
    896 		}
    897 	} else {
    898 		struct cil_type *type = (struct cil_type *)datum;
    899 		if (ebitmap_set_bit(bitmap, type->value, 1)) {
    900 			cil_log(CIL_ERR, "Failed to set type bit\n");
    901 			ebitmap_destroy(bitmap);
    902 			goto exit;
    903 		}
    904 	}
    905 
    906 	return SEPOL_OK;
    907 
    908 exit:
    909 	return rc;
    910 }
    911 
    912 static int __evaluate_user_expression(struct cil_userattribute *attr, struct cil_db *db)
    913 {
    914 	int rc;
    915 
    916 	attr->users = cil_malloc(sizeof(*attr->users));
    917 	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->users, db->num_users, db);
    918 	if (rc != SEPOL_OK) {
    919 		cil_log(CIL_ERR, "Failed to expand user attribute to bitmap\n");
    920 		ebitmap_destroy(attr->users);
    921 		free(attr->users);
    922 		attr->users = NULL;
    923 	}
    924 	return rc;
    925 }
    926 
    927 static int __cil_user_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
    928 {
    929 	int rc = SEPOL_ERR;
    930 	struct cil_tree_node *node = datum->nodes->head->data;
    931 	struct cil_userattribute *attr = NULL;
    932 	struct cil_user *user = NULL;
    933 
    934 	ebitmap_init(bitmap);
    935 
    936 	if (node->flavor == CIL_USERATTRIBUTE) {
    937 		attr = (struct cil_userattribute *)datum;
    938 		if (attr->users == NULL) {
    939 			rc = __evaluate_user_expression(attr, db);
    940 			if (rc != SEPOL_OK) {
    941 				goto exit;
    942 			}
    943 		}
    944 		ebitmap_union(bitmap, attr->users);
    945 	} else {
    946 		user = (struct cil_user *)datum;
    947 		if (ebitmap_set_bit(bitmap, user->value, 1)) {
    948 			cil_log(CIL_ERR, "Failed to set user bit\n");
    949 			ebitmap_destroy(bitmap);
    950 			goto exit;
    951 		}
    952 	}
    953 
    954 	return SEPOL_OK;
    955 
    956 exit:
    957 	return rc;
    958 }
    959 
    960 static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db)
    961 {
    962 	int rc;
    963 
    964 	attr->roles = cil_malloc(sizeof(*attr->roles));
    965 	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->roles, db->num_roles, db);
    966 	if (rc != SEPOL_OK) {
    967 		cil_log(CIL_ERR, "Failed to expand role attribute to bitmap\n");
    968 		ebitmap_destroy(attr->roles);
    969 		free(attr->roles);
    970 		attr->roles = NULL;
    971 	}
    972 	return rc;
    973 }
    974 
    975 static int __cil_role_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
    976 {
    977 	int rc = SEPOL_ERR;
    978 	struct cil_tree_node *node = datum->nodes->head->data;
    979 
    980 	ebitmap_init(bitmap);
    981 
    982 	if (node->flavor == CIL_ROLEATTRIBUTE) {
    983 		struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
    984 		if (attr->roles == NULL) {
    985 			rc = __evaluate_role_expression(attr, db);
    986 			if (rc != SEPOL_OK) goto exit;
    987 		}
    988 		ebitmap_union(bitmap, attr->roles);
    989 	} else {
    990 		struct cil_role *role = (struct cil_role *)datum;
    991 		if (ebitmap_set_bit(bitmap, role->value, 1)) {
    992 			cil_log(CIL_ERR, "Failed to set role bit\n");
    993 			ebitmap_destroy(bitmap);
    994 			goto exit;
    995 		}
    996 	}
    997 
    998 	return SEPOL_OK;
    999 
   1000 exit:
   1001 	return rc;
   1002 }
   1003 
   1004 static int __evaluate_permissionx_expression(struct cil_permissionx *permx, struct cil_db *db)
   1005 {
   1006 	int rc;
   1007 
   1008 	permx->perms = cil_malloc(sizeof(*permx->perms));
   1009 	ebitmap_init(permx->perms);
   1010 
   1011 	rc = __cil_expr_to_bitmap(permx->expr_str, permx->perms, 0x10000, db); // max is one more than 0xFFFF
   1012 	if (rc != SEPOL_OK) {
   1013 		cil_log(CIL_ERR, "Failed to expand permissionx expression\n");
   1014 		ebitmap_destroy(permx->perms);
   1015 		free(permx->perms);
   1016 		permx->perms = NULL;
   1017 	}
   1018 
   1019 	return rc;
   1020 }
   1021 
   1022 static int __cil_permx_str_to_int(char *permx_str, uint16_t *val)
   1023 {
   1024 	char *endptr = NULL;
   1025 	long lval = strtol(permx_str, &endptr, 0);
   1026 
   1027 	if (*endptr != '\0') {
   1028 		cil_log(CIL_ERR, "permissionx value %s not valid number\n", permx_str);
   1029 		goto exit;
   1030 	}
   1031 	if (lval < 0x0000 || lval > 0xFFFF) {
   1032 		cil_log(CIL_ERR, "permissionx value %s must be between 0x0000 and 0xFFFF\n", permx_str);
   1033 		goto exit;
   1034 	}
   1035 
   1036 	*val = (uint16_t)lval;
   1037 
   1038 	return SEPOL_OK;
   1039 
   1040 exit:
   1041 	return SEPOL_ERR;
   1042 }
   1043 
   1044 static int __cil_permx_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
   1045 {
   1046 	int rc = SEPOL_ERR;
   1047 	uint16_t val;
   1048 
   1049 	rc = __cil_permx_str_to_int((char*)datum, &val);
   1050 	if (rc != SEPOL_OK) {
   1051 		goto exit;
   1052 	}
   1053 
   1054 	ebitmap_init(bitmap);
   1055 	if (ebitmap_set_bit(bitmap, (unsigned int)val, 1)) {
   1056 		cil_log(CIL_ERR, "Failed to set permissionx bit\n");
   1057 		ebitmap_destroy(bitmap);
   1058 		goto exit;
   1059 	}
   1060 
   1061 	return SEPOL_OK;
   1062 
   1063 exit:
   1064 	return rc;
   1065 }
   1066 
   1067 static int __cil_perm_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
   1068 {
   1069 	struct cil_perm *perm = (struct cil_perm *)datum;
   1070 	unsigned int value = perm->value;
   1071 
   1072 	ebitmap_init(bitmap);
   1073 	if (ebitmap_set_bit(bitmap, value, 1)) {
   1074 		cil_log(CIL_INFO, "Failed to set perm bit\n");
   1075 		ebitmap_destroy(bitmap);
   1076 		return SEPOL_ERR;
   1077 	}
   1078 
   1079 	return SEPOL_OK;
   1080 }
   1081 
   1082 static int __evaluate_cat_expression(struct cil_cats *cats, struct cil_db *db)
   1083 {
   1084 	int rc = SEPOL_ERR;
   1085 	ebitmap_t bitmap;
   1086 	struct cil_list *new;
   1087 	struct cil_list_item *curr;
   1088 
   1089 	if (cats->evaluated == CIL_TRUE) {
   1090 		return SEPOL_OK;
   1091 	}
   1092 
   1093 	if (cil_verify_is_list(cats->datum_expr, CIL_CAT)) {
   1094 		return SEPOL_OK;
   1095 	}
   1096 
   1097 	ebitmap_init(&bitmap);
   1098 	rc = __cil_expr_to_bitmap(cats->datum_expr, &bitmap, db->num_cats, db);
   1099 	if (rc != SEPOL_OK) {
   1100 		cil_log(CIL_ERR, "Failed to expand category expression to bitmap\n");
   1101 		ebitmap_destroy(&bitmap);
   1102 		goto exit;
   1103 	}
   1104 
   1105 	cil_list_init(&new, CIL_CAT);
   1106 
   1107 	cil_list_for_each(curr, db->catorder) {
   1108 		struct cil_cat *cat = curr->data;
   1109 		if (ebitmap_get_bit(&bitmap, cat->value)) {
   1110 			cil_list_append(new, CIL_DATUM, cat);
   1111 		}
   1112 	}
   1113 
   1114 	ebitmap_destroy(&bitmap);
   1115 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
   1116 	cats->datum_expr = new;
   1117 
   1118 	cats->evaluated = CIL_TRUE;
   1119 
   1120 	return SEPOL_OK;
   1121 
   1122 exit:
   1123 	return rc;
   1124 }
   1125 
   1126 static int __cil_cat_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
   1127 {
   1128 	int rc = SEPOL_ERR;
   1129 	struct cil_tree_node *node = datum->nodes->head->data;
   1130 
   1131 	ebitmap_init(bitmap);
   1132 
   1133 	if (node->flavor == CIL_CATSET) {
   1134 		struct cil_catset *catset = (struct cil_catset *)datum;
   1135 		struct cil_list_item *curr;
   1136 		if (catset->cats->evaluated == CIL_FALSE) {
   1137 			rc = __evaluate_cat_expression(catset->cats, db);
   1138 			if (rc != SEPOL_OK) goto exit;
   1139 		}
   1140 		for (curr = catset->cats->datum_expr->head; curr; curr = curr->next) {
   1141 			struct cil_cat *cat = (struct cil_cat *)curr->data;
   1142 			if (ebitmap_set_bit(bitmap, cat->value, 1)) {
   1143 				cil_log(CIL_ERR, "Failed to set cat bit\n");
   1144 				ebitmap_destroy(bitmap);
   1145 				goto exit;
   1146 			}
   1147 		}
   1148 	} else if (node->flavor == CIL_CATALIAS) {
   1149 		struct cil_alias *alias = (struct cil_alias *)datum;
   1150 		struct cil_cat *cat = alias->actual;
   1151 		if (ebitmap_set_bit(bitmap, cat->value, 1)) {
   1152 			cil_log(CIL_ERR, "Failed to set cat bit\n");
   1153 			ebitmap_destroy(bitmap);
   1154 			goto exit;
   1155 		}
   1156 	} else {
   1157 		struct cil_cat *cat = (struct cil_cat *)datum;
   1158 		if (ebitmap_set_bit(bitmap, cat->value, 1)) {
   1159 			cil_log(CIL_ERR, "Failed to set cat bit\n");
   1160 			ebitmap_destroy(bitmap);
   1161 			goto exit;
   1162 		}
   1163 	}
   1164 
   1165 	return SEPOL_OK;
   1166 
   1167 exit:
   1168 	return rc;
   1169 }
   1170 
   1171 static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
   1172 {
   1173 	int rc = SEPOL_ERR;
   1174 	struct cil_symtab_datum *d1 = i1->data;
   1175 	struct cil_symtab_datum *d2 = i2->data;
   1176 	struct cil_tree_node *n1 = d1->nodes->head->data;
   1177 	struct cil_tree_node *n2 = d2->nodes->head->data;
   1178 	struct cil_cat *c1 = (struct cil_cat *)d1;
   1179 	struct cil_cat *c2 = (struct cil_cat *)d2;
   1180 	int i;
   1181 
   1182 	if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) {
   1183 		cil_log(CIL_ERR, "Category sets cannont be used in a category range\n");
   1184 		goto exit;
   1185 	}
   1186 
   1187 	if (n1->flavor == CIL_CATALIAS) {
   1188 		struct cil_alias *alias = (struct cil_alias *)d1;
   1189 		c1 = alias->actual;
   1190 	}
   1191 
   1192 	if (n2->flavor == CIL_CATALIAS) {
   1193 		struct cil_alias *alias = (struct cil_alias *)d2;
   1194 		c2 = alias->actual;
   1195 	}
   1196 
   1197 	if (c1->value > c2->value) {
   1198 		cil_log(CIL_ERR, "Invalid category range\n");
   1199 		goto exit;
   1200 	}
   1201 
   1202 	for (i = c1->value; i <= c2->value; i++) {
   1203 		if (ebitmap_set_bit(bitmap, i, 1)) {
   1204 			cil_log(CIL_ERR, "Failed to set cat bit\n");
   1205 			ebitmap_destroy(bitmap);
   1206 			goto exit;
   1207 		}
   1208 	}
   1209 
   1210 	return SEPOL_OK;
   1211 
   1212 exit:
   1213 	return rc;
   1214 }
   1215 
   1216 static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
   1217 {
   1218 	int rc = SEPOL_ERR;
   1219 	char *p1 = i1->data;
   1220 	char *p2 = i2->data;
   1221 	uint16_t v1;
   1222 	uint16_t v2;
   1223 	uint32_t i;
   1224 
   1225 	rc = __cil_permx_str_to_int(p1, &v1);
   1226 	if (rc != SEPOL_OK) {
   1227 		goto exit;
   1228 	}
   1229 
   1230 	rc = __cil_permx_str_to_int(p2, &v2);
   1231 	if (rc != SEPOL_OK) {
   1232 		goto exit;
   1233 	}
   1234 
   1235 	for (i = v1; i <= v2; i++) {
   1236 		if (ebitmap_set_bit(bitmap, i, 1)) {
   1237 			cil_log(CIL_ERR, "Failed to set permissionx bit\n");
   1238 			ebitmap_destroy(bitmap);
   1239 			goto exit;
   1240 		}
   1241 	}
   1242 
   1243 	return SEPOL_OK;
   1244 
   1245 exit:
   1246 	return rc;
   1247 }
   1248 
   1249 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)
   1250 {
   1251 	int rc = SEPOL_ERR;
   1252 
   1253 	if (curr->flavor == CIL_DATUM) {
   1254 		switch (flavor) {
   1255 		case CIL_TYPE:
   1256 			rc = __cil_type_to_bitmap(curr->data, bitmap, db);
   1257 			break;
   1258 		case CIL_ROLE:
   1259 			rc = __cil_role_to_bitmap(curr->data, bitmap, db);
   1260 			break;
   1261 		case CIL_USER:
   1262 			rc = __cil_user_to_bitmap(curr->data, bitmap, db);
   1263 			break;
   1264 		case CIL_PERM:
   1265 			rc = __cil_perm_to_bitmap(curr->data, bitmap, db);
   1266 			break;
   1267 		case CIL_CAT:
   1268 			rc = __cil_cat_to_bitmap(curr->data, bitmap, db);
   1269 			break;
   1270 		default:
   1271 			rc = SEPOL_ERR;
   1272 		}
   1273 	} else if (curr->flavor == CIL_LIST) {
   1274 		struct cil_list *l = curr->data;
   1275 		ebitmap_init(bitmap);
   1276 		rc = __cil_expr_to_bitmap(l, bitmap, max, db);
   1277 		if (rc != SEPOL_OK) {
   1278 			ebitmap_destroy(bitmap);
   1279 		}
   1280 	} else if (flavor == CIL_PERMISSIONX) {
   1281 		// permissionx expressions aren't resolved into anything, so curr->flavor
   1282 		// is just a CIL_STRING, not a CIL_DATUM, so just check on flavor for those
   1283 		rc = __cil_permx_to_bitmap(curr->data, bitmap, db);
   1284 	}
   1285 
   1286 	return rc;
   1287 }
   1288 
   1289 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db)
   1290 {
   1291 	int rc = SEPOL_ERR;
   1292 	struct cil_list_item *curr;
   1293 	enum cil_flavor flavor;
   1294 	ebitmap_t tmp, b1, b2;
   1295 
   1296 	if (expr == NULL || expr->head == NULL) {
   1297 		return SEPOL_OK;
   1298 	}
   1299 
   1300 	curr = expr->head;
   1301 	flavor = expr->flavor;
   1302 
   1303 	if (curr->flavor == CIL_OP) {
   1304 		enum cil_flavor op = (enum cil_flavor)curr->data;
   1305 
   1306 		if (op == CIL_ALL) {
   1307 			ebitmap_init(&b1); /* all zeros */
   1308 			rc = ebitmap_not(&tmp, &b1, max);
   1309 			ebitmap_destroy(&b1);
   1310 			if (rc != SEPOL_OK) {
   1311 				cil_log(CIL_INFO, "Failed to expand 'all' operator\n");
   1312 				ebitmap_destroy(&tmp);
   1313 				goto exit;
   1314 			}
   1315 		} else if (op == CIL_RANGE) {
   1316 			if (flavor == CIL_CAT) {
   1317 				ebitmap_init(&tmp);
   1318 				rc = __cil_cat_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
   1319 				if (rc != SEPOL_OK) {
   1320 					cil_log(CIL_INFO, "Failed to expand category range\n");
   1321 					ebitmap_destroy(&tmp);
   1322 					goto exit;
   1323 				}
   1324 			} else if (flavor == CIL_PERMISSIONX) {
   1325 				ebitmap_init(&tmp);
   1326 				rc = __cil_permissionx_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
   1327 				if (rc != SEPOL_OK) {
   1328 					cil_log(CIL_INFO, "Failed to expand category range\n");
   1329 					ebitmap_destroy(&tmp);
   1330 					goto exit;
   1331 				}
   1332 			} else {
   1333 				cil_log(CIL_INFO, "Range operation only supported for categories permissionx\n");
   1334 				rc = SEPOL_ERR;
   1335 				goto exit;
   1336 			}
   1337 		} else {
   1338 			rc = __cil_expr_to_bitmap_helper(curr->next, flavor, &b1, max, db);
   1339 			if (rc != SEPOL_OK) {
   1340 				cil_log(CIL_INFO, "Failed to get first operand bitmap\n");
   1341 				goto exit;
   1342 			}
   1343 
   1344 			if (op == CIL_NOT) {
   1345 				rc = ebitmap_not(&tmp, &b1, max);
   1346 				ebitmap_destroy(&b1);
   1347 				if (rc != SEPOL_OK) {
   1348 					cil_log(CIL_INFO, "Failed to NOT bitmap\n");
   1349 					ebitmap_destroy(&tmp);
   1350 					goto exit;
   1351 				}
   1352 			} else {
   1353 				rc = __cil_expr_to_bitmap_helper(curr->next->next, flavor, &b2, max, db);
   1354 				if (rc != SEPOL_OK) {
   1355 					cil_log(CIL_INFO, "Failed to get second operand bitmap\n");
   1356 					ebitmap_destroy(&b1);
   1357 					goto exit;
   1358 				}
   1359 
   1360 				if (op == CIL_OR) {
   1361 					rc = ebitmap_or(&tmp, &b1, &b2);
   1362 				} else if (op == CIL_AND) {
   1363 					rc = ebitmap_and(&tmp, &b1, &b2);
   1364 				} else if (op == CIL_XOR) {
   1365 					rc = ebitmap_xor(&tmp, &b1, &b2);
   1366 				} else {
   1367 					rc = SEPOL_ERR;
   1368 				}
   1369 				ebitmap_destroy(&b1);
   1370 				ebitmap_destroy(&b2);
   1371 				if (rc != SEPOL_OK) {
   1372 					cil_log(CIL_INFO, "Failed to apply operator to bitmaps\n");
   1373 					ebitmap_destroy(&tmp);
   1374 					goto exit;
   1375 				}
   1376 			}
   1377 		}
   1378 	} else {
   1379 		ebitmap_init(&tmp);
   1380 		for (;curr; curr = curr->next) {
   1381 			rc = __cil_expr_to_bitmap_helper(curr, flavor, &b2, max, db);
   1382 			if (rc != SEPOL_OK) {
   1383 				cil_log(CIL_INFO, "Failed to get operand in list\n");
   1384 				ebitmap_destroy(&tmp);
   1385 				goto exit;
   1386 			}
   1387 			b1 = tmp;
   1388 			rc = ebitmap_or(&tmp, &b1, &b2);
   1389 			ebitmap_destroy(&b1);
   1390 			ebitmap_destroy(&b2);
   1391 			if (rc != SEPOL_OK) {
   1392 				cil_log(CIL_INFO, "Failed to OR operands in list\n");
   1393 				ebitmap_destroy(&tmp);
   1394 				goto exit;
   1395 			}
   1396 
   1397 		}
   1398 	}
   1399 
   1400 	ebitmap_union(out, &tmp);
   1401 	ebitmap_destroy(&tmp);
   1402 
   1403 	return SEPOL_OK;
   1404 
   1405 exit:
   1406 	return rc;
   1407 }
   1408 
   1409 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db)
   1410 {
   1411 	int rc = SEPOL_ERR;
   1412 	struct cil_list_item *expr;
   1413 
   1414 	ebitmap_init(out);
   1415 
   1416 	if (expr_list == NULL) {
   1417 		return SEPOL_OK;
   1418 	}
   1419 
   1420 	cil_list_for_each(expr, expr_list) {
   1421 		ebitmap_t bitmap;
   1422 		struct cil_list *l = (struct cil_list *)expr->data;
   1423 		ebitmap_init(&bitmap);
   1424 		rc = __cil_expr_to_bitmap(l, &bitmap, max, db);
   1425 		if (rc != SEPOL_OK) {
   1426 			cil_log(CIL_INFO, "Failed to expand expression list to bitmap\n");
   1427 			ebitmap_destroy(&bitmap);
   1428 			goto exit;
   1429 		}
   1430 		ebitmap_union(out, &bitmap);
   1431 		ebitmap_destroy(&bitmap);
   1432 	}
   1433 
   1434 	return SEPOL_OK;
   1435 
   1436 exit:
   1437 	return SEPOL_ERR;
   1438 }
   1439 
   1440 static int cil_typeattribute_used(struct cil_typeattribute *attr, struct cil_db *db)
   1441 {
   1442 	if (!attr->used) {
   1443 		return CIL_FALSE;
   1444 	}
   1445 
   1446 	if (attr->used & CIL_ATTR_EXPAND_FALSE) {
   1447 		return CIL_TRUE;
   1448 	}
   1449 
   1450 	if (attr->used & CIL_ATTR_EXPAND_TRUE) {
   1451 		return CIL_FALSE;
   1452 	}
   1453 
   1454 	if (attr->used & CIL_ATTR_CONSTRAINT) {
   1455 		return CIL_TRUE;
   1456 	}
   1457 
   1458 	if (db->attrs_expand_generated || attr->used == CIL_ATTR_NEVERALLOW) {
   1459 		if (strcmp(DATUM(attr)->name, GEN_REQUIRE_ATTR) == 0) {
   1460 			return CIL_FALSE;
   1461 		} else if (strstr(DATUM(attr)->name, TYPEATTR_INFIX) != NULL) {
   1462 			return CIL_FALSE;
   1463 		}
   1464 
   1465 		if (attr->used == CIL_ATTR_NEVERALLOW) {
   1466 			return CIL_TRUE;
   1467 		}
   1468 	}
   1469 
   1470 	if (attr->used == CIL_ATTR_AVRULE) {
   1471 		if (ebitmap_cardinality(attr->types) < db->attrs_expand_size) {
   1472 			return CIL_FALSE;
   1473 		}
   1474 	}
   1475 
   1476 	return CIL_TRUE;
   1477 }
   1478 
   1479 static void __mark_neverallow_attrs(struct cil_list *expr_list)
   1480 {
   1481 	struct cil_list_item *curr;
   1482 
   1483 	cil_list_for_each(curr, expr_list) {
   1484 		if (curr->flavor == CIL_DATUM) {
   1485 			if (NODE(curr->data)->flavor == CIL_TYPEATTRIBUTE) {
   1486 				struct cil_typeattribute *attr = curr->data;
   1487 				if (strstr(DATUM(attr)->name, TYPEATTR_INFIX)) {
   1488 					__mark_neverallow_attrs(attr->expr_list);
   1489 				} else {
   1490 					attr->used |= CIL_ATTR_NEVERALLOW;
   1491 				}
   1492 			}
   1493 		} else if (curr->flavor == CIL_LIST) {
   1494 			 __mark_neverallow_attrs(curr->data);
   1495 		}
   1496 	}
   1497 }
   1498 
   1499 static int __cil_post_db_neverallow_attr_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
   1500 {
   1501 	switch (node->flavor) {
   1502 	case CIL_BLOCK: {
   1503 		struct cil_block *blk = node->data;
   1504 		if (blk->is_abstract == CIL_TRUE) {
   1505 			*finished = CIL_TREE_SKIP_HEAD;
   1506 		}
   1507 		break;
   1508 	}
   1509 	case CIL_MACRO: {
   1510 		*finished = CIL_TREE_SKIP_HEAD;
   1511 		break;
   1512 	}
   1513 	case CIL_TYPEATTRIBUTE: {
   1514 		struct cil_typeattribute *attr = node->data;
   1515 		if ((attr->used & CIL_ATTR_NEVERALLOW) &&
   1516 		    strstr(DATUM(attr)->name, TYPEATTR_INFIX)) {
   1517 			__mark_neverallow_attrs(attr->expr_list);
   1518 		}
   1519 		break;
   1520 	}
   1521 	default:
   1522 		break;
   1523 	}
   1524 
   1525 	return SEPOL_OK;
   1526 }
   1527 
   1528 static int __cil_post_db_attr_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   1529 {
   1530 	int rc = SEPOL_ERR;
   1531 	struct cil_db *db = extra_args;
   1532 
   1533 	switch (node->flavor) {
   1534 	case CIL_BLOCK: {
   1535 		struct cil_block *blk = node->data;
   1536 		if (blk->is_abstract == CIL_TRUE) {
   1537 			*finished = CIL_TREE_SKIP_HEAD;
   1538 		}
   1539 		break;
   1540 	}
   1541 	case CIL_MACRO: {
   1542 		*finished = CIL_TREE_SKIP_HEAD;
   1543 		break;
   1544 	}
   1545 	case CIL_TYPEATTRIBUTE: {
   1546 		struct cil_typeattribute *attr = node->data;
   1547 		if (attr->types == NULL) {
   1548 			rc = __evaluate_type_expression(attr, db);
   1549 			if (rc != SEPOL_OK) goto exit;
   1550 		}
   1551 		attr->keep = cil_typeattribute_used(attr, db);
   1552 		break;
   1553 	}
   1554 	case CIL_ROLEATTRIBUTE: {
   1555 		struct cil_roleattribute *attr = node->data;
   1556 		if (attr->roles == NULL) {
   1557 			rc = __evaluate_role_expression(attr, db);
   1558 			if (rc != SEPOL_OK) goto exit;
   1559 		}
   1560 		break;
   1561 	}
   1562 	case CIL_AVRULEX: {
   1563 		struct cil_avrule *rule = node->data;
   1564 		if (rule->perms.x.permx_str == NULL) {
   1565 			rc = __evaluate_permissionx_expression(rule->perms.x.permx, db);
   1566 			if (rc != SEPOL_OK) goto exit;
   1567 		}
   1568 		break;
   1569 	}
   1570 	case CIL_PERMISSIONX: {
   1571 		struct cil_permissionx *permx = node->data;
   1572 		rc = __evaluate_permissionx_expression(permx, db);
   1573 		if (rc != SEPOL_OK) goto exit;
   1574 		break;
   1575 	}
   1576 	case CIL_USERATTRIBUTE: {
   1577 		struct cil_userattribute *attr = node->data;
   1578 		if (attr->users == NULL) {
   1579 			rc = __evaluate_user_expression(attr, db);
   1580 			if (rc != SEPOL_OK) {
   1581 				goto exit;
   1582 			}
   1583 		}
   1584 		break;
   1585 	}
   1586 	default:
   1587 		break;
   1588 	}
   1589 
   1590 	return SEPOL_OK;
   1591 
   1592 exit:
   1593 	return rc;
   1594 }
   1595 
   1596 static int __cil_role_assign_types(struct cil_role *role, struct cil_symtab_datum *datum)
   1597 {
   1598 	struct cil_tree_node *node = datum->nodes->head->data;
   1599 
   1600 	if (role->types == NULL) {
   1601 		role->types = cil_malloc(sizeof(*role->types));
   1602 		ebitmap_init(role->types);
   1603 	}
   1604 
   1605 	if (node->flavor == CIL_TYPE) {
   1606 		struct cil_type *type = (struct cil_type *)datum;
   1607 		if (ebitmap_set_bit(role->types, type->value, 1)) {
   1608 			cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
   1609 			goto exit;
   1610 		}
   1611 	} else if (node->flavor == CIL_TYPEALIAS) {
   1612 		struct cil_alias *alias = (struct cil_alias *)datum;
   1613 		struct cil_type *type = alias->actual;
   1614 		if (ebitmap_set_bit(role->types, type->value, 1)) {
   1615 			cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
   1616 			goto exit;
   1617 		}
   1618 	} else if (node->flavor == CIL_TYPEATTRIBUTE) {
   1619 		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
   1620 		ebitmap_union(role->types, attr->types);
   1621 	}
   1622 
   1623 	return SEPOL_OK;
   1624 
   1625 exit:
   1626 	return SEPOL_ERR;
   1627 }
   1628 
   1629 static int __cil_post_db_roletype_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   1630 {
   1631 	int rc = SEPOL_ERR;
   1632 	struct cil_db *db = extra_args;
   1633 
   1634 	switch (node->flavor) {
   1635 	case CIL_BLOCK: {
   1636 		struct cil_block *blk = node->data;
   1637 		if (blk->is_abstract == CIL_TRUE) {
   1638 			*finished = CIL_TREE_SKIP_HEAD;
   1639 		}
   1640 		break;
   1641 	}
   1642 	case CIL_MACRO: {
   1643 		*finished = CIL_TREE_SKIP_HEAD;
   1644 		break;
   1645 	}
   1646 	case CIL_ROLETYPE: {
   1647 		struct cil_roletype *roletype = node->data;
   1648 		struct cil_symtab_datum *role_datum = roletype->role;
   1649 		struct cil_symtab_datum *type_datum = roletype->type;
   1650 		struct cil_tree_node *role_node = role_datum->nodes->head->data;
   1651 
   1652 		if (role_node->flavor == CIL_ROLEATTRIBUTE) {
   1653 			struct cil_roleattribute *attr = roletype->role;
   1654 			ebitmap_node_t *rnode;
   1655 			unsigned int i;
   1656 
   1657 			ebitmap_for_each_bit(attr->roles, rnode, i) {
   1658 				struct cil_role *role = NULL;
   1659 
   1660 				if (!ebitmap_get_bit(attr->roles, i)) {
   1661 					continue;
   1662 				}
   1663 
   1664 				role = db->val_to_role[i];
   1665 
   1666 				rc = __cil_role_assign_types(role, type_datum);
   1667 				if (rc != SEPOL_OK) {
   1668 					goto exit;
   1669 				}
   1670 			}
   1671 		} else {
   1672 			struct cil_role *role = roletype->role;
   1673 
   1674 			rc = __cil_role_assign_types(role, type_datum);
   1675 			if (rc != SEPOL_OK) {
   1676 				goto exit;
   1677 			}
   1678 		}
   1679 		break;
   1680 	}
   1681 	default:
   1682 		break;
   1683 	}
   1684 
   1685 	return SEPOL_OK;
   1686 exit:
   1687 	cil_log(CIL_INFO, "cil_post_db_roletype_helper failed\n");
   1688 	return rc;
   1689 }
   1690 
   1691 static int __cil_user_assign_roles(struct cil_user *user, struct cil_symtab_datum *datum)
   1692 {
   1693 	struct cil_tree_node *node = datum->nodes->head->data;
   1694 	struct cil_role *role = NULL;
   1695 	struct cil_roleattribute *attr = NULL;
   1696 
   1697 	if (user->roles == NULL) {
   1698 		user->roles = cil_malloc(sizeof(*user->roles));
   1699 		ebitmap_init(user->roles);
   1700 	}
   1701 
   1702 	if (node->flavor == CIL_ROLE) {
   1703 		role = (struct cil_role *)datum;
   1704 		if (ebitmap_set_bit(user->roles, role->value, 1)) {
   1705 			cil_log(CIL_INFO, "Failed to set bit in user roles bitmap\n");
   1706 			goto exit;
   1707 		}
   1708 	} else if (node->flavor == CIL_ROLEATTRIBUTE) {
   1709 		attr = (struct cil_roleattribute *)datum;
   1710 		ebitmap_union(user->roles, attr->roles);
   1711 	}
   1712 
   1713 	return SEPOL_OK;
   1714 
   1715 exit:
   1716 	return SEPOL_ERR;
   1717 }
   1718 
   1719 static int __cil_post_db_userrole_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   1720 {
   1721 	int rc = SEPOL_ERR;
   1722 	struct cil_db *db = extra_args;
   1723 	struct cil_block *blk = NULL;
   1724 	struct cil_userrole *userrole = NULL;
   1725 	struct cil_symtab_datum *user_datum = NULL;
   1726 	struct cil_symtab_datum *role_datum = NULL;
   1727 	struct cil_tree_node *user_node = NULL;
   1728 	struct cil_userattribute *u_attr = NULL;
   1729 	unsigned int i;
   1730 	struct cil_user *user = NULL;
   1731 	ebitmap_node_t *unode = NULL;
   1732 
   1733 	switch (node->flavor) {
   1734 	case CIL_BLOCK: {
   1735 		blk = node->data;
   1736 		if (blk->is_abstract == CIL_TRUE) {
   1737 			*finished = CIL_TREE_SKIP_HEAD;
   1738 		}
   1739 		break;
   1740 	}
   1741 	case CIL_MACRO: {
   1742 		*finished = CIL_TREE_SKIP_HEAD;
   1743 		break;
   1744 	}
   1745 	case CIL_USERROLE: {
   1746 		userrole = node->data;
   1747 		user_datum = userrole->user;
   1748 		role_datum = userrole->role;
   1749 		user_node = user_datum->nodes->head->data;
   1750 
   1751 		if (user_node->flavor == CIL_USERATTRIBUTE) {
   1752 			u_attr = userrole->user;
   1753 
   1754 			ebitmap_for_each_bit(u_attr->users, unode, i) {
   1755 				if (!ebitmap_get_bit(u_attr->users, i)) {
   1756 					continue;
   1757 				}
   1758 
   1759 				user = db->val_to_user[i];
   1760 
   1761 				rc = __cil_user_assign_roles(user, role_datum);
   1762 				if (rc != SEPOL_OK) {
   1763 					goto exit;
   1764 				}
   1765 			}
   1766 		} else {
   1767 			user = userrole->user;
   1768 
   1769 			rc = __cil_user_assign_roles(user, role_datum);
   1770 			if (rc != SEPOL_OK) {
   1771 				goto exit;
   1772 			}
   1773 		}
   1774 
   1775 		break;
   1776 	}
   1777 	default:
   1778 		break;
   1779 	}
   1780 
   1781 	return SEPOL_OK;
   1782 exit:
   1783 	cil_log(CIL_INFO, "cil_post_db_userrole_helper failed\n");
   1784 	return rc;
   1785 }
   1786 
   1787 static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db)
   1788 {
   1789 	if (level->cats != NULL) {
   1790 		return __evaluate_cat_expression(level->cats, db);
   1791 	}
   1792 
   1793 	return SEPOL_OK;
   1794 }
   1795 
   1796 static int __evaluate_levelrange_expression(struct cil_levelrange *levelrange, struct cil_db *db)
   1797 {
   1798 	int rc = SEPOL_OK;
   1799 
   1800 	if (levelrange->low != NULL && levelrange->low->cats != NULL) {
   1801 		rc =  __evaluate_cat_expression(levelrange->low->cats, db);
   1802 		if (rc != SEPOL_OK) {
   1803 			goto exit;
   1804 		}
   1805 	}
   1806 	if (levelrange->high != NULL && levelrange->high->cats != NULL) {
   1807 		rc = __evaluate_cat_expression(levelrange->high->cats, db);
   1808 		if (rc != SEPOL_OK) {
   1809 			goto exit;
   1810 		}
   1811 	}
   1812 
   1813 exit:
   1814 	return rc;
   1815 }
   1816 
   1817 static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   1818 {
   1819 	int rc = SEPOL_ERR;
   1820 	struct cil_db *db = extra_args;
   1821 
   1822 	switch (node->flavor) {
   1823 	case CIL_BLOCK: {
   1824 		struct cil_block *blk = node->data;
   1825 		if (blk->is_abstract == CIL_TRUE) {
   1826 			*finished = CIL_TREE_SKIP_HEAD;
   1827 		}
   1828 		break;
   1829 	}
   1830 	case CIL_MACRO: {
   1831 		*finished = CIL_TREE_SKIP_HEAD;
   1832 		break;
   1833 	}
   1834 	case CIL_CATSET: {
   1835 		struct cil_catset *catset = node->data;
   1836 		rc = __evaluate_cat_expression(catset->cats, db);
   1837 		if (rc != SEPOL_OK) {
   1838 			goto exit;
   1839 		}
   1840 		break;
   1841 	}
   1842 	case CIL_SENSCAT: {
   1843 		struct cil_senscat *senscat = node->data;
   1844 		rc = __evaluate_cat_expression(senscat->cats, db);
   1845 		if (rc != SEPOL_OK) {
   1846 			goto exit;
   1847 		}
   1848 		break;
   1849 	}
   1850 	case CIL_LEVEL: {
   1851 		rc = __evaluate_level_expression(node->data, db);
   1852 		if (rc != SEPOL_OK) {
   1853 			goto exit;
   1854 		}
   1855 		break;
   1856 	}
   1857 	case CIL_LEVELRANGE: {
   1858 		rc = __evaluate_levelrange_expression(node->data, db);
   1859 		if (rc != SEPOL_OK) {
   1860 			goto exit;
   1861 		}
   1862 		break;
   1863 	}
   1864 	case CIL_USER: {
   1865 		struct cil_user *user = node->data;
   1866 		rc = __evaluate_level_expression(user->dftlevel, db);
   1867 		if (rc != SEPOL_OK) {
   1868 			goto exit;
   1869 		}
   1870 		rc = __evaluate_levelrange_expression(user->range, db);
   1871 		if (rc != SEPOL_OK) {
   1872 			goto exit;
   1873 		}
   1874 		break;
   1875 	}
   1876 	case CIL_SELINUXUSERDEFAULT:
   1877 	case CIL_SELINUXUSER: {
   1878 		struct cil_selinuxuser *selinuxuser = node->data;
   1879 		rc = __evaluate_levelrange_expression(selinuxuser->range, db);
   1880 		if (rc != SEPOL_OK) {
   1881 			goto exit;
   1882 		}
   1883 		break;
   1884 	}
   1885 	case CIL_RANGETRANSITION: {
   1886 		struct cil_rangetransition *rangetrans = node->data;
   1887 		rc = __evaluate_levelrange_expression(rangetrans->range, db);
   1888 		if (rc != SEPOL_OK) {
   1889 			goto exit;
   1890 		}
   1891 		break;
   1892 	}
   1893 	case CIL_CONTEXT: {
   1894 		struct cil_context *context = node->data;
   1895 		rc = __evaluate_levelrange_expression(context->range, db);
   1896 		if (rc != SEPOL_OK) {
   1897 			goto exit;
   1898 		}
   1899 		break;
   1900 	}
   1901 	case CIL_SIDCONTEXT: {
   1902 		struct cil_sidcontext *sidcontext = node->data;
   1903 		rc = __evaluate_levelrange_expression(sidcontext->context->range, db);
   1904 		if (rc != SEPOL_OK) {
   1905 			goto exit;
   1906 		}
   1907 		break;
   1908 	}
   1909 	case CIL_FILECON: {
   1910 		struct cil_filecon *filecon = node->data;
   1911 		if (filecon->context) {
   1912 			rc = __evaluate_levelrange_expression(filecon->context->range, db);
   1913 			if (rc != SEPOL_OK) {
   1914 				goto exit;
   1915 			}
   1916 		}
   1917 		break;
   1918 	}
   1919 	case CIL_IBPKEYCON: {
   1920 		struct cil_ibpkeycon *ibpkeycon = node->data;
   1921 
   1922 		rc = __evaluate_levelrange_expression(ibpkeycon->context->range, db);
   1923 		if (rc != SEPOL_OK)
   1924 			goto exit;
   1925 		break;
   1926 	}
   1927 	case CIL_IBENDPORTCON: {
   1928 		struct cil_ibendportcon *ibendportcon = node->data;
   1929 
   1930 		rc = __evaluate_levelrange_expression(ibendportcon->context->range, db);
   1931 		if (rc != SEPOL_OK)
   1932 			goto exit;
   1933 		break;
   1934 	}
   1935 	case CIL_PORTCON: {
   1936 		struct cil_portcon *portcon = node->data;
   1937 		rc = __evaluate_levelrange_expression(portcon->context->range, db);
   1938 		if (rc != SEPOL_OK) {
   1939 			goto exit;
   1940 		}
   1941 		break;
   1942 	}
   1943 	case CIL_NODECON: {
   1944 		struct cil_nodecon *nodecon = node->data;
   1945 		rc = __evaluate_levelrange_expression(nodecon->context->range, db);
   1946 		if (rc != SEPOL_OK) {
   1947 			goto exit;
   1948 		}
   1949 		break;
   1950 	}
   1951 	case CIL_GENFSCON: {
   1952 		struct cil_genfscon *genfscon = node->data;
   1953 		rc = __evaluate_levelrange_expression(genfscon->context->range, db);
   1954 		if (rc != SEPOL_OK) {
   1955 			goto exit;
   1956 		}
   1957 		break;
   1958 	}
   1959 	case CIL_NETIFCON: {
   1960 		struct cil_netifcon *netifcon = node->data;
   1961 		rc = __evaluate_levelrange_expression(netifcon->if_context->range, db);
   1962 		if (rc != SEPOL_OK) {
   1963 			goto exit;
   1964 		}
   1965 		rc = __evaluate_levelrange_expression(netifcon->packet_context->range, db);
   1966 		if (rc != SEPOL_OK) {
   1967 			goto exit;
   1968 		}
   1969 		break;
   1970 	}
   1971 	case CIL_PIRQCON: {
   1972 		struct cil_pirqcon *pirqcon = node->data;
   1973 		rc = __evaluate_levelrange_expression(pirqcon->context->range, db);
   1974 		if (rc != SEPOL_OK) {
   1975 			goto exit;
   1976 		}
   1977 		break;
   1978 	}
   1979 	case CIL_IOMEMCON: {
   1980 		struct cil_iomemcon *iomemcon = node->data;
   1981 		rc = __evaluate_levelrange_expression(iomemcon->context->range, db);
   1982 		if (rc != SEPOL_OK) {
   1983 			goto exit;
   1984 		}
   1985 		break;
   1986 	}
   1987 	case CIL_IOPORTCON: {
   1988 		struct cil_ioportcon *ioportcon = node->data;
   1989 		rc = __evaluate_levelrange_expression(ioportcon->context->range, db);
   1990 		if (rc != SEPOL_OK) {
   1991 			goto exit;
   1992 		}
   1993 		break;
   1994 	}
   1995 	case CIL_PCIDEVICECON: {
   1996 		struct cil_pcidevicecon *pcidevicecon = node->data;
   1997 		rc = __evaluate_levelrange_expression(pcidevicecon->context->range, db);
   1998 		if (rc != SEPOL_OK) {
   1999 			goto exit;
   2000 		}
   2001 		break;
   2002 	}
   2003 	case CIL_DEVICETREECON: {
   2004 		struct cil_devicetreecon *devicetreecon = node->data;
   2005 		rc = __evaluate_levelrange_expression(devicetreecon->context->range, db);
   2006 		if (rc != SEPOL_OK) {
   2007 			goto exit;
   2008 		}
   2009 		break;
   2010 	}
   2011 	case CIL_FSUSE: {
   2012 		struct cil_fsuse *fsuse = node->data;
   2013 		rc = __evaluate_levelrange_expression(fsuse->context->range, db);
   2014 		if (rc != SEPOL_OK) {
   2015 			goto exit;
   2016 		}
   2017 		break;
   2018 	}
   2019 	default:
   2020 		break;
   2021 	}
   2022 
   2023 	return SEPOL_OK;
   2024 
   2025 exit:
   2026 	return rc;
   2027 }
   2028 
   2029 struct perm_to_list {
   2030 	enum cil_flavor flavor;
   2031 	ebitmap_t *perms;
   2032 	struct cil_list *new_list;
   2033 };
   2034 
   2035 static int __perm_bits_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
   2036 {
   2037 	struct perm_to_list *perm_args = (struct perm_to_list *)args;
   2038 	ebitmap_t *perms = perm_args->perms;
   2039 	struct cil_list *new_list = perm_args->new_list;
   2040 	struct cil_perm *perm = (struct cil_perm *)d;
   2041 	unsigned int value = perm->value;
   2042 
   2043 	if (!ebitmap_get_bit(perms, value)) {
   2044 		return SEPOL_OK;
   2045 	}
   2046 
   2047 	cil_list_append(new_list, CIL_DATUM, d);
   2048 
   2049 	return SEPOL_OK;
   2050 }
   2051 
   2052 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)
   2053 {
   2054 	int rc = SEPOL_ERR;
   2055 	struct perm_to_list args;
   2056 	ebitmap_t bitmap;
   2057 
   2058 	if (cil_verify_is_list(perms, CIL_PERM)) {
   2059 		return SEPOL_OK;
   2060 	}
   2061 
   2062 	ebitmap_init(&bitmap);
   2063 	rc = __cil_expr_to_bitmap(perms, &bitmap, num_perms, db);
   2064 	if (rc != SEPOL_OK) {
   2065 		ebitmap_destroy(&bitmap);
   2066 		goto exit;
   2067 	}
   2068 
   2069 	cil_list_init(new_list, flavor);
   2070 
   2071 	args.flavor = flavor;
   2072 	args.perms = &bitmap;
   2073 	args.new_list = *new_list;
   2074 
   2075 	cil_symtab_map(class_symtab, __perm_bits_to_list, &args);
   2076 
   2077 	if (common_symtab != NULL) {
   2078 		cil_symtab_map(common_symtab, __perm_bits_to_list, &args);
   2079 	}
   2080 
   2081 	ebitmap_destroy(&bitmap);
   2082 	return SEPOL_OK;
   2083 
   2084 exit:
   2085 	return rc;
   2086 }
   2087 
   2088 static int __evaluate_classperms(struct cil_classperms *cp, struct cil_db *db)
   2089 {
   2090 	int rc = SEPOL_ERR;
   2091 	struct cil_class *class = cp->class;
   2092 	struct cil_class *common = class->common;
   2093 	symtab_t *common_symtab = NULL;
   2094 	struct cil_list *new_list = NULL;
   2095 
   2096 	if (common) {
   2097 		common_symtab = &common->perms;
   2098 	}
   2099 
   2100 	rc = __evaluate_perm_expression(cp->perms, CIL_PERM, &class->perms, common_symtab, class->num_perms, &new_list, db);
   2101 	if (rc != SEPOL_OK) {
   2102 		goto exit;
   2103 	}
   2104 
   2105 	if (new_list == NULL) {
   2106 		return SEPOL_OK;
   2107 	}
   2108 
   2109 	cil_list_destroy(&cp->perms, CIL_FALSE);
   2110 
   2111 	cp->perms = new_list;
   2112 
   2113 	return SEPOL_OK;
   2114 
   2115 exit:
   2116 	return rc;
   2117 }
   2118 
   2119 static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db *db)
   2120 {
   2121 	int rc = SEPOL_ERR;
   2122 	struct cil_list_item *curr;
   2123 
   2124 	cil_list_for_each(curr, classperms) {
   2125 		if (curr->flavor == CIL_CLASSPERMS) {
   2126 			struct cil_classperms *cp = curr->data;
   2127 			if (FLAVOR(cp->class) == CIL_CLASS) {
   2128 				rc = __evaluate_classperms(cp, db);
   2129 				if (rc != SEPOL_OK) {
   2130 					goto exit;
   2131 				}
   2132 			} else { /* MAP */
   2133 				struct cil_list_item *i = NULL;
   2134 				cil_list_for_each(i, cp->perms) {
   2135 					struct cil_perm *cmp = i->data;
   2136 					rc = __evaluate_classperms_list(cmp->classperms, db);
   2137 					if (rc != SEPOL_OK) {
   2138 						goto exit;
   2139 					}
   2140 				}
   2141 			}
   2142 		} else { /* SET */
   2143 			struct cil_classperms_set *cp_set = curr->data;
   2144 			struct cil_classpermission *cp = cp_set->set;
   2145 			rc = __evaluate_classperms_list(cp->classperms, db);
   2146 			if (rc != SEPOL_OK) {
   2147 				goto exit;
   2148 			}
   2149 		}
   2150 	}
   2151 
   2152 	return SEPOL_OK;
   2153 
   2154 exit:
   2155 	return rc;
   2156 }
   2157 
   2158 struct class_map_args {
   2159 	struct cil_db *db;
   2160 	int rc;
   2161 };
   2162 
   2163 static int __evaluate_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
   2164 {
   2165 	struct class_map_args *map_args = args;
   2166 	struct cil_perm *cmp = (struct cil_perm *)d;
   2167 
   2168 	int rc = __evaluate_classperms_list(cmp->classperms, map_args->db);
   2169 
   2170 	if (rc != SEPOL_OK) {
   2171 		map_args->rc = rc;
   2172 	}
   2173 
   2174 	return SEPOL_OK;
   2175 }
   2176 
   2177 static int __evaluate_map_class(struct cil_class *mc, struct cil_db *db)
   2178 {
   2179 	struct class_map_args map_args;
   2180 
   2181 	map_args.db = db;
   2182 	map_args.rc = SEPOL_OK;
   2183 	cil_symtab_map(&mc->perms, __evaluate_map_perm_classperms, &map_args);
   2184 
   2185 	return map_args.rc;
   2186 }
   2187 
   2188 static int __cil_post_db_classperms_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   2189 {
   2190 	int rc = SEPOL_ERR;
   2191 	struct cil_db *db = extra_args;
   2192 
   2193 	switch (node->flavor) {
   2194 	case CIL_BLOCK: {
   2195 		struct cil_block *blk = node->data;
   2196 		if (blk->is_abstract == CIL_TRUE) {
   2197 			*finished = CIL_TREE_SKIP_HEAD;
   2198 		}
   2199 		break;
   2200 	}
   2201 	case CIL_MACRO:
   2202 		*finished = CIL_TREE_SKIP_HEAD;
   2203 		break;
   2204 	case CIL_MAP_CLASS: {
   2205 		rc = __evaluate_map_class(node->data, db);
   2206 		if (rc != SEPOL_OK) {
   2207 			goto exit;
   2208 		}
   2209 		break;
   2210 	}
   2211 	case CIL_CLASSPERMISSION: {
   2212 		struct cil_classpermission *cp = node->data;
   2213 		rc = __evaluate_classperms_list(cp->classperms, db);
   2214 		if (rc != SEPOL_OK) {
   2215 			goto exit;
   2216 		}
   2217 		break;
   2218 	}
   2219 	case CIL_AVRULE: {
   2220 		struct cil_avrule *avrule = node->data;
   2221 		rc = __evaluate_classperms_list(avrule->perms.classperms, db);
   2222 		if (rc != SEPOL_OK) {
   2223 			goto exit;
   2224 		}
   2225 		break;
   2226 	}
   2227 	case CIL_CONSTRAIN:
   2228 	case CIL_MLSCONSTRAIN: {
   2229 		struct cil_constrain *constrain = node->data;
   2230 		rc = __evaluate_classperms_list(constrain->classperms, db);
   2231 		if (rc != SEPOL_OK) {
   2232 			goto exit;
   2233 		}
   2234 		break;
   2235 	}
   2236 	default:
   2237 		break;
   2238 	}
   2239 
   2240 	return SEPOL_OK;
   2241 
   2242 exit:
   2243 	return rc;
   2244 }
   2245 
   2246 static int __cil_post_report_conflict(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
   2247 {
   2248 	struct cil_list_item *li = extra_args;
   2249 
   2250 	if (node->flavor == CIL_BLOCK) {
   2251 		struct cil_block *blk = node->data;
   2252 		if (blk->is_abstract == CIL_TRUE) {
   2253 			*finished = CIL_TREE_SKIP_HEAD;
   2254 		}
   2255 	} else if (node->flavor == CIL_MACRO) {
   2256 		*finished = CIL_TREE_SKIP_HEAD;
   2257 	} else if (node->flavor == li->flavor) {
   2258 		if (node->data == li->data) {
   2259 			char *path = cil_tree_get_cil_path(node);
   2260 			cil_log(CIL_WARN, "  at %s:%d\n", path, node->line);
   2261 		}
   2262 	}
   2263 	return SEPOL_OK;
   2264 }
   2265 
   2266 static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar)(const void *, const void *), int (*concompar)(const void *, const void *), struct cil_db *db, enum cil_flavor flavor, const char *flavor_str)
   2267 {
   2268 	uint32_t count = sort->count;
   2269 	uint32_t i, j = 0, removed = 0;
   2270 	int rc = SEPOL_OK;
   2271 
   2272 	if (count < 2) {
   2273 		return SEPOL_OK;
   2274 	}
   2275 
   2276 	qsort(sort->array, sort->count, sizeof(sort->array), compar);
   2277 
   2278 	for (i=1; i<count; i++) {
   2279 		if (compar(&sort->array[i], &sort->array[j]) != 0) {
   2280 			j++;
   2281 		} else {
   2282 			removed++;
   2283 			if (!db->multiple_decls ||
   2284 			   concompar(&sort->array[i], &sort->array[j]) != 0) {
   2285 				struct cil_list_item li;
   2286 				int rc2;
   2287 				cil_log(CIL_WARN, "Found conflicting %s rules\n",
   2288 					flavor_str);
   2289 				rc = SEPOL_ERR;
   2290 				li.flavor = flavor;
   2291 				li.data = sort->array[i];
   2292 				rc2 = cil_tree_walk(db->ast->root,
   2293 						    __cil_post_report_conflict,
   2294 						    NULL, NULL, &li);
   2295 				if (rc2 != SEPOL_OK) goto exit;
   2296 				li.data = sort->array[j];
   2297 				rc2 = cil_tree_walk(db->ast->root,
   2298 						    __cil_post_report_conflict,
   2299 						    NULL, NULL, &li);
   2300 				if (rc2 != SEPOL_OK) goto exit;
   2301 			}
   2302 		}
   2303 		if (i != j) {
   2304 			sort->array[j] = sort->array[i];
   2305 		}
   2306 	}
   2307 
   2308 	sort->count = count - removed;
   2309 
   2310 exit:
   2311 	return rc;
   2312 }
   2313 
   2314 static int cil_post_db(struct cil_db *db)
   2315 {
   2316 	int rc = SEPOL_ERR;
   2317 
   2318 	rc = cil_tree_walk(db->ast->root, __cil_post_db_count_helper, NULL, NULL, db);
   2319 	if (rc != SEPOL_OK) {
   2320 		cil_log(CIL_INFO, "Failure during cil databse count helper\n");
   2321 		goto exit;
   2322 	}
   2323 
   2324 	rc = cil_tree_walk(db->ast->root, __cil_post_db_array_helper, NULL, NULL, db);
   2325 	if (rc != SEPOL_OK) {
   2326 		cil_log(CIL_INFO, "Failure during cil database array helper\n");
   2327 		goto exit;
   2328 	}
   2329 
   2330 	rc = cil_tree_walk(db->ast->root, __cil_post_db_neverallow_attr_helper, NULL, NULL, db);
   2331 	if (rc != SEPOL_OK) {
   2332 		cil_log(CIL_INFO, "Failed to mark attributes used by generated attributes used in neverallow rules\n");
   2333 		goto exit;
   2334 	}
   2335 
   2336 	rc = cil_tree_walk(db->ast->root, __cil_post_db_attr_helper, NULL, NULL, db);
   2337 	if (rc != SEPOL_OK) {
   2338 		cil_log(CIL_INFO, "Failed to create attribute bitmaps\n");
   2339 		goto exit;
   2340 	}
   2341 
   2342 	rc = cil_tree_walk(db->ast->root, __cil_post_db_roletype_helper, NULL, NULL, db);
   2343 	if (rc != SEPOL_OK) {
   2344 		cil_log(CIL_INFO, "Failed during roletype association\n");
   2345 		goto exit;
   2346 	}
   2347 
   2348 	rc = cil_tree_walk(db->ast->root, __cil_post_db_userrole_helper, NULL, NULL, db);
   2349 	if (rc != SEPOL_OK) {
   2350 		cil_log(CIL_INFO, "Failed during userrole association\n");
   2351 		goto exit;
   2352 	}
   2353 
   2354 	rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db);
   2355 	if (rc != SEPOL_OK) {
   2356 		cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n");
   2357 		goto exit;
   2358 	}
   2359 
   2360 	rc = cil_tree_walk(db->ast->root, __cil_post_db_cat_helper, NULL, NULL, db);
   2361 	if (rc != SEPOL_OK) {
   2362 		cil_log(CIL_INFO, "Failed to evaluate category expressions\n");
   2363 		goto exit;
   2364 	}
   2365 
   2366 	rc = __cil_post_process_context_rules(db->netifcon, cil_post_netifcon_compare, cil_post_netifcon_context_compare, db, CIL_NETIFCON, CIL_KEY_NETIFCON);
   2367 	if (rc != SEPOL_OK) {
   2368 		cil_log(CIL_ERR, "Problems processing netifcon rules\n");
   2369 		goto exit;
   2370 	}
   2371 
   2372 	rc = __cil_post_process_context_rules(db->genfscon, cil_post_genfscon_compare, cil_post_genfscon_context_compare, db, CIL_GENFSCON, CIL_KEY_GENFSCON);
   2373 	if (rc != SEPOL_OK) {
   2374 		cil_log(CIL_ERR, "Problems processing genfscon rules\n");
   2375 		goto exit;
   2376 	}
   2377 
   2378 	rc = __cil_post_process_context_rules(db->ibpkeycon, cil_post_ibpkeycon_compare, cil_post_ibpkeycon_context_compare, db, CIL_IBPKEYCON, CIL_KEY_IBPKEYCON);
   2379 	if (rc != SEPOL_OK) {
   2380 		cil_log(CIL_ERR, "Problems processing ibpkeycon rules\n");
   2381 		goto exit;
   2382 	}
   2383 
   2384 	rc = __cil_post_process_context_rules(db->ibendportcon, cil_post_ibendportcon_compare, cil_post_ibendportcon_context_compare, db, CIL_IBENDPORTCON, CIL_KEY_IBENDPORTCON);
   2385 	if (rc != SEPOL_OK) {
   2386 		cil_log(CIL_ERR, "Problems processing ibendportcon rules\n");
   2387 		goto exit;
   2388 	}
   2389 
   2390 	rc = __cil_post_process_context_rules(db->portcon, cil_post_portcon_compare, cil_post_portcon_context_compare, db, CIL_PORTCON, CIL_KEY_PORTCON);
   2391 	if (rc != SEPOL_OK) {
   2392 		cil_log(CIL_ERR, "Problems processing portcon rules\n");
   2393 		goto exit;
   2394 	}
   2395 
   2396 	rc = __cil_post_process_context_rules(db->nodecon, cil_post_nodecon_compare, cil_post_nodecon_context_compare, db, CIL_NODECON, CIL_KEY_NODECON);
   2397 	if (rc != SEPOL_OK) {
   2398 		cil_log(CIL_ERR, "Problems processing nodecon rules\n");
   2399 		goto exit;
   2400 	}
   2401 
   2402 	rc = __cil_post_process_context_rules(db->fsuse, cil_post_fsuse_compare, cil_post_fsuse_context_compare, db, CIL_FSUSE, CIL_KEY_FSUSE);
   2403 	if (rc != SEPOL_OK) {
   2404 		cil_log(CIL_ERR, "Problems processing fsuse rules\n");
   2405 		goto exit;
   2406 	}
   2407 
   2408 	rc = __cil_post_process_context_rules(db->filecon, cil_post_filecon_compare, cil_post_filecon_context_compare, db, CIL_FILECON, CIL_KEY_FILECON);
   2409 	if (rc != SEPOL_OK) {
   2410 		cil_log(CIL_ERR, "Problems processing filecon rules\n");
   2411 		goto exit;
   2412 	}
   2413 
   2414 	rc = __cil_post_process_context_rules(db->iomemcon, cil_post_iomemcon_compare, cil_post_iomemcon_context_compare, db, CIL_IOMEMCON, CIL_KEY_IOMEMCON);
   2415 	if (rc != SEPOL_OK) {
   2416 		cil_log(CIL_ERR, "Problems processing iomemcon rules\n");
   2417 		goto exit;
   2418 	}
   2419 
   2420 	rc = __cil_post_process_context_rules(db->ioportcon, cil_post_ioportcon_compare, cil_post_ioportcon_context_compare, db, CIL_IOPORTCON, CIL_KEY_IOPORTCON);
   2421 	if (rc != SEPOL_OK) {
   2422 		cil_log(CIL_ERR, "Problems processing ioportcon rules\n");
   2423 		goto exit;
   2424 	}
   2425 
   2426 	rc = __cil_post_process_context_rules(db->pcidevicecon, cil_post_pcidevicecon_compare, cil_post_pcidevicecon_context_compare, db, CIL_PCIDEVICECON, CIL_KEY_PCIDEVICECON);
   2427 	if (rc != SEPOL_OK) {
   2428 		cil_log(CIL_ERR, "Problems processing pcidevicecon rules\n");
   2429 		goto exit;
   2430 	}
   2431 
   2432 	rc = __cil_post_process_context_rules(db->devicetreecon, cil_post_devicetreecon_compare, cil_post_devicetreecon_context_compare, db, CIL_DEVICETREECON, CIL_KEY_DEVICETREECON);
   2433 	if (rc != SEPOL_OK) {
   2434 		cil_log(CIL_ERR, "Problems processing devicetreecon rules\n");
   2435 		goto exit;
   2436 	}
   2437 
   2438 exit:
   2439 	return rc;
   2440 }
   2441 
   2442 static int cil_post_verify(struct cil_db *db)
   2443 {
   2444 	int rc = SEPOL_ERR;
   2445 	int avrule_cnt = 0;
   2446 	int handleunknown = -1;
   2447 	int mls = -1;
   2448 	int nseuserdflt = 0;
   2449 	int pass = 0;
   2450 	struct cil_args_verify extra_args;
   2451 	struct cil_complex_symtab csymtab;
   2452 
   2453 	cil_complex_symtab_init(&csymtab, CIL_CLASS_SYM_SIZE);
   2454 
   2455 	extra_args.db = db;
   2456 	extra_args.csymtab = &csymtab;
   2457 	extra_args.avrule_cnt = &avrule_cnt;
   2458 	extra_args.handleunknown = &handleunknown;
   2459 	extra_args.mls = &mls;
   2460 	extra_args.nseuserdflt = &nseuserdflt;
   2461 	extra_args.pass = &pass;
   2462 
   2463 	for (pass = 0; pass < 2; pass++) {
   2464 		rc = cil_tree_walk(db->ast->root, __cil_verify_helper, NULL, NULL, &extra_args);
   2465 		if (rc != SEPOL_OK) {
   2466 			cil_log(CIL_ERR, "Failed to verify cil database\n");
   2467 			goto exit;
   2468 		}
   2469 	}
   2470 
   2471 	if (db->handle_unknown == -1) {
   2472 		if (handleunknown == -1) {
   2473 			db->handle_unknown = SEPOL_DENY_UNKNOWN;
   2474 		} else {
   2475 			db->handle_unknown = handleunknown;
   2476 		}
   2477 	}
   2478 
   2479 	if (db->mls == -1) {
   2480 		if (mls == -1) {
   2481 			db->mls = CIL_FALSE;
   2482 		} else {
   2483 			db->mls = mls;
   2484 		}
   2485 	}
   2486 
   2487 	if (avrule_cnt == 0) {
   2488 		cil_log(CIL_ERR, "Policy must include at least one avrule\n");
   2489 		rc = SEPOL_ERR;
   2490 		goto exit;
   2491 	}
   2492 
   2493 	if (nseuserdflt > 1) {
   2494 		cil_log(CIL_ERR, "Policy cannot contain more than one selinuxuserdefault, found: %d\n", nseuserdflt);
   2495 		rc = SEPOL_ERR;
   2496 		goto exit;
   2497 	}
   2498 
   2499 exit:
   2500 	cil_complex_symtab_destroy(&csymtab);
   2501 	return rc;
   2502 }
   2503 
   2504 static int cil_pre_verify(struct cil_db *db)
   2505 {
   2506 	int rc = SEPOL_ERR;
   2507 	struct cil_args_verify extra_args;
   2508 
   2509 	extra_args.db = db;
   2510 
   2511 	rc = cil_tree_walk(db->ast->root, __cil_pre_verify_helper, NULL, NULL, &extra_args);
   2512 	if (rc != SEPOL_OK) {
   2513 		cil_log(CIL_ERR, "Failed to verify cil database\n");
   2514 		goto exit;
   2515 	}
   2516 
   2517 exit:
   2518 	return rc;
   2519 }
   2520 
   2521 int cil_post_process(struct cil_db *db)
   2522 {
   2523 	int rc = SEPOL_ERR;
   2524 
   2525 	rc = cil_pre_verify(db);
   2526 	if (rc != SEPOL_OK) {
   2527 		cil_log(CIL_ERR, "Failed to verify cil database\n");
   2528 		goto exit;
   2529 	}
   2530 
   2531 	rc = cil_post_db(db);
   2532 	if (rc != SEPOL_OK) {
   2533 		cil_log(CIL_ERR, "Failed post db handling\n");
   2534 		goto exit;
   2535 	}
   2536 
   2537 	rc = cil_post_verify(db);
   2538 	if (rc != SEPOL_OK) {
   2539 		cil_log(CIL_ERR, "Failed to verify cil database\n");
   2540 		goto exit;
   2541 	}
   2542 
   2543 exit:
   2544 	return rc;
   2545 
   2546 }
   2547