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