1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <unistd.h>
35 
36 #include <sepol/policydb/conditional.h>
37 #include <sepol/errcodes.h>
38 
39 #include "cil_internal.h"
40 #include "cil_flavor.h"
41 #include "cil_log.h"
42 #include "cil_mem.h"
43 #include "cil_tree.h"
44 #include "cil_list.h"
45 #include "cil_post.h"
46 #include "cil_policy.h"
47 #include "cil_verify.h"
48 #include "cil_symtab.h"
49 
50 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
51 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
52 
cil_verify_is_list(struct cil_list * list,enum cil_flavor flavor)53 static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
54 {
55 	struct cil_list_item *curr;
56 
57 	cil_list_for_each(curr, list) {
58 		switch (curr->flavor) {
59 		case CIL_LIST:
60 			return CIL_FALSE;
61 			break;
62 		case CIL_OP:
63 			return CIL_FALSE;
64 			break;
65 		default:
66 			if (flavor == CIL_CAT) {
67 				struct cil_symtab_datum *d = curr->data;
68 				struct cil_tree_node *n = d->nodes->head->data;
69 				if (n->flavor == CIL_CATSET) {
70 					return CIL_FALSE;
71 				}
72 			}
73 			break;
74 		}
75 	}
76 	return CIL_TRUE;
77 }
78 
cil_post_fc_fill_data(struct fc_data * fc,char * path)79 void cil_post_fc_fill_data(struct fc_data *fc, char *path)
80 {
81 	int c = 0;
82 	fc->meta = 0;
83 	fc->stem_len = 0;
84 	fc->str_len = 0;
85 
86 	while (path[c] != '\0') {
87 		switch (path[c]) {
88 		case '.':
89 		case '^':
90 		case '$':
91 		case '?':
92 		case '*':
93 		case '+':
94 		case '|':
95 		case '[':
96 		case '(':
97 		case '{':
98 			fc->meta = 1;
99 			break;
100 		case '\\':
101 			c++;
102 		default:
103 			if (!fc->meta) {
104 				fc->stem_len++;
105 			}
106 			break;
107 		}
108 		fc->str_len++;
109 		c++;
110 	}
111 }
112 
cil_post_filecon_compare(const void * a,const void * b)113 int cil_post_filecon_compare(const void *a, const void *b)
114 {
115 	int rc = 0;
116 	struct cil_filecon *a_filecon = *(struct cil_filecon**)a;
117 	struct cil_filecon *b_filecon = *(struct cil_filecon**)b;
118 	struct fc_data *a_data = cil_malloc(sizeof(*a_data));
119 	struct fc_data *b_data = cil_malloc(sizeof(*b_data));
120 	char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1);
121 	a_path[0] = '\0';
122 	char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1);
123 	b_path[0] = '\0';
124 	strcat(a_path, a_filecon->path_str);
125 	strcat(b_path, b_filecon->path_str);
126 	cil_post_fc_fill_data(a_data, a_path);
127 	cil_post_fc_fill_data(b_data, b_path);
128 	if (a_data->meta && !b_data->meta) {
129 		rc = -1;
130 	} else if (b_data->meta && !a_data->meta) {
131 		rc = 1;
132 	} else if (a_data->stem_len < b_data->stem_len) {
133 		rc = -1;
134 	} else if (b_data->stem_len < a_data->stem_len) {
135 		rc = 1;
136 	} else if (a_data->str_len < b_data->str_len) {
137 		rc = -1;
138 	} else if (b_data->str_len < a_data->str_len) {
139 		rc = 1;
140 	} else if (a_filecon->type < b_filecon->type) {
141 		rc = -1;
142 	} else if (b_filecon->type < a_filecon->type) {
143 		rc = 1;
144 	}
145 
146 	free(a_path);
147 	free(b_path);
148 	free(a_data);
149 	free(b_data);
150 
151 	return rc;
152 }
153 
cil_post_portcon_compare(const void * a,const void * b)154 int cil_post_portcon_compare(const void *a, const void *b)
155 {
156 	int rc = SEPOL_ERR;
157 	struct cil_portcon *aportcon = *(struct cil_portcon**)a;
158 	struct cil_portcon *bportcon = *(struct cil_portcon**)b;
159 
160 	rc = (aportcon->port_high - aportcon->port_low)
161 		- (bportcon->port_high - bportcon->port_low);
162 	if (rc == 0) {
163 		if (aportcon->port_low < bportcon->port_low) {
164 			rc = -1;
165 		} else if (bportcon->port_low < aportcon->port_low) {
166 			rc = 1;
167 		}
168 	}
169 
170 	return rc;
171 }
172 
cil_post_genfscon_compare(const void * a,const void * b)173 int cil_post_genfscon_compare(const void *a, const void *b)
174 {
175 	int rc = SEPOL_ERR;
176 	struct cil_genfscon *agenfscon = *(struct cil_genfscon**)a;
177 	struct cil_genfscon *bgenfscon = *(struct cil_genfscon**)b;
178 
179 	rc = strcmp(agenfscon->fs_str, bgenfscon->fs_str);
180 	if (rc == 0) {
181 		rc = strcmp(agenfscon->path_str, bgenfscon->path_str);
182 	}
183 
184 	return rc;
185 }
186 
cil_post_netifcon_compare(const void * a,const void * b)187 int cil_post_netifcon_compare(const void *a, const void *b)
188 {
189 	struct cil_netifcon *anetifcon = *(struct cil_netifcon**)a;
190 	struct cil_netifcon *bnetifcon = *(struct cil_netifcon**)b;
191 
192 	return  strcmp(anetifcon->interface_str, bnetifcon->interface_str);
193 }
194 
cil_post_nodecon_compare(const void * a,const void * b)195 int cil_post_nodecon_compare(const void *a, const void *b)
196 {
197 	struct cil_nodecon *anodecon;
198 	struct cil_nodecon *bnodecon;
199 	anodecon = *(struct cil_nodecon**)a;
200 	bnodecon = *(struct cil_nodecon**)b;
201 
202 	/* sort ipv4 before ipv6 */
203 	if (anodecon->addr->family != bnodecon->addr->family) {
204 		if (anodecon->addr->family == AF_INET) {
205 			return -1;
206 		} else {
207 			return 1;
208 		}
209 	}
210 
211 	/* most specific netmask goes first, then order by ip addr */
212 	if (anodecon->addr->family == AF_INET) {
213 		int rc = memcmp(&anodecon->mask->ip.v4, &bnodecon->mask->ip.v4, sizeof(anodecon->mask->ip.v4));
214 		if (rc != 0) {
215 			return -1 * rc;
216 		}
217 		return memcmp(&anodecon->addr->ip.v4, &bnodecon->addr->ip.v4, sizeof(anodecon->addr->ip.v4));
218 	} else {
219 		int rc = memcmp(&anodecon->mask->ip.v6, &bnodecon->mask->ip.v6, sizeof(anodecon->mask->ip.v6));
220 		if (rc != 0) {
221 			return -1 * rc;
222 		}
223 		return memcmp(&anodecon->addr->ip.v6, &bnodecon->addr->ip.v6, sizeof(anodecon->addr->ip.v6));
224 	}
225 }
226 
cil_post_pirqcon_compare(const void * a,const void * b)227 int cil_post_pirqcon_compare(const void *a, const void *b)
228 {
229 	int rc = SEPOL_ERR;
230 	struct cil_pirqcon *apirqcon = *(struct cil_pirqcon**)a;
231 	struct cil_pirqcon *bpirqcon = *(struct cil_pirqcon**)b;
232 
233 	if (apirqcon->pirq < bpirqcon->pirq) {
234 		rc = -1;
235 	} else if (bpirqcon->pirq < apirqcon->pirq) {
236 		rc = 1;
237 	} else {
238 		rc = 0;
239 	}
240 
241 	return rc;
242 }
243 
cil_post_iomemcon_compare(const void * a,const void * b)244 int cil_post_iomemcon_compare(const void *a, const void *b)
245 {
246 	int rc = SEPOL_ERR;
247 	struct cil_iomemcon *aiomemcon = *(struct cil_iomemcon**)a;
248 	struct cil_iomemcon *biomemcon = *(struct cil_iomemcon**)b;
249 
250 	rc = (aiomemcon->iomem_high - aiomemcon->iomem_low)
251 		- (biomemcon->iomem_high - biomemcon->iomem_low);
252 	if (rc == 0) {
253 		if (aiomemcon->iomem_low < biomemcon->iomem_low) {
254 			rc = -1;
255 		} else if (biomemcon->iomem_low < aiomemcon->iomem_low) {
256 			rc = 1;
257 		}
258 	}
259 
260 	return rc;
261 }
262 
cil_post_ioportcon_compare(const void * a,const void * b)263 int cil_post_ioportcon_compare(const void *a, const void *b)
264 {
265 	int rc = SEPOL_ERR;
266 	struct cil_ioportcon *aioportcon = *(struct cil_ioportcon**)a;
267 	struct cil_ioportcon *bioportcon = *(struct cil_ioportcon**)b;
268 
269 	rc = (aioportcon->ioport_high - aioportcon->ioport_low)
270 		- (bioportcon->ioport_high - bioportcon->ioport_low);
271 	if (rc == 0) {
272 		if (aioportcon->ioport_low < bioportcon->ioport_low) {
273 			rc = -1;
274 		} else if (bioportcon->ioport_low < aioportcon->ioport_low) {
275 			rc = 1;
276 		}
277 	}
278 
279 	return rc;
280 }
281 
cil_post_pcidevicecon_compare(const void * a,const void * b)282 int cil_post_pcidevicecon_compare(const void *a, const void *b)
283 {
284 	int rc = SEPOL_ERR;
285 	struct cil_pcidevicecon *apcidevicecon = *(struct cil_pcidevicecon**)a;
286 	struct cil_pcidevicecon *bpcidevicecon = *(struct cil_pcidevicecon**)b;
287 
288 	if (apcidevicecon->dev < bpcidevicecon->dev) {
289 		rc = -1;
290 	} else if (bpcidevicecon->dev < apcidevicecon->dev) {
291 		rc = 1;
292 	} else {
293 		rc = 0;
294 	}
295 
296 	return rc;
297 }
298 
cil_post_devicetreecon_compare(const void * a,const void * b)299 int cil_post_devicetreecon_compare(const void *a, const void *b)
300 {
301 	int rc = SEPOL_ERR;
302 	struct cil_devicetreecon *adevicetreecon = *(struct cil_devicetreecon**)a;
303 	struct cil_devicetreecon *bdevicetreecon = *(struct cil_devicetreecon**)b;
304 
305 	rc = strcmp(adevicetreecon->path, bdevicetreecon->path);
306 
307 	return rc;
308 }
309 
cil_post_fsuse_compare(const void * a,const void * b)310 int cil_post_fsuse_compare(const void *a, const void *b)
311 {
312 	int rc;
313 	struct cil_fsuse *afsuse;
314 	struct cil_fsuse *bfsuse;
315 	afsuse = *(struct cil_fsuse**)a;
316 	bfsuse = *(struct cil_fsuse**)b;
317 	if (afsuse->type < bfsuse->type) {
318 		rc = -1;
319 	} else if (bfsuse->type < afsuse->type) {
320 		rc = 1;
321 	} else {
322 		rc = strcmp(afsuse->fs_str, bfsuse->fs_str);
323 	}
324 	return rc;
325 }
326 
__cil_post_db_count_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)327 static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
328 {
329 	struct cil_db *db = extra_args;
330 
331 	switch(node->flavor) {
332 	case CIL_BLOCK: {
333 		struct cil_block *blk = node->data;
334 		if (blk->is_abstract == CIL_TRUE) {
335 			*finished = CIL_TREE_SKIP_HEAD;
336 		}
337 		break;
338 	}
339 	case CIL_MACRO:
340 		*finished = CIL_TREE_SKIP_HEAD;
341 		break;
342 	case CIL_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 
__cil_post_db_array_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)404 static 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 
__evaluate_type_expression(struct cil_typeattribute * attr,struct cil_db * db)575 static 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 
__cil_type_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)590 static 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 
623 exit:
624 	return rc;
625 }
626 
__evaluate_role_expression(struct cil_roleattribute * attr,struct cil_db * db)627 static 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 
__cil_role_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)642 static 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 
667 exit:
668 	return rc;
669 }
670 
__cil_perm_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)671 static 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 
__evaluate_cat_expression(struct cil_cats * cats,struct cil_db * db)686 static 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 
732 exit:
733 	return rc;
734 }
735 
__cil_cat_to_bitmap(struct cil_symtab_datum * datum,ebitmap_t * bitmap,struct cil_db * db)736 static 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 
777 exit:
778 	return rc;
779 }
780 
__cil_expr_range_to_bitmap_helper(struct cil_list_item * i1,struct cil_list_item * i2,ebitmap_t * bitmap)781 static 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 
817 exit:
818 	return rc;
819 }
820 
__cil_expr_to_bitmap_helper(struct cil_list_item * curr,enum cil_flavor flavor,ebitmap_t * bitmap,int max,struct cil_db * db)821 static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flavor flavor, ebitmap_t *bitmap, int max, struct cil_db *db)
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 
__cil_expr_to_bitmap(struct cil_list * expr,ebitmap_t * out,int max,struct cil_db * db)854 static 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 
960 exit:
961 	return rc;
962 }
963 
__cil_expr_list_to_bitmap(struct cil_list * expr_list,ebitmap_t * out,int max,struct cil_db * db)964 static 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 
991 exit:
992 	return SEPOL_ERR;
993 }
994 
__cil_post_db_attr_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)995 static 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 
1034 exit:
1035 	return rc;
1036 }
1037 
__cil_role_assign_types(struct cil_role * role,struct cil_symtab_datum * datum)1038 static 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 
1067 exit:
1068 	return SEPOL_ERR;
1069 }
1070 
__cil_post_db_roletype_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1071 static 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;
1128 exit:
1129 	cil_log(CIL_INFO, "cil_post_db_roletype_helper failed\n");
1130 	return rc;
1131 }
1132 
__evaluate_level_expression(struct cil_level * level,struct cil_db * db)1133 static 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 
__evaluate_levelrange_expression(struct cil_levelrange * levelrange,struct cil_db * db)1142 static 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 
1159 exit:
1160 	return rc;
1161 }
1162 
__cil_post_db_cat_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1163 static 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 
1355 exit:
1356 	return rc;
1357 }
1358 
1359 struct perm_to_list {
1360 	enum cil_flavor flavor;
1361 	ebitmap_t *perms;
1362 	struct cil_list *new_list;
1363 };
1364 
__perm_bits_to_list(hashtab_key_t k,hashtab_datum_t d,void * args)1365 static 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 
__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)1382 static int __evaluate_perm_expression(struct cil_list *perms, enum cil_flavor flavor, symtab_t *class_symtab, symtab_t *common_symtab, unsigned int num_perms, struct cil_list **new_list, struct cil_db *db)
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 
1414 exit:
1415 	return rc;
1416 }
1417 
__evaluate_classperms(struct cil_classperms * cp,struct cil_db * db)1418 static 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 
1445 exit:
1446 	return rc;
1447 }
1448 
__evaluate_classperms_list(struct cil_list * classperms,struct cil_db * db)1449 static 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 
1484 exit:
1485 	return rc;
1486 }
1487 
1488 struct class_map_args {
1489 	struct cil_db *db;
1490 	int rc;
1491 };
1492 
__evaluate_map_perm_classperms(hashtab_key_t k,hashtab_datum_t d,void * args)1493 static 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 
__evaluate_map_class(struct cil_class * mc,struct cil_db * db)1507 static 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 
__cil_post_db_classperms_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1518 static 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 
1572 exit:
1573 	return rc;
1574 }
1575 
cil_post_db(struct cil_db * db)1576 static 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 
1628 exit:
1629 	return rc;
1630 }
1631 
cil_post_verify(struct cil_db * db)1632 static 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 
1689 exit:
1690 	cil_complex_symtab_destroy(&csymtab);
1691 	return rc;
1692 }
1693 
cil_post_process(struct cil_db * db)1694 int 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 
1715 exit:
1716 	return rc;
1717 
1718 }
1719