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