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