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_TYPE: {
343		struct cil_type *type = node->data;
344		if (type->datum.nodes->head->data == node) {
345			// multiple AST nodes can point to the same cil_type data (like if
346			// copied from a macro). This check ensures we only count the
347			// duplicates once
348			type->value = db->num_types;
349			db->num_types++;
350		}
351		break;
352	}
353	case CIL_ROLE: {
354		struct cil_role *role = node->data;
355		if (role->datum.nodes->head->data == node) {
356			// multiple AST nodes can point to the same cil_role data (like if
357			// copied from a macro). This check ensures we only count the
358			// duplicates once
359			role->value = db->num_roles;
360			db->num_roles++;
361		}
362		break;
363	}
364	case CIL_NETIFCON:
365		db->netifcon->count++;
366		break;
367	case CIL_GENFSCON:
368		db->genfscon->count++;
369		break;
370	case CIL_FILECON:
371		db->filecon->count++;
372		break;
373	case CIL_NODECON:
374		db->nodecon->count++;
375		break;
376	case CIL_PORTCON:
377		db->portcon->count++;
378		break;
379	case CIL_PIRQCON:
380		db->pirqcon->count++;
381		break;
382	case CIL_IOMEMCON:
383		db->iomemcon->count++;
384		break;
385	case CIL_IOPORTCON:
386		db->ioportcon->count++;
387		break;
388	case CIL_PCIDEVICECON:
389		db->pcidevicecon->count++;
390		break;
391	case CIL_DEVICETREECON:
392		db->devicetreecon->count++;
393		break;
394	case CIL_FSUSE:
395		db->fsuse->count++;
396		break;
397	default:
398		break;
399	}
400
401	return SEPOL_OK;
402}
403
404static int __cil_post_db_array_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
405{
406	struct cil_db *db = extra_args;
407
408	switch(node->flavor) {
409	case CIL_BLOCK: {
410		struct cil_block *blk = node->data;
411		if (blk->is_abstract == CIL_TRUE) {
412			*finished = CIL_TREE_SKIP_HEAD;
413		}
414		break;
415	}
416	case CIL_MACRO:
417		*finished = CIL_TREE_SKIP_HEAD;
418		break;
419	case CIL_TYPE: {
420		struct cil_type *type = node->data;
421		if (db->val_to_type == NULL) {
422			db->val_to_type = cil_malloc(sizeof(*db->val_to_type) * db->num_types);
423		}
424		db->val_to_type[type->value] = type;
425		break;
426	}
427	case CIL_ROLE: {
428		struct cil_role *role = node->data;
429		if (db->val_to_role == NULL) {
430			db->val_to_role = cil_malloc(sizeof(*db->val_to_role) * db->num_roles);
431		}
432		db->val_to_role[role->value] = role;
433		break;
434	}
435	case CIL_USERPREFIX: {
436		cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data);
437		break;
438	}
439	case CIL_SELINUXUSER: {
440		cil_list_prepend(db->selinuxusers, CIL_SELINUXUSER, node->data);
441		break;
442	}
443	case CIL_SELINUXUSERDEFAULT: {
444		cil_list_append(db->selinuxusers, CIL_SELINUXUSERDEFAULT, node->data);
445		break;
446	}
447	case CIL_NETIFCON: {
448		struct cil_sort *sort = db->netifcon;
449		uint32_t count = sort->count;
450		uint32_t i = sort->index;
451		if (sort->array == NULL) {
452			sort->array = cil_malloc(sizeof(*sort->array)*count);
453		}
454		sort->array[i] = node->data;
455		sort->index++;
456		break;
457	}
458	case CIL_FSUSE: {
459		struct cil_sort *sort = db->fsuse;
460		uint32_t count = sort->count;
461		uint32_t i = sort->index;
462		if (sort->array == NULL) {
463			sort->array = cil_malloc(sizeof(*sort->array)*count);
464		}
465		sort->array[i] = node->data;
466		sort->index++;
467		break;
468	}
469	case CIL_GENFSCON: {
470		struct cil_sort *sort = db->genfscon;
471		uint32_t count = sort->count;
472		uint32_t i = sort->index;
473		if (sort->array == NULL) {
474			sort->array = cil_malloc(sizeof(*sort->array)*count);
475		}
476		sort->array[i] = node->data;
477		sort->index++;
478		break;
479	}
480	case CIL_FILECON: {
481		struct cil_sort *sort = db->filecon;
482		uint32_t count = sort->count;
483		uint32_t i = sort->index;
484		if (sort->array == NULL) {
485		sort->array = cil_malloc(sizeof(*sort->array)*count);
486		}
487		sort->array[i] = node->data;
488		sort->index++;
489		break;
490	}
491	case CIL_NODECON: {
492		struct cil_sort *sort = db->nodecon;
493		uint32_t count = sort->count;
494		uint32_t i = sort->index;
495		if (sort->array == NULL) {
496			sort->array = cil_malloc(sizeof(*sort->array)*count);
497		}
498		sort->array[i] = node->data;
499		sort->index++;
500		break;
501	}
502	case CIL_PORTCON: {
503		struct cil_sort *sort = db->portcon;
504		uint32_t count = sort->count;
505		uint32_t i = sort->index;
506		if (sort->array == NULL) {
507			sort->array = cil_malloc(sizeof(*sort->array)*count);
508		}
509		sort->array[i] = node->data;
510		sort->index++;
511		break;
512	}
513	case CIL_PIRQCON: {
514		struct cil_sort *sort = db->pirqcon;
515		uint32_t count = sort->count;
516		uint32_t i = sort->index;
517		if (sort->array == NULL) {
518			sort->array = cil_malloc(sizeof(*sort->array)*count);
519		}
520		sort->array[i] = node->data;
521		sort->index++;
522		break;
523	}
524	case CIL_IOMEMCON: {
525		struct cil_sort *sort = db->iomemcon;
526		uint32_t count = sort->count;
527		uint32_t i = sort->index;
528		if (sort->array == NULL) {
529			sort->array = cil_malloc(sizeof(*sort->array)*count);
530		}
531		sort->array[i] = node->data;
532		sort->index++;
533		break;
534	}
535	case CIL_IOPORTCON: {
536		struct cil_sort *sort = db->ioportcon;
537		uint32_t count = sort->count;
538		uint32_t i = sort->index;
539		if (sort->array == NULL) {
540			sort->array = cil_malloc(sizeof(*sort->array)*count);
541		}
542		sort->array[i] = node->data;
543		sort->index++;
544		break;
545	}
546	case CIL_PCIDEVICECON: {
547		struct cil_sort *sort = db->pcidevicecon;
548		uint32_t count = sort->count;
549		uint32_t i = sort->index;
550		if (sort->array == NULL) {
551			sort->array = cil_malloc(sizeof(*sort->array)*count);
552		}
553		sort->array[i] = node->data;
554		sort->index++;
555		break;
556	}
557	case CIL_DEVICETREECON: {
558		struct cil_sort *sort = db->devicetreecon;
559		uint32_t count = sort->count;
560		uint32_t i = sort->index;
561		if (sort->array == NULL) {
562			sort->array = cil_malloc(sizeof(*sort->array)*count);
563		}
564		sort->array[i] = node->data;
565		sort->index++;
566		break;
567	}
568	default:
569		break;
570	}
571
572	return SEPOL_OK;
573}
574
575static int __evaluate_type_expression(struct cil_typeattribute *attr, struct cil_db *db)
576{
577	int rc;
578
579	attr->types = cil_malloc(sizeof(*attr->types));
580	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->types, db->num_types, db);
581	if (rc != SEPOL_OK) {
582		cil_log(CIL_ERR, "Failed to expand type attribute to bitmap\n");
583		ebitmap_destroy(attr->types);
584		free(attr->types);
585		attr->types = NULL;
586	}
587	return rc;
588}
589
590static int __cil_type_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
591{
592	int rc = SEPOL_ERR;
593	struct cil_tree_node *node = datum->nodes->head->data;
594
595	ebitmap_init(bitmap);
596
597	if (node->flavor == CIL_TYPEATTRIBUTE) {
598		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
599		if (attr->types == NULL) {
600			rc = __evaluate_type_expression(attr, db);
601			if (rc != SEPOL_OK) goto exit;
602		}
603		ebitmap_union(bitmap, attr->types);
604	} else if (node->flavor == CIL_TYPEALIAS) {
605		struct cil_alias *alias = (struct cil_alias *)datum;
606		struct cil_type *type = alias->actual;
607		if (ebitmap_set_bit(bitmap, type->value, 1)) {
608			cil_log(CIL_ERR, "Failed to set type bit\n");
609			ebitmap_destroy(bitmap);
610			goto exit;
611		}
612	} else {
613		struct cil_type *type = (struct cil_type *)datum;
614		if (ebitmap_set_bit(bitmap, type->value, 1)) {
615			cil_log(CIL_ERR, "Failed to set type bit\n");
616			ebitmap_destroy(bitmap);
617			goto exit;
618		}
619	}
620
621	return SEPOL_OK;
622
623exit:
624	return rc;
625}
626
627static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db)
628{
629	int rc;
630
631	attr->roles = cil_malloc(sizeof(*attr->roles));
632	rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->roles, db->num_roles, db);
633	if (rc != SEPOL_OK) {
634		cil_log(CIL_ERR, "Failed to expand role attribute to bitmap\n");
635		ebitmap_destroy(attr->roles);
636		free(attr->roles);
637		attr->roles = NULL;
638	}
639	return rc;
640}
641
642static int __cil_role_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
643{
644	int rc = SEPOL_ERR;
645	struct cil_tree_node *node = datum->nodes->head->data;
646
647	ebitmap_init(bitmap);
648
649	if (node->flavor == CIL_ROLEATTRIBUTE) {
650		struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
651		if (attr->roles == NULL) {
652			rc = __evaluate_role_expression(attr, db);
653			if (rc != SEPOL_OK) goto exit;
654		}
655		ebitmap_union(bitmap, attr->roles);
656	} else {
657		struct cil_role *role = (struct cil_role *)datum;
658		if (ebitmap_set_bit(bitmap, role->value, 1)) {
659			cil_log(CIL_ERR, "Failed to set role bit\n");
660			ebitmap_destroy(bitmap);
661			goto exit;
662		}
663	}
664
665	return SEPOL_OK;
666
667exit:
668	return rc;
669}
670
671static int __cil_perm_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
672{
673	struct cil_perm *perm = (struct cil_perm *)datum;
674	unsigned int value = perm->value;
675
676	ebitmap_init(bitmap);
677	if (ebitmap_set_bit(bitmap, value, 1)) {
678		cil_log(CIL_INFO, "Failed to set perm bit\n");
679		ebitmap_destroy(bitmap);
680		return SEPOL_ERR;
681	}
682
683	return SEPOL_OK;
684}
685
686static int __evaluate_cat_expression(struct cil_cats *cats, struct cil_db *db)
687{
688	int rc = SEPOL_ERR;
689	ebitmap_t bitmap;
690	struct cil_list *new;
691	struct cil_list_item *curr;
692
693	if (cats->evaluated == CIL_TRUE) {
694		return SEPOL_OK;
695	}
696
697	if (cil_verify_is_list(cats->datum_expr, CIL_CAT)) {
698		return SEPOL_OK;
699	}
700
701	ebitmap_init(&bitmap);
702	rc = __cil_expr_to_bitmap(cats->datum_expr, &bitmap, db->num_cats, db);
703	if (rc != SEPOL_OK) {
704		cil_log(CIL_ERR, "Failed to expand category expression to bitmap\n");
705		ebitmap_destroy(&bitmap);
706		goto exit;
707	}
708
709	cil_list_init(&new, CIL_CAT);
710
711	cil_list_for_each(curr, db->catorder) {
712		struct cil_cat *cat = curr->data;
713		if (ebitmap_get_bit(&bitmap, cat->value)) {
714			cil_list_append(new, CIL_DATUM, cat);
715		}
716	}
717
718	ebitmap_destroy(&bitmap);
719	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
720	if (new->head != NULL) {
721		cats->datum_expr = new;
722	} else {
723		/* empty list */
724		cil_list_destroy(&new, CIL_FALSE);
725		cats->datum_expr = NULL;
726	}
727
728	cats->evaluated = CIL_TRUE;
729
730	return SEPOL_OK;
731
732exit:
733	return rc;
734}
735
736static int __cil_cat_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
737{
738	int rc = SEPOL_ERR;
739	struct cil_tree_node *node = datum->nodes->head->data;
740
741	ebitmap_init(bitmap);
742
743	if (node->flavor == CIL_CATSET) {
744		struct cil_catset *catset = (struct cil_catset *)datum;
745		struct cil_list_item *curr;
746		if (catset->cats->evaluated == CIL_FALSE) {
747			rc = __evaluate_cat_expression(catset->cats, db);
748			if (rc != SEPOL_OK) goto exit;
749		}
750		for (curr = catset->cats->datum_expr->head; curr; curr = curr->next) {
751			struct cil_cat *cat = (struct cil_cat *)curr->data;
752			if (ebitmap_set_bit(bitmap, cat->value, 1)) {
753				cil_log(CIL_ERR, "Failed to set cat bit\n");
754				ebitmap_destroy(bitmap);
755				goto exit;
756			}
757		}
758	} else if (node->flavor == CIL_CATALIAS) {
759		struct cil_alias *alias = (struct cil_alias *)datum;
760		struct cil_cat *cat = alias->actual;
761		if (ebitmap_set_bit(bitmap, cat->value, 1)) {
762			cil_log(CIL_ERR, "Failed to set cat bit\n");
763			ebitmap_destroy(bitmap);
764			goto exit;
765		}
766	} else {
767		struct cil_cat *cat = (struct cil_cat *)datum;
768		if (ebitmap_set_bit(bitmap, cat->value, 1)) {
769			cil_log(CIL_ERR, "Failed to set cat bit\n");
770			ebitmap_destroy(bitmap);
771			goto exit;
772		}
773	}
774
775	return SEPOL_OK;
776
777exit:
778	return rc;
779}
780
781static int __cil_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
782{
783	int rc = SEPOL_ERR;
784	struct cil_symtab_datum *d1 = i1->data;
785	struct cil_symtab_datum *d2 = i2->data;
786	struct cil_tree_node *n1 = d1->nodes->head->data;
787	struct cil_tree_node *n2 = d2->nodes->head->data;
788	struct cil_cat *c1 = (struct cil_cat *)d1;
789	struct cil_cat *c2 = (struct cil_cat *)d2;
790	int i;
791
792	if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) {
793		cil_log(CIL_ERR, "Category sets cannont be used in a category range\n");
794		goto exit;
795	}
796
797	if (n1->flavor == CIL_CATALIAS) {
798		struct cil_alias *alias = (struct cil_alias *)d1;
799		c1 = alias->actual;
800	}
801
802	if (n2->flavor == CIL_CATALIAS) {
803		struct cil_alias *alias = (struct cil_alias *)d2;
804		c2 = alias->actual;
805	}
806
807	for (i = c1->value; i <= c2->value; i++) {
808		if (ebitmap_set_bit(bitmap, i, 1)) {
809			cil_log(CIL_ERR, "Failed to set cat bit\n");
810			ebitmap_destroy(bitmap);
811			goto exit;
812		}
813	}
814
815	return SEPOL_OK;
816
817exit:
818	return rc;
819}
820
821static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flavor flavor, ebitmap_t *bitmap, int max, struct cil_db *db)
822{
823	int rc = SEPOL_ERR;
824
825	if (curr->flavor == CIL_DATUM) {
826		switch (flavor) {
827		case CIL_TYPE:
828			rc = __cil_type_to_bitmap(curr->data, bitmap, db);
829			break;
830		case CIL_ROLE:
831			rc = __cil_role_to_bitmap(curr->data, bitmap, db);
832			break;
833		case CIL_PERM:
834			rc = __cil_perm_to_bitmap(curr->data, bitmap, db);
835			break;
836		case CIL_CAT:
837			rc = __cil_cat_to_bitmap(curr->data, bitmap, db);
838			break;
839		default:
840			rc = SEPOL_ERR;
841		}
842	} else if (curr->flavor == CIL_LIST) {
843		struct cil_list *l = curr->data;
844		ebitmap_init(bitmap);
845		rc = __cil_expr_to_bitmap(l, bitmap, max, db);
846		if (rc != SEPOL_OK) {
847			ebitmap_destroy(bitmap);
848		}
849	}
850
851	return rc;
852}
853
854static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db)
855{
856	int rc = SEPOL_ERR;
857	struct cil_list_item *curr;
858	enum cil_flavor flavor;
859	ebitmap_t tmp, b1, b2;
860
861	if (expr == NULL || expr->head == NULL) {
862		return SEPOL_OK;
863	}
864
865	curr = expr->head;
866	flavor = expr->flavor;
867
868	if (curr->flavor == CIL_OP) {
869		enum cil_flavor op = (enum cil_flavor)curr->data;
870
871		if (op == CIL_ALL) {
872			ebitmap_init(&b1); /* all zeros */
873			rc = ebitmap_not(&tmp, &b1, max);
874			ebitmap_destroy(&b1);
875			if (rc != SEPOL_OK) {
876				cil_log(CIL_INFO, "Failed to expand 'all' operator\n");
877				ebitmap_destroy(&tmp);
878				goto exit;
879			}
880		} else if (op == CIL_RANGE) {
881			if (flavor != CIL_CAT) {
882				cil_log(CIL_INFO, "Range operation only supported for categories\n");
883				rc = SEPOL_ERR;
884				goto exit;
885			}
886			ebitmap_init(&tmp);
887			rc = __cil_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
888			if (rc != SEPOL_OK) {
889				cil_log(CIL_INFO, "Failed to expand category range\n");
890				ebitmap_destroy(&tmp);
891				goto exit;
892			}
893		} else {
894			rc = __cil_expr_to_bitmap_helper(curr->next, flavor, &b1, max, db);
895			if (rc != SEPOL_OK) {
896				cil_log(CIL_INFO, "Failed to get first operand bitmap\n");
897				goto exit;
898			}
899
900			if (op == CIL_NOT) {
901				rc = ebitmap_not(&tmp, &b1, max);
902				ebitmap_destroy(&b1);
903				if (rc != SEPOL_OK) {
904					cil_log(CIL_INFO, "Failed to NOT bitmap\n");
905					ebitmap_destroy(&tmp);
906					goto exit;
907				}
908			} else {
909				rc = __cil_expr_to_bitmap_helper(curr->next->next, flavor, &b2, max, db);
910				if (rc != SEPOL_OK) {
911					cil_log(CIL_INFO, "Failed to get second operand bitmap\n");
912					goto exit;
913				}
914
915				if (op == CIL_OR) {
916					rc = ebitmap_or(&tmp, &b1, &b2);
917				} else if (op == CIL_AND) {
918					rc = ebitmap_and(&tmp, &b1, &b2);
919				} else if (op == CIL_XOR) {
920					rc = ebitmap_xor(&tmp, &b1, &b2);
921				} else {
922					rc = SEPOL_ERR;
923				}
924				ebitmap_destroy(&b1);
925				ebitmap_destroy(&b2);
926				if (rc != SEPOL_OK) {
927					cil_log(CIL_INFO, "Failed to apply operator to bitmaps\n");
928					ebitmap_destroy(&tmp);
929					goto exit;
930				}
931			}
932		}
933	} else {
934		ebitmap_init(&tmp);
935		for (;curr; curr = curr->next) {
936			rc = __cil_expr_to_bitmap_helper(curr, flavor, &b2, max, db);
937			if (rc != SEPOL_OK) {
938				cil_log(CIL_INFO, "Failed to get operand in list\n");
939				ebitmap_destroy(&tmp);
940				goto exit;
941			}
942			b1 = tmp;
943			rc = ebitmap_or(&tmp, &b1, &b2);
944			ebitmap_destroy(&b1);
945			ebitmap_destroy(&b2);
946			if (rc != SEPOL_OK) {
947				cil_log(CIL_INFO, "Failed to OR operands in list\n");
948				ebitmap_destroy(&tmp);
949				goto exit;
950			}
951
952		}
953	}
954
955	ebitmap_union(out, &tmp);
956	ebitmap_destroy(&tmp);
957
958	return SEPOL_OK;
959
960exit:
961	return rc;
962}
963
964static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db)
965{
966	int rc = SEPOL_ERR;
967	struct cil_list_item *expr;
968
969	ebitmap_init(out);
970
971	if (expr_list == NULL) {
972		return SEPOL_OK;
973	}
974
975	cil_list_for_each(expr, expr_list) {
976		ebitmap_t bitmap;
977		struct cil_list *l = (struct cil_list *)expr->data;
978		ebitmap_init(&bitmap);
979		rc = __cil_expr_to_bitmap(l, &bitmap, max, db);
980		if (rc != SEPOL_OK) {
981			cil_log(CIL_INFO, "Failed to expand expression list to bitmap\n");
982			ebitmap_destroy(&bitmap);
983			goto exit;
984		}
985		ebitmap_union(out, &bitmap);
986		ebitmap_destroy(&bitmap);
987	}
988
989	return SEPOL_OK;
990
991exit:
992	return SEPOL_ERR;
993}
994
995static int __cil_post_db_attr_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
996{
997	int rc = SEPOL_ERR;
998	struct cil_db *db = extra_args;
999
1000	switch (node->flavor) {
1001	case CIL_BLOCK: {
1002		struct cil_block *blk = node->data;
1003		if (blk->is_abstract == CIL_TRUE) {
1004			*finished = CIL_TREE_SKIP_HEAD;
1005		}
1006		break;
1007	}
1008	case CIL_MACRO: {
1009		*finished = CIL_TREE_SKIP_HEAD;
1010		break;
1011	}
1012	case CIL_TYPEATTRIBUTE: {
1013		struct cil_typeattribute *attr = node->data;
1014		if (attr->types == NULL) {
1015			rc = __evaluate_type_expression(attr, db);
1016			if (rc != SEPOL_OK) goto exit;
1017		}
1018		break;
1019	}
1020	case CIL_ROLEATTRIBUTE: {
1021		struct cil_roleattribute *attr = node->data;
1022		if (attr->roles == NULL) {
1023			rc = __evaluate_role_expression(attr, db);
1024			if (rc != SEPOL_OK) goto exit;
1025		}
1026		break;
1027	}
1028	default:
1029		break;
1030	}
1031
1032	return SEPOL_OK;
1033
1034exit:
1035	return rc;
1036}
1037
1038static int __cil_role_assign_types(struct cil_role *role, struct cil_symtab_datum *datum)
1039{
1040	struct cil_tree_node *node = datum->nodes->head->data;
1041
1042	if (role->types == NULL) {
1043		role->types = cil_malloc(sizeof(*role->types));
1044		ebitmap_init(role->types);
1045	}
1046
1047	if (node->flavor == CIL_TYPE) {
1048		struct cil_type *type = (struct cil_type *)datum;
1049		if (ebitmap_set_bit(role->types, type->value, 1)) {
1050			cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
1051			goto exit;
1052		}
1053	} else if (node->flavor == CIL_TYPEALIAS) {
1054		struct cil_alias *alias = (struct cil_alias *)datum;
1055		struct cil_type *type = alias->actual;
1056		if (ebitmap_set_bit(role->types, type->value, 1)) {
1057			cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n");
1058			goto exit;
1059		}
1060	} else if (node->flavor == CIL_TYPEATTRIBUTE) {
1061		struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
1062		ebitmap_union(role->types, attr->types);
1063	}
1064
1065	return SEPOL_OK;
1066
1067exit:
1068	return SEPOL_ERR;
1069}
1070
1071static int __cil_post_db_roletype_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
1072{
1073	int rc = SEPOL_ERR;
1074	struct cil_db *db = extra_args;
1075
1076	switch (node->flavor) {
1077	case CIL_BLOCK: {
1078		struct cil_block *blk = node->data;
1079		if (blk->is_abstract == CIL_TRUE) {
1080			*finished = CIL_TREE_SKIP_HEAD;
1081		}
1082		break;
1083	}
1084	case CIL_MACRO: {
1085		*finished = CIL_TREE_SKIP_HEAD;
1086		break;
1087	}
1088	case CIL_ROLETYPE: {
1089		struct cil_roletype *roletype = node->data;
1090		struct cil_symtab_datum *role_datum = roletype->role;
1091		struct cil_symtab_datum *type_datum = roletype->type;
1092		struct cil_tree_node *role_node = role_datum->nodes->head->data;
1093
1094		if (role_node->flavor == CIL_ROLEATTRIBUTE) {
1095			struct cil_roleattribute *attr = roletype->role;
1096			ebitmap_node_t *rnode;
1097			unsigned int i;
1098
1099			ebitmap_for_each_bit(attr->roles, rnode, i) {
1100				struct cil_role *role = NULL;
1101
1102				if (!ebitmap_get_bit(attr->roles, i)) {
1103					continue;
1104				}
1105
1106				role = db->val_to_role[i];
1107
1108				rc = __cil_role_assign_types(role, type_datum);
1109				if (rc != SEPOL_OK) {
1110					goto exit;
1111				}
1112			}
1113		} else {
1114			struct cil_role *role = roletype->role;
1115
1116			rc = __cil_role_assign_types(role, type_datum);
1117			if (rc != SEPOL_OK) {
1118				goto exit;
1119			}
1120		}
1121		break;
1122	}
1123	default:
1124		break;
1125	}
1126
1127	return SEPOL_OK;
1128exit:
1129	cil_log(CIL_INFO, "cil_post_db_roletype_helper failed\n");
1130	return rc;
1131}
1132
1133static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db)
1134{
1135	if (level->cats != NULL) {
1136		return __evaluate_cat_expression(level->cats, db);
1137	}
1138
1139	return SEPOL_OK;
1140}
1141
1142static int __evaluate_levelrange_expression(struct cil_levelrange *levelrange, struct cil_db *db)
1143{
1144	int rc = SEPOL_OK;
1145
1146	if (levelrange->low != NULL && levelrange->low->cats != NULL) {
1147		rc =  __evaluate_cat_expression(levelrange->low->cats, db);
1148		if (rc != SEPOL_OK) {
1149			goto exit;
1150		}
1151	}
1152	if (levelrange->high != NULL && levelrange->high->cats != NULL) {
1153		rc = __evaluate_cat_expression(levelrange->high->cats, db);
1154		if (rc != SEPOL_OK) {
1155			goto exit;
1156		}
1157	}
1158
1159exit:
1160	return rc;
1161}
1162
1163static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1164{
1165	int rc = SEPOL_ERR;
1166	struct cil_db *db = extra_args;
1167
1168	switch (node->flavor) {
1169	case CIL_BLOCK: {
1170		struct cil_block *blk = node->data;
1171		if (blk->is_abstract == CIL_TRUE) {
1172			*finished = CIL_TREE_SKIP_HEAD;
1173		}
1174		break;
1175	}
1176	case CIL_MACRO: {
1177		*finished = CIL_TREE_SKIP_HEAD;
1178		break;
1179	}
1180	case CIL_CATSET: {
1181		struct cil_catset *catset = node->data;
1182		rc = __evaluate_cat_expression(catset->cats, db);
1183		if (rc != SEPOL_OK) {
1184			goto exit;
1185		}
1186		break;
1187	}
1188	case CIL_SENSCAT: {
1189		struct cil_senscat *senscat = node->data;
1190		rc = __evaluate_cat_expression(senscat->cats, db);
1191		if (rc != SEPOL_OK) {
1192			goto exit;
1193		}
1194		break;
1195	}
1196	case CIL_LEVEL: {
1197		rc = __evaluate_level_expression(node->data, db);
1198		if (rc != SEPOL_OK) {
1199			goto exit;
1200		}
1201		break;
1202	}
1203	case CIL_LEVELRANGE: {
1204		rc = __evaluate_levelrange_expression(node->data, db);
1205		if (rc != SEPOL_OK) {
1206			goto exit;
1207		}
1208		break;
1209	}
1210	case CIL_USER: {
1211		struct cil_user *user = node->data;
1212		rc = __evaluate_level_expression(user->dftlevel, db);
1213		if (rc != SEPOL_OK) {
1214			goto exit;
1215		}
1216		rc = __evaluate_levelrange_expression(user->range, db);
1217		if (rc != SEPOL_OK) {
1218			goto exit;
1219		}
1220		break;
1221	}
1222	case CIL_SELINUXUSERDEFAULT:
1223	case CIL_SELINUXUSER: {
1224		struct cil_selinuxuser *selinuxuser = node->data;
1225		rc = __evaluate_levelrange_expression(selinuxuser->range, db);
1226		if (rc != SEPOL_OK) {
1227			goto exit;
1228		}
1229		break;
1230	}
1231	case CIL_RANGETRANSITION: {
1232		struct cil_rangetransition *rangetrans = node->data;
1233		rc = __evaluate_levelrange_expression(rangetrans->range, db);
1234		if (rc != SEPOL_OK) {
1235			goto exit;
1236		}
1237		break;
1238	}
1239	case CIL_CONTEXT: {
1240		struct cil_context *context = node->data;
1241		rc = __evaluate_levelrange_expression(context->range, db);
1242		if (rc != SEPOL_OK) {
1243			goto exit;
1244		}
1245		break;
1246	}
1247	case CIL_SIDCONTEXT: {
1248		struct cil_sidcontext *sidcontext = node->data;
1249		rc = __evaluate_levelrange_expression(sidcontext->context->range, db);
1250		if (rc != SEPOL_OK) {
1251			goto exit;
1252		}
1253		break;
1254	}
1255	case CIL_FILECON: {
1256		struct cil_filecon *filecon = node->data;
1257		if (filecon->context) {
1258			rc = __evaluate_levelrange_expression(filecon->context->range, db);
1259			if (rc != SEPOL_OK) {
1260				goto exit;
1261			}
1262		}
1263		break;
1264	}
1265	case CIL_PORTCON: {
1266		struct cil_portcon *portcon = node->data;
1267		rc = __evaluate_levelrange_expression(portcon->context->range, db);
1268		if (rc != SEPOL_OK) {
1269			goto exit;
1270		}
1271		break;
1272	}
1273	case CIL_NODECON: {
1274		struct cil_nodecon *nodecon = node->data;
1275		rc = __evaluate_levelrange_expression(nodecon->context->range, db);
1276		if (rc != SEPOL_OK) {
1277			goto exit;
1278		}
1279		break;
1280	}
1281	case CIL_GENFSCON: {
1282		struct cil_genfscon *genfscon = node->data;
1283		rc = __evaluate_levelrange_expression(genfscon->context->range, db);
1284		if (rc != SEPOL_OK) {
1285			goto exit;
1286		}
1287		break;
1288	}
1289	case CIL_NETIFCON: {
1290		struct cil_netifcon *netifcon = node->data;
1291		rc = __evaluate_levelrange_expression(netifcon->if_context->range, db);
1292		if (rc != SEPOL_OK) {
1293			goto exit;
1294		}
1295		rc = __evaluate_levelrange_expression(netifcon->packet_context->range, db);
1296		if (rc != SEPOL_OK) {
1297			goto exit;
1298		}
1299		break;
1300	}
1301	case CIL_PIRQCON: {
1302		struct cil_pirqcon *pirqcon = node->data;
1303		rc = __evaluate_levelrange_expression(pirqcon->context->range, db);
1304		if (rc != SEPOL_OK) {
1305			goto exit;
1306		}
1307		break;
1308	}
1309	case CIL_IOMEMCON: {
1310		struct cil_iomemcon *iomemcon = node->data;
1311		rc = __evaluate_levelrange_expression(iomemcon->context->range, db);
1312		if (rc != SEPOL_OK) {
1313			goto exit;
1314		}
1315		break;
1316	}
1317	case CIL_IOPORTCON: {
1318		struct cil_ioportcon *ioportcon = node->data;
1319		rc = __evaluate_levelrange_expression(ioportcon->context->range, db);
1320		if (rc != SEPOL_OK) {
1321			goto exit;
1322		}
1323		break;
1324	}
1325	case CIL_PCIDEVICECON: {
1326		struct cil_pcidevicecon *pcidevicecon = node->data;
1327		rc = __evaluate_levelrange_expression(pcidevicecon->context->range, db);
1328		if (rc != SEPOL_OK) {
1329			goto exit;
1330		}
1331		break;
1332	}
1333	case CIL_DEVICETREECON: {
1334		struct cil_devicetreecon *devicetreecon = node->data;
1335		rc = __evaluate_levelrange_expression(devicetreecon->context->range, db);
1336		if (rc != SEPOL_OK) {
1337			goto exit;
1338		}
1339		break;
1340	}
1341	case CIL_FSUSE: {
1342		struct cil_fsuse *fsuse = node->data;
1343		rc = __evaluate_levelrange_expression(fsuse->context->range, db);
1344		if (rc != SEPOL_OK) {
1345			goto exit;
1346		}
1347		break;
1348	}
1349	default:
1350		break;
1351	}
1352
1353	return SEPOL_OK;
1354
1355exit:
1356	return rc;
1357}
1358
1359struct perm_to_list {
1360	enum cil_flavor flavor;
1361	ebitmap_t *perms;
1362	struct cil_list *new_list;
1363};
1364
1365static int __perm_bits_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1366{
1367	struct perm_to_list *perm_args = (struct perm_to_list *)args;
1368	ebitmap_t *perms = perm_args->perms;
1369	struct cil_list *new_list = perm_args->new_list;
1370	struct cil_perm *perm = (struct cil_perm *)d;
1371	unsigned int value = perm->value;
1372
1373	if (!ebitmap_get_bit(perms, value)) {
1374		return SEPOL_OK;
1375	}
1376
1377	cil_list_append(new_list, CIL_DATUM, d);
1378
1379	return SEPOL_OK;
1380}
1381
1382static int __evaluate_perm_expression(struct cil_list *perms, enum cil_flavor flavor, symtab_t *class_symtab, symtab_t *common_symtab, unsigned int num_perms, struct cil_list **new_list, struct cil_db *db)
1383{
1384	int rc = SEPOL_ERR;
1385	struct perm_to_list args;
1386	ebitmap_t bitmap;
1387
1388	if (cil_verify_is_list(perms, CIL_PERM)) {
1389		return SEPOL_OK;
1390	}
1391
1392	ebitmap_init(&bitmap);
1393	rc = __cil_expr_to_bitmap(perms, &bitmap, num_perms, db);
1394	if (rc != SEPOL_OK) {
1395		ebitmap_destroy(&bitmap);
1396		goto exit;
1397	}
1398
1399	cil_list_init(new_list, flavor);
1400
1401	args.flavor = flavor;
1402	args.perms = &bitmap;
1403	args.new_list = *new_list;
1404
1405	cil_symtab_map(class_symtab, __perm_bits_to_list, &args);
1406
1407	if (common_symtab != NULL) {
1408		cil_symtab_map(common_symtab, __perm_bits_to_list, &args);
1409	}
1410
1411	ebitmap_destroy(&bitmap);
1412	return SEPOL_OK;
1413
1414exit:
1415	return rc;
1416}
1417
1418static int __evaluate_classperms(struct cil_classperms *cp, struct cil_db *db)
1419{
1420	int rc = SEPOL_ERR;
1421	struct cil_class *class = cp->class;
1422	struct cil_class *common = class->common;
1423	symtab_t *common_symtab = NULL;
1424	struct cil_list *new_list = NULL;
1425
1426	if (common) {
1427		common_symtab = &common->perms;
1428	}
1429
1430	rc = __evaluate_perm_expression(cp->perms, CIL_PERM, &class->perms, common_symtab, class->num_perms, &new_list, db);
1431	if (rc != SEPOL_OK) {
1432		goto exit;
1433	}
1434
1435	if (new_list == NULL) {
1436		return SEPOL_OK;
1437	}
1438
1439	cil_list_destroy(&cp->perms, CIL_FALSE);
1440
1441	cp->perms = new_list;
1442
1443	return SEPOL_OK;
1444
1445exit:
1446	return rc;
1447}
1448
1449static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db *db)
1450{
1451	int rc = SEPOL_ERR;
1452	struct cil_list_item *curr;
1453
1454	cil_list_for_each(curr, classperms) {
1455		if (curr->flavor == CIL_CLASSPERMS) {
1456			struct cil_classperms *cp = curr->data;
1457			if (FLAVOR(cp->class) == CIL_CLASS) {
1458				rc = __evaluate_classperms(cp, db);
1459				if (rc != SEPOL_OK) {
1460					goto exit;
1461				}
1462			} else { /* MAP */
1463				struct cil_list_item *i = NULL;
1464				cil_list_for_each(i, cp->perms) {
1465					struct cil_perm *cmp = i->data;
1466					rc = __evaluate_classperms_list(cmp->classperms, db);
1467					if (rc != SEPOL_OK) {
1468						goto exit;
1469					}
1470				}
1471			}
1472		} else { /* SET */
1473			struct cil_classperms_set *cp_set = curr->data;
1474			struct cil_classpermission *cp = cp_set->set;
1475			rc = __evaluate_classperms_list(cp->classperms, db);
1476			if (rc != SEPOL_OK) {
1477				goto exit;
1478			}
1479		}
1480	}
1481
1482	return SEPOL_OK;
1483
1484exit:
1485	return rc;
1486}
1487
1488struct class_map_args {
1489	struct cil_db *db;
1490	int rc;
1491};
1492
1493static int __evaluate_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1494{
1495	struct class_map_args *map_args = args;
1496	struct cil_perm *cmp = (struct cil_perm *)d;
1497
1498	int rc = __evaluate_classperms_list(cmp->classperms, map_args->db);
1499
1500	if (rc != SEPOL_OK) {
1501		map_args->rc = rc;
1502	}
1503
1504	return SEPOL_OK;
1505}
1506
1507static int __evaluate_map_class(struct cil_class *mc, struct cil_db *db)
1508{
1509	struct class_map_args map_args;
1510
1511	map_args.db = db;
1512	map_args.rc = SEPOL_OK;
1513	cil_symtab_map(&mc->perms, __evaluate_map_perm_classperms, &map_args);
1514
1515	return map_args.rc;
1516}
1517
1518static int __cil_post_db_classperms_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1519{
1520	int rc = SEPOL_ERR;
1521	struct cil_db *db = extra_args;
1522
1523	switch (node->flavor) {
1524	case CIL_BLOCK: {
1525		struct cil_block *blk = node->data;
1526		if (blk->is_abstract == CIL_TRUE) {
1527			*finished = CIL_TREE_SKIP_HEAD;
1528		}
1529		break;
1530	}
1531	case CIL_MACRO:
1532		*finished = CIL_TREE_SKIP_HEAD;
1533		break;
1534	case CIL_MAP_CLASS: {
1535		rc = __evaluate_map_class(node->data, db);
1536		if (rc != SEPOL_OK) {
1537			goto exit;
1538		}
1539		break;
1540	}
1541	case CIL_CLASSPERMISSION: {
1542		struct cil_classpermission *cp = node->data;
1543		rc = __evaluate_classperms_list(cp->classperms, db);
1544		if (rc != SEPOL_OK) {
1545			goto exit;
1546		}
1547		break;
1548	}
1549	case CIL_AVRULE: {
1550		struct cil_avrule *avrule = node->data;
1551		rc = __evaluate_classperms_list(avrule->classperms, db);
1552		if (rc != SEPOL_OK) {
1553			goto exit;
1554		}
1555		break;
1556	}
1557	case CIL_CONSTRAIN:
1558	case CIL_MLSCONSTRAIN: {
1559		struct cil_constrain *constrain = node->data;
1560		rc = __evaluate_classperms_list(constrain->classperms, db);
1561		if (rc != SEPOL_OK) {
1562			goto exit;
1563		}
1564		break;
1565	}
1566	default:
1567		break;
1568	}
1569
1570	return SEPOL_OK;
1571
1572exit:
1573	return rc;
1574}
1575
1576static int cil_post_db(struct cil_db *db)
1577{
1578	int rc = SEPOL_ERR;
1579
1580	rc = cil_tree_walk(db->ast->root, __cil_post_db_count_helper, NULL, NULL, db);
1581	if (rc != SEPOL_OK) {
1582		cil_log(CIL_INFO, "Failure during cil databse count helper\n");
1583		goto exit;
1584	}
1585
1586	rc = cil_tree_walk(db->ast->root, __cil_post_db_array_helper, NULL, NULL, db);
1587	if (rc != SEPOL_OK) {
1588		cil_log(CIL_INFO, "Failure during cil database array helper\n");
1589		goto exit;
1590	}
1591
1592	rc = cil_tree_walk(db->ast->root, __cil_post_db_attr_helper, NULL, NULL, db);
1593	if (rc != SEPOL_OK) {
1594		cil_log(CIL_INFO, "Failed to create attribute bitmaps\n");
1595		goto exit;
1596	}
1597
1598	rc = cil_tree_walk(db->ast->root, __cil_post_db_roletype_helper, NULL, NULL, db);
1599	if (rc != SEPOL_OK) {
1600		cil_log(CIL_INFO, "Failed during roletype association\n");
1601		goto exit;
1602	}
1603
1604	rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db);
1605	if (rc != SEPOL_OK) {
1606		cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n");
1607		goto exit;
1608	}
1609
1610	rc = cil_tree_walk(db->ast->root, __cil_post_db_cat_helper, NULL, NULL, db);
1611	if (rc != SEPOL_OK) {
1612		cil_log(CIL_INFO, "Failed to evaluate category expressions\n");
1613		goto exit;
1614	}
1615
1616	qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
1617	qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
1618	qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
1619	qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
1620	qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
1621	qsort(db->filecon->array, db->filecon->count, sizeof(db->filecon->array), cil_post_filecon_compare);
1622	qsort(db->pirqcon->array, db->pirqcon->count, sizeof(db->pirqcon->array), cil_post_pirqcon_compare);
1623	qsort(db->iomemcon->array, db->iomemcon->count, sizeof(db->iomemcon->array), cil_post_iomemcon_compare);
1624	qsort(db->ioportcon->array, db->ioportcon->count, sizeof(db->ioportcon->array), cil_post_ioportcon_compare);
1625	qsort(db->pcidevicecon->array, db->pcidevicecon->count, sizeof(db->pcidevicecon->array), cil_post_pcidevicecon_compare);
1626	qsort(db->devicetreecon->array, db->devicetreecon->count, sizeof(db->devicetreecon->array), cil_post_devicetreecon_compare);
1627
1628exit:
1629	return rc;
1630}
1631
1632static int cil_post_verify(struct cil_db *db)
1633{
1634	int rc = SEPOL_ERR;
1635	int avrule_cnt = 0;
1636	int handleunknown = -1;
1637	int mls = -1;
1638	int nseuserdflt = 0;
1639	int pass = 0;
1640	struct cil_args_verify extra_args;
1641	struct cil_complex_symtab csymtab;
1642
1643	cil_complex_symtab_init(&csymtab, CIL_CLASS_SYM_SIZE);
1644
1645	extra_args.db = db;
1646	extra_args.csymtab = &csymtab;
1647	extra_args.avrule_cnt = &avrule_cnt;
1648	extra_args.handleunknown = &handleunknown;
1649	extra_args.mls = &mls;
1650	extra_args.nseuserdflt = &nseuserdflt;
1651	extra_args.pass = &pass;
1652
1653	for (pass = 0; pass < 2; pass++) {
1654		rc = cil_tree_walk(db->ast->root, __cil_verify_helper, NULL, NULL, &extra_args);
1655		if (rc != SEPOL_OK) {
1656			cil_log(CIL_ERR, "Failed to verify cil database\n");
1657			goto exit;
1658		}
1659	}
1660
1661	if (db->handle_unknown == -1) {
1662		if (handleunknown == -1) {
1663			db->handle_unknown = SEPOL_DENY_UNKNOWN;
1664		} else {
1665			db->handle_unknown = handleunknown;
1666		}
1667	}
1668
1669	if (db->mls == -1) {
1670		if (mls == -1) {
1671			db->mls = CIL_FALSE;
1672		} else {
1673			db->mls = mls;
1674		}
1675	}
1676
1677	if (avrule_cnt == 0) {
1678		cil_log(CIL_ERR, "Policy must include at least one avrule\n");
1679		rc = SEPOL_ERR;
1680		goto exit;
1681	}
1682
1683	if (nseuserdflt > 1) {
1684		cil_log(CIL_ERR, "Policy cannot contain more than one selinuxuserdefault, found: %d\n", nseuserdflt);
1685		rc = SEPOL_ERR;
1686		goto exit;
1687	}
1688
1689exit:
1690	cil_complex_symtab_destroy(&csymtab);
1691	return rc;
1692}
1693
1694int cil_post_process(struct cil_db *db)
1695{
1696	int rc = SEPOL_ERR;
1697
1698	rc = cil_verify_no_classperms_loop(db);
1699	if (rc != SEPOL_OK) {
1700		goto exit;
1701	}
1702
1703	rc = cil_post_db(db);
1704	if (rc != SEPOL_OK) {
1705		cil_log(CIL_ERR, "Failed post db handling\n");
1706		goto exit;
1707	}
1708
1709	rc = cil_post_verify(db);
1710	if (rc != SEPOL_OK) {
1711		cil_log(CIL_ERR, "Failed to verify cil database\n");
1712		goto exit;
1713	}
1714
1715exit:
1716	return rc;
1717
1718}
1719