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