• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Authors: Steve Lawrence <slawrence@tresys.com>
2  *
3  * Functions to convert policy module to CIL
4  *
5  * Copyright (C) 2015 Tresys Technology, LLC
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2.1 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include <arpa/inet.h>
23 #include <ctype.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <getopt.h>
27 #include <libgen.h>
28 #include <netinet/in.h>
29 #ifndef IPPROTO_DCCP
30 #define IPPROTO_DCCP 33
31 #endif
32 #include <signal.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <inttypes.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 
42 #include <sepol/module.h>
43 #include <sepol/module_to_cil.h>
44 #include <sepol/policydb/conditional.h>
45 #include <sepol/policydb/hashtab.h>
46 #include <sepol/policydb/polcaps.h>
47 #include <sepol/policydb/policydb.h>
48 #include <sepol/policydb/services.h>
49 #include <sepol/policydb/util.h>
50 
51 #include "private.h"
52 
53 #ifdef __GNUC__
54 #  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
55 #else
56 #  define UNUSED(x) UNUSED_ ## x
57 #endif
58 
59 FILE *out_file;
60 
61 #define STACK_SIZE 16
62 #define DEFAULT_LEVEL "systemlow"
63 #define DEFAULT_OBJECT "object_r"
64 #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/cil/src/cil_post.c */
65 #define TYPEATTR_INFIX "_typeattr_"        /* Also in libsepol/cil/src/cil_post.c */
66 #define ROLEATTR_INFIX "_roleattr_"
67 
68 __attribute__ ((format(printf, 1, 2)))
log_err(const char * fmt,...)69 static void log_err(const char *fmt, ...)
70 {
71 	va_list argptr;
72 	va_start(argptr, fmt);
73 	if (vfprintf(stderr, fmt, argptr) < 0) {
74 		_exit(EXIT_FAILURE);
75 	}
76 	va_end(argptr);
77 	if (fprintf(stderr, "\n") < 0) {
78 		_exit(EXIT_FAILURE);
79 	}
80 }
81 
cil_indent(int indent)82 static void cil_indent(int indent)
83 {
84 	if (fprintf(out_file, "%*s", indent * 4, "") < 0) {
85 		log_err("Failed to write to output");
86 		_exit(EXIT_FAILURE);
87 	}
88 }
89 
90 __attribute__ ((format(printf, 1, 2)))
cil_printf(const char * fmt,...)91 static void cil_printf(const char *fmt, ...) {
92 	va_list argptr;
93 	va_start(argptr, fmt);
94 	if (vfprintf(out_file, fmt, argptr) < 0) {
95 		log_err("Failed to write to output");
96 		_exit(EXIT_FAILURE);
97 	}
98 	va_end(argptr);
99 }
100 
101 __attribute__ ((format(printf, 2, 3)))
cil_println(int indent,const char * fmt,...)102 static void cil_println(int indent, const char *fmt, ...)
103 {
104 	cil_indent(indent);
105 	va_list argptr;
106 	va_start(argptr, fmt);
107 	if (vfprintf(out_file, fmt, argptr) < 0) {
108 		log_err("Failed to write to output");
109 		_exit(EXIT_FAILURE);
110 	}
111 	va_end(argptr);
112 	if (fprintf(out_file, "\n") < 0) {
113 		log_err("Failed to write to output");
114 		_exit(EXIT_FAILURE);
115 	}
116 }
117 
get_line(char ** start,char * end,char ** line)118 static int get_line(char **start, char *end, char **line)
119 {
120 	int rc = 1;
121 	char *p = NULL;
122 	size_t len = 0;
123 
124 	*line = NULL;
125 
126 	for (p = *start; p < end && isspace(*p); p++);
127 
128 	*start = p;
129 
130 	for (len = 0; p < end && *p != '\n' && *p != '\0'; p++, len++);
131 
132 	if (zero_or_saturated(len)) {
133 		rc = 0;
134 		goto exit;
135 	}
136 
137 	*line = malloc(len+1);
138 	if (*line == NULL) {
139 		log_err("Out of memory");
140 		rc = -1;
141 		goto exit;
142 	}
143 
144 	memcpy(*line, *start, len);
145 	(*line)[len] = '\0';
146 
147 	*start = p;
148 
149 	return rc;
150 
151 exit:
152 	*start = NULL;
153 	return rc;
154 }
155 
156 struct map_args {
157 	struct policydb *pdb;
158 	struct avrule_block *block;
159 	struct stack *decl_stack;
160 	int scope;
161 	int indent;
162 	int sym_index;
163 };
164 
165 struct stack {
166 	 void **stack;
167 	 int pos;
168 	 int size;
169 };
170 
171 struct role_list_node {
172 	char *role_name;
173 	role_datum_t *role;
174 };
175 
176 struct attr_list_node {
177 	char *attr_name;
178 	int is_type;
179 	void *set;
180 };
181 
182 struct list_node {
183 	void *data;
184 	struct list_node *next;
185 };
186 
187 struct list {
188 	struct list_node *head;
189 };
190 
191 /* A linked list of all roles stored in the pdb
192  * which is iterated to determine types associated
193  * with each role when printing role_type statements
194  */
195 static struct list *role_list;
196 
list_destroy(struct list ** list)197 static void list_destroy(struct list **list)
198 {
199 	struct list_node *curr = (*list)->head;
200 	struct list_node *tmp;
201 
202 	while (curr != NULL) {
203 		tmp = curr->next;
204 		free(curr);
205 		curr = tmp;
206 	}
207 
208 	free(*list);
209 	*list = NULL;
210 }
211 
role_list_destroy(void)212 static void role_list_destroy(void)
213 {
214 	struct list_node *curr = role_list->head;
215 
216 	while (curr != NULL) {
217 		free(curr->data);
218 		curr->data = NULL;
219 		curr = curr->next;
220 	}
221 
222 	list_destroy(&role_list);
223 }
224 
attr_list_destroy(struct list ** attr_list)225 static void attr_list_destroy(struct list **attr_list)
226 {
227 	if (attr_list == NULL || *attr_list == NULL) {
228 		return;
229 	}
230 
231 	struct list_node *curr = (*attr_list)->head;
232 	struct attr_list_node *attr;
233 
234 	while (curr != NULL) {
235 		attr = curr->data;
236 		if (attr != NULL) {
237 			free(attr->attr_name);
238 		}
239 
240 		free(curr->data);
241 		curr->data = NULL;
242 		curr = curr->next;
243 	}
244 
245 	list_destroy(attr_list);
246 }
247 
list_init(struct list ** list)248 static int list_init(struct list **list)
249 {
250 	struct list *l = calloc(1, sizeof(*l));
251 	if (l == NULL) {
252 		return -1;
253 	}
254 
255 	*list = l;
256 	return 0;
257 }
258 
list_prepend(struct list * list,void * data)259 static int list_prepend(struct list *list, void *data)
260 {
261 	int rc = -1;
262 	struct list_node *node = calloc(1, sizeof(*node));
263 	if (node == NULL) {
264 		goto exit;
265 	}
266 
267 	node->data = data;
268 	node->next = list->head;
269 	list->head = node;
270 
271 	rc = 0;
272 
273 exit:
274 	return rc;
275 }
276 
roles_gather_map(char * key,void * data,void * args)277 static int roles_gather_map(char *key, void *data, void *args)
278 {
279 	struct role_list_node *role_node;
280 	role_datum_t *role = data;
281 	int rc = -1;
282 
283 	role_node = calloc(1, sizeof(*role_node));
284 	if (role_node == NULL) {
285 		return rc;
286 	}
287 
288 	role_node->role_name = key;
289 	role_node->role = role;
290 
291 	rc = list_prepend((struct list *)args, role_node);
292 	return rc;
293 }
294 
role_list_create(hashtab_t roles_tab)295 static int role_list_create(hashtab_t roles_tab)
296 {
297 	int rc = -1;
298 
299 	rc = list_init(&role_list);
300 	if (rc != 0) {
301 		goto exit;
302 	}
303 
304 	rc = hashtab_map(roles_tab, roles_gather_map, role_list);
305 
306 exit:
307 	return rc;
308 }
309 
310 // array of lists, where each list contains all the aliases defined in the scope at index i
311 static struct list **typealias_lists;
312 static uint32_t typealias_lists_len;
313 
typealiases_gather_map(char * key,void * data,void * arg)314 static int typealiases_gather_map(char *key, void *data, void *arg)
315 {
316 	int rc = -1;
317 	struct type_datum *type = data;
318 	struct policydb *pdb = arg;
319 	struct scope_datum *scope;
320 	uint32_t i;
321 	uint32_t scope_id;
322 
323 	if (type->primary != 1) {
324 		scope = hashtab_search(pdb->scope[SYM_TYPES].table, key);
325 		if (scope == NULL) {
326 			return -1;
327 		}
328 
329 		for (i = 0; i < scope->decl_ids_len; i++) {
330 			scope_id = scope->decl_ids[i];
331 			if (typealias_lists[scope_id] == NULL) {
332 				rc = list_init(&typealias_lists[scope_id]);
333 				if (rc != 0) {
334 					goto exit;
335 				}
336 			}
337 			list_prepend(typealias_lists[scope_id], key);
338 		}
339 	}
340 
341 	return 0;
342 
343 exit:
344 	return rc;
345 }
346 
typealias_list_destroy(void)347 static void typealias_list_destroy(void)
348 {
349 	uint32_t i;
350 	for (i = 0; i < typealias_lists_len; i++) {
351 		if (typealias_lists[i] != NULL) {
352 			list_destroy(&typealias_lists[i]);
353 		}
354 	}
355 	typealias_lists_len = 0;
356 	free(typealias_lists);
357 	typealias_lists = NULL;
358 }
359 
typealias_list_create(struct policydb * pdb)360 static int typealias_list_create(struct policydb *pdb)
361 {
362 	uint32_t max_decl_id = 0;
363 	struct avrule_decl *decl;
364 	struct avrule_block *block;
365 	uint32_t rc = -1;
366 
367 	for (block = pdb->global; block != NULL; block = block->next) {
368 		decl = block->branch_list;
369 		if (decl != NULL && decl->decl_id > max_decl_id) {
370 			max_decl_id = decl->decl_id;
371 		}
372 	}
373 
374 	typealias_lists = calloc(max_decl_id + 1, sizeof(*typealias_lists));
375 	typealias_lists_len = max_decl_id + 1;
376 
377 	rc = hashtab_map(pdb->p_types.table, typealiases_gather_map, pdb);
378 	if (rc != 0) {
379 		goto exit;
380 	}
381 
382 	return 0;
383 
384 exit:
385 	typealias_list_destroy();
386 
387 	return rc;
388 }
389 
390 
stack_destroy(struct stack ** stack)391 static int stack_destroy(struct stack **stack)
392 {
393 	if (stack == NULL || *stack == NULL) {
394 		return 0;
395 	}
396 
397 	free((*stack)->stack);
398 	free(*stack);
399 	*stack = NULL;
400 
401 	return 0;
402 }
403 
stack_init(struct stack ** stack)404 static int stack_init(struct stack **stack)
405 {
406 	int rc = -1;
407 	struct stack *s = calloc(1, sizeof(*s));
408 	if (s == NULL) {
409 		goto exit;
410 	}
411 
412 	s->stack = malloc(sizeof(*s->stack) * STACK_SIZE);
413 	if (s->stack == NULL) {
414 		goto exit;
415 	}
416 
417 	s->pos = -1;
418 	s->size = STACK_SIZE;
419 
420 	*stack = s;
421 
422 	return 0;
423 
424 exit:
425 	stack_destroy(&s);
426 	return rc;
427 }
428 
stack_push(struct stack * stack,void * ptr)429 static int stack_push(struct stack *stack, void *ptr)
430 {
431 	int rc = -1;
432 	void *new_stack;
433 
434 	if (stack->pos + 1 == stack->size) {
435 		new_stack = realloc(stack->stack, sizeof(*stack->stack) * (stack->size * 2));
436 		if (new_stack == NULL) {
437 			goto exit;
438 		}
439 		stack->stack = new_stack;
440 		stack->size *= 2;
441 	}
442 
443 	stack->pos++;
444 	stack->stack[stack->pos] = ptr;
445 
446 	rc = 0;
447 exit:
448 	return rc;
449 }
450 
stack_pop(struct stack * stack)451 static void *stack_pop(struct stack *stack)
452 {
453 	if (stack->pos == -1) {
454 		return NULL;
455 	}
456 
457 	stack->pos--;
458 	return stack->stack[stack->pos + 1];
459 }
460 
stack_peek(struct stack * stack)461 static void *stack_peek(struct stack *stack)
462 {
463 	if (stack->pos == -1) {
464 		return NULL;
465 	}
466 
467 	return stack->stack[stack->pos];
468 }
469 
is_id_in_scope_with_start(struct policydb * pdb,struct stack * decl_stack,int start,uint32_t symbol_type,char * id)470 static int is_id_in_scope_with_start(struct policydb *pdb, struct stack *decl_stack, int start, uint32_t symbol_type, char *id)
471 {
472 	int i;
473 	uint32_t j;
474 	struct avrule_decl *decl;
475 	struct scope_datum *scope;
476 
477 	scope = hashtab_search(pdb->scope[symbol_type].table, id);
478 	if (scope == NULL) {
479 		return 0;
480 	}
481 
482 	for (i = start; i >= 0; i--) {
483 		decl = decl_stack->stack[i];
484 
485 		for (j = 0; j < scope->decl_ids_len; j++) {
486 			if (scope->decl_ids[j] == decl->decl_id) {
487 				return 1;
488 			}
489 		}
490 	}
491 
492 	return 0;
493 }
494 
is_id_in_ancestor_scope(struct policydb * pdb,struct stack * decl_stack,char * type,uint32_t symbol_type)495 static int is_id_in_ancestor_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type)
496 {
497 	int start = decl_stack->pos - 1;
498 
499 	return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type);
500 }
501 
is_id_in_scope(struct policydb * pdb,struct stack * decl_stack,char * type,uint32_t symbol_type)502 static int is_id_in_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type)
503 {
504 	int start = decl_stack->pos;
505 
506 	return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type);
507 }
508 
semantic_level_to_cil(struct policydb * pdb,int sens_offset,struct mls_semantic_level * level)509 static int semantic_level_to_cil(struct policydb *pdb, int sens_offset, struct mls_semantic_level *level)
510 {
511 	struct mls_semantic_cat *cat;
512 
513 	cil_printf("(%s ", pdb->p_sens_val_to_name[level->sens - sens_offset]);
514 
515 	if (level->cat != NULL) {
516 		cil_printf("(");
517 	}
518 
519 	for (cat = level->cat; cat != NULL; cat = cat->next) {
520 		if (cat->low == cat->high) {
521 			cil_printf("%s", pdb->p_cat_val_to_name[cat->low - 1]);
522 		} else {
523 			cil_printf("range %s %s", pdb->p_cat_val_to_name[cat->low - 1], pdb->p_cat_val_to_name[cat->high - 1]);
524 		}
525 
526 		if (cat->next != NULL) {
527 			cil_printf(" ");
528 		}
529 	}
530 
531 	if (level->cat != NULL) {
532 		cil_printf(")");
533 	}
534 
535 	cil_printf(")");
536 
537 	return 0;
538 }
539 
avrule_to_cil(int indent,struct policydb * pdb,uint32_t type,const char * src,const char * tgt,const struct class_perm_node * classperms)540 static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const struct class_perm_node *classperms)
541 {
542 	int rc = -1;
543 	const char *rule;
544 	const struct class_perm_node *classperm;
545 	char *perms;
546 
547 	switch (type) {
548 	case AVRULE_ALLOWED:
549 		rule = "allow";
550 		break;
551 	case AVRULE_AUDITALLOW:
552 		rule = "auditallow";
553 		break;
554 	case AVRULE_AUDITDENY:
555 		rule = "auditdenty";
556 		break;
557 	case AVRULE_DONTAUDIT:
558 		rule = "dontaudit";
559 		break;
560 	case AVRULE_NEVERALLOW:
561 		rule = "neverallow";
562 		break;
563 	case AVRULE_TRANSITION:
564 		rule = "typetransition";
565 		break;
566 	case AVRULE_MEMBER:
567 		rule = "typemember";
568 		break;
569 	case AVRULE_CHANGE:
570 		rule = "typechange";
571 		break;
572 	default:
573 		log_err("Unknown avrule type: %i", type);
574 		rc = -1;
575 		goto exit;
576 	}
577 
578 	for (classperm = classperms; classperm != NULL; classperm = classperm->next) {
579 		if (type & AVRULE_AV) {
580 			perms = sepol_av_to_string(pdb, classperm->tclass, classperm->data);
581 			if (perms == NULL) {
582 				log_err("Failed to generate permission string");
583 				rc = -1;
584 				goto exit;
585 			}
586 			cil_println(indent, "(%s %s %s (%s (%s)))",
587 					rule, src, tgt,
588 					pdb->p_class_val_to_name[classperm->tclass - 1],
589 					perms + 1);
590 		} else {
591 			cil_println(indent, "(%s %s %s %s %s)",
592 					rule, src, tgt,
593 					pdb->p_class_val_to_name[classperm->tclass - 1],
594 					pdb->p_type_val_to_name[classperm->data - 1]);
595 		}
596 	}
597 
598 	return 0;
599 
600 exit:
601 	return rc;
602 }
603 
604 #define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p))
605 
xperms_to_cil(const av_extended_perms_t * xperms)606 static int xperms_to_cil(const av_extended_perms_t *xperms)
607 {
608 	uint16_t value;
609 	uint16_t low_bit;
610 	uint16_t low_value;
611 	unsigned int bit;
612 	unsigned int in_range = 0;
613 	int first = 1;
614 
615 	if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
616 		&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
617 		return -1;
618 
619 	for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
620 		if (!xperm_test(bit, xperms->perms))
621 			continue;
622 
623 		if (in_range && next_bit_in_range(bit, xperms->perms)) {
624 			/* continue until high value found */
625 			continue;
626 		} else if (next_bit_in_range(bit, xperms->perms)) {
627 			/* low value */
628 			low_bit = bit;
629 			in_range = 1;
630 			continue;
631 		}
632 
633 		if (!first)
634 			cil_printf(" ");
635 		else
636 			first = 0;
637 
638 		if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
639 			value = xperms->driver<<8 | bit;
640 			low_value = xperms->driver<<8 | low_bit;
641 			if (in_range) {
642 				cil_printf("(range 0x%hx 0x%hx)", low_value, value);
643 				in_range = 0;
644 			} else {
645 				cil_printf("0x%hx", value);
646 			}
647 		} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
648 			value = bit << 8;
649 			low_value = low_bit << 8;
650 			if (in_range) {
651 				cil_printf("(range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff));
652 				in_range = 0;
653 			} else {
654 				cil_printf("(range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff));
655 			}
656 		}
657 	}
658 
659 	return 0;
660 }
661 
avrulex_to_cil(int indent,struct policydb * pdb,uint32_t type,const char * src,const char * tgt,const class_perm_node_t * classperms,const av_extended_perms_t * xperms)662 static int avrulex_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const class_perm_node_t *classperms, const av_extended_perms_t *xperms)
663 {
664 	int rc = -1;
665 	const char *rule;
666 	const struct class_perm_node *classperm;
667 
668 	switch (type) {
669 	case AVRULE_XPERMS_ALLOWED:
670 		rule = "allowx";
671 		break;
672 	case AVRULE_XPERMS_AUDITALLOW:
673 		rule = "auditallowx";
674 		break;
675 	case AVRULE_XPERMS_DONTAUDIT:
676 		rule = "dontauditx";
677 		break;
678 	case AVRULE_XPERMS_NEVERALLOW:
679 		rule = "neverallowx";
680 		break;
681 	default:
682 		log_err("Unknown avrule xperm type: %i", type);
683 		rc = -1;
684 		goto exit;
685 	}
686 
687 	for (classperm = classperms; classperm != NULL; classperm = classperm->next) {
688 		cil_indent(indent);
689 		cil_printf("(%s %s %s (%s %s (", rule, src, tgt,
690 			   "ioctl", pdb->p_class_val_to_name[classperm->tclass - 1]);
691 		xperms_to_cil(xperms);
692 		cil_printf(")))\n");
693 	}
694 
695 	return 0;
696 
697 exit:
698 	return rc;
699 }
700 
num_digits(int n)701 static int num_digits(int n)
702 {
703 	int num = 1;
704 	while (n >= 10) {
705 		n /= 10;
706 		num++;
707 	}
708 	return num;
709 }
710 
ebitmap_to_cil(struct policydb * pdb,struct ebitmap * map,int type)711 static int ebitmap_to_cil(struct policydb *pdb, struct ebitmap *map, int type)
712 {
713 	struct ebitmap_node *node;
714 	uint32_t i;
715 	char **val_to_name = pdb->sym_val_to_name[type];
716 
717 	ebitmap_for_each_bit(map, node, i) {
718 		if (!ebitmap_get_bit(map, i)) {
719 			continue;
720 		}
721 		cil_printf("%s ", val_to_name[i]);
722 	}
723 
724 	return 0;
725 }
726 
get_new_attr_name(struct policydb * pdb,int is_type)727 static char *get_new_attr_name(struct policydb *pdb, int is_type)
728 {
729 	static unsigned int num_attrs = 0;
730 	int len, rlen;
731 	const char *infix;
732 	char *attr_name = NULL;
733 
734 	num_attrs++;
735 
736 	if (is_type) {
737 		infix = TYPEATTR_INFIX;
738 	} else {
739 		infix = ROLEATTR_INFIX;
740 	}
741 
742 	len = strlen(pdb->name) + strlen(infix) + num_digits(num_attrs) + 1;
743 	attr_name = malloc(len);
744 	if (!attr_name) {
745 		log_err("Out of memory");
746 		goto exit;
747 	}
748 
749 	rlen = snprintf(attr_name, len, "%s%s%i", pdb->name, infix, num_attrs);
750 	if (rlen < 0 || rlen >= len) {
751 		log_err("Failed to generate attribute name");
752 		free(attr_name);
753 		attr_name = NULL;
754 		goto exit;
755 	}
756 
757 exit:
758 	return attr_name;
759 }
760 
cil_add_attr_to_list(struct list * attr_list,char * attr_name,int is_type,void * set)761 static int cil_add_attr_to_list(struct list *attr_list, char *attr_name, int is_type, void *set)
762 {
763 	struct attr_list_node *attr_list_node = NULL;
764 	int rc = 0;
765 
766 	attr_list_node = calloc(1, sizeof(*attr_list_node));
767 	if (attr_list_node == NULL) {
768 		log_err("Out of memory");
769 		rc = -1;
770 		goto exit;
771 	}
772 
773 	rc = list_prepend(attr_list, attr_list_node);
774 	if (rc != 0) {
775 		goto exit;
776 	}
777 
778 	attr_list_node->attr_name = attr_name;
779 	attr_list_node->is_type = is_type;
780 	attr_list_node->set = set;
781 
782 	return rc;
783 
784 exit:
785 	free(attr_list_node);
786 	return rc;
787 }
788 
cil_print_attr_strs(int indent,struct policydb * pdb,int is_type,void * set,char * attr_name)789 static int cil_print_attr_strs(int indent, struct policydb *pdb, int is_type, void *set, char *attr_name)
790 {
791 	// CIL doesn't support anonymous positive/negative/complemented sets.  So
792 	// instead we create a CIL type/roleattributeset that matches the set. If
793 	// the set has a negative set, then convert it to is (P & !N), where P is
794 	// the list of members in the positive set and N is the list of members
795 	// in the negative set. Additionally, if the set is complemented, then wrap
796 	// the whole thing with a negation.
797 
798 	struct ebitmap_node *node;
799 	struct ebitmap *pos, *neg;
800 	uint32_t flags;
801 	unsigned i;
802 	struct type_set *ts;
803 	struct role_set *rs;
804 	int has_positive, has_negative;
805 	const char *kind;
806 	char **val_to_name;
807 	int rc = 0;
808 
809 	if (is_type) {
810 		kind = "type";
811 		val_to_name = pdb->p_type_val_to_name;
812 		ts = (struct type_set *)set;
813 		pos = &ts->types;
814 		neg = &ts->negset;
815 		flags = ts->flags;
816 		has_positive = pos && (ebitmap_length(pos) > 0);
817 		has_negative = neg && (ebitmap_length(neg) > 0);
818 	} else {
819 		kind = "role";
820 		val_to_name = pdb->p_role_val_to_name;
821 		rs = (struct role_set *)set;
822 		pos = &rs->roles;
823 		neg = NULL;
824 		flags = rs->flags;
825 		has_positive = pos && (ebitmap_length(pos) > 0);
826 		has_negative = 0;
827 	}
828 
829 	cil_println(indent, "(%sattribute %s)", kind, attr_name);
830 	cil_indent(indent);
831 	cil_printf("(%sattributeset %s ", kind, attr_name);
832 
833 	if (flags & TYPE_STAR) {
834 		cil_printf("(all)");
835 	}
836 
837 	if (flags & TYPE_COMP) {
838 		cil_printf("(not ");
839 	}
840 
841 	if (has_positive && has_negative) {
842 		cil_printf("(and ");
843 	}
844 
845 	if (has_positive) {
846 		cil_printf("(");
847 		ebitmap_for_each_bit(pos, node, i) {
848 			if (!ebitmap_get_bit(pos, i)) {
849 				continue;
850 			}
851 			cil_printf("%s ", val_to_name[i]);
852 		}
853 		cil_printf(") ");
854 	}
855 
856 	if (has_negative) {
857 		cil_printf("(not (");
858 
859 		ebitmap_for_each_bit(neg, node, i) {
860 			if (!ebitmap_get_bit(neg, i)) {
861 				continue;
862 			}
863 			cil_printf("%s ", val_to_name[i]);
864 		}
865 
866 		cil_printf("))");
867 	}
868 
869 	if (has_positive && has_negative) {
870 		cil_printf(")");
871 	}
872 
873 	if (flags & TYPE_COMP) {
874 		cil_printf(")");
875 	}
876 
877 	cil_printf(")\n");
878 
879 	return rc;
880 }
881 
cil_print_attr_list(int indent,struct policydb * pdb,struct list * attr_list)882 static int cil_print_attr_list(int indent, struct policydb *pdb, struct list *attr_list)
883 {
884 	struct list_node *curr;
885 	struct attr_list_node *node;
886 	int rc = 0;
887 
888 	for (curr = attr_list->head; curr != NULL; curr = curr->next) {
889 		node = curr->data;
890 		rc = cil_print_attr_strs(indent, pdb, node->is_type, node->set, node->attr_name);
891 		if (rc != 0) {
892 			return rc;
893 		}
894 	}
895 
896 	return rc;
897 }
898 
search_attr_list(struct list * attr_list,int is_type,void * set)899 static char *search_attr_list(struct list *attr_list, int is_type, void *set)
900 {
901 	struct list_node *curr;
902 	struct attr_list_node *node;
903 	struct role_set *rs1 = NULL, *rs2;
904 	struct type_set *ts1 = NULL, *ts2;
905 
906 	if (is_type) {
907 		ts1 = (struct type_set *)set;
908 	} else {
909 		rs1 = (struct role_set *)set;
910 	}
911 
912 	for (curr = attr_list->head; curr != NULL; curr = curr->next) {
913 		node = curr->data;
914 		if (node->is_type != is_type)
915 			continue;
916 		if (ts1) {
917 			ts2 = (struct type_set *)node->set;
918 			if (ts1->flags != ts2->flags)
919 				continue;
920 			if (ebitmap_cmp(&ts1->negset, &ts2->negset) == 0)
921 				continue;
922 			if (ebitmap_cmp(&ts1->types, &ts2->types) == 0)
923 				continue;
924 			return node->attr_name;
925 		} else {
926 			rs2 = (struct role_set *)node->set;
927 			if (rs1->flags != rs2->flags)
928 				continue;
929 			if (ebitmap_cmp(&rs1->roles, &rs2->roles) == 0)
930 				continue;
931 			return node->attr_name;
932 		}
933 	}
934 
935 	return NULL;
936 }
937 
set_to_names(struct policydb * pdb,int is_type,void * set,struct list * attr_list,char *** names,int * num_names)938 static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, int *num_names)
939 {
940 	char *attr_name = NULL;
941 	int rc = 0;
942 
943 	*names = NULL;
944 	*num_names = 0;
945 
946 	attr_name = search_attr_list(attr_list, is_type, set);
947 
948 	if (!attr_name) {
949 		attr_name = get_new_attr_name(pdb, is_type);
950 		if (!attr_name) {
951 			rc = -1;
952 			goto exit;
953 		}
954 
955 		rc = cil_add_attr_to_list(attr_list, attr_name, is_type, set);
956 		if (rc != 0) {
957 			free(attr_name);
958 			goto exit;
959 		}
960 	}
961 
962 	*names = malloc(sizeof(char *));
963 	if (!*names) {
964 		log_err("Out of memory");
965 		rc = -1;
966 		goto exit;
967 	}
968 	*names[0] = attr_name;
969 	*num_names = 1;
970 
971 exit:
972 	return rc;
973 }
974 
ebitmap_to_names(struct ebitmap * map,char ** vals_to_names,char *** names,int * num_names)975 static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, int *num_names)
976 {
977 	int rc = 0;
978 	struct ebitmap_node *node;
979 	uint32_t i;
980 	uint32_t num;
981 	char **name_arr;
982 
983 	num = 0;
984 	ebitmap_for_each_bit(map, node, i) {
985 		if (ebitmap_get_bit(map, i))
986 			num++;
987 	}
988 
989 	name_arr = malloc(sizeof(*name_arr) * num);
990 	if (name_arr == NULL) {
991 		log_err("Out of memory");
992 		rc = -1;
993 		goto exit;
994 	}
995 
996 	num = 0;
997 	ebitmap_for_each_bit(map, node, i) {
998 		if (ebitmap_get_bit(map, i)) {
999 			name_arr[num] = vals_to_names[i];
1000 			num++;
1001 		}
1002 	}
1003 
1004 	*names = name_arr;
1005 	*num_names = num;
1006 
1007 exit:
1008 	return rc;
1009 }
1010 
process_roleset(struct policydb * pdb,struct role_set * rs,struct list * attr_list,char *** names,int * num_names)1011 static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, int *num_names)
1012 {
1013 	int rc = 0;
1014 
1015 	*names = NULL;
1016 	*num_names = 0;
1017 
1018 	if (rs->flags) {
1019 		rc = set_to_names(pdb, 0, &rs->roles, attr_list, names, num_names);
1020 		if (rc != 0) {
1021 			goto exit;
1022 		}
1023 	} else {
1024 		rc = ebitmap_to_names(&rs->roles, pdb->p_role_val_to_name, names, num_names);
1025 		if (rc != 0) {
1026 			goto exit;
1027 		}
1028 	}
1029 
1030 exit:
1031 	return rc;
1032 }
1033 
process_typeset(struct policydb * pdb,struct type_set * ts,struct list * attr_list,char *** names,int * num_names)1034 static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, int *num_names)
1035 {
1036 	int rc = 0;
1037 
1038 	*names = NULL;
1039 	*num_names = 0;
1040 
1041 	if (ebitmap_length(&ts->negset) > 0 || ts->flags != 0) {
1042 		rc = set_to_names(pdb, 1, ts, attr_list, names, num_names);
1043 		if (rc != 0) {
1044 			goto exit;
1045 		}
1046 	} else {
1047 		rc = ebitmap_to_names(&ts->types, pdb->p_type_val_to_name, names, num_names);
1048 		if (rc != 0) {
1049 			goto exit;
1050 		}
1051 	}
1052 
1053 exit:
1054 	return rc;
1055 }
1056 
names_destroy(char *** names,int * num_names)1057 static void names_destroy(char ***names, int *num_names)
1058 {
1059 	free(*names);
1060 	*names = NULL;
1061 	*num_names = 0;
1062 }
1063 
roletype_role_in_ancestor_to_cil(struct policydb * pdb,struct stack * decl_stack,char * type_name,int indent)1064 static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *decl_stack, char *type_name, int indent)
1065 {
1066 	struct list_node *curr;
1067 	char **tnames = NULL;
1068 	int num_tnames, i;
1069 	struct role_list_node *role_node = NULL;
1070 	int rc;
1071 	struct type_set *ts;
1072 	struct list *attr_list = NULL;
1073 
1074 	rc = list_init(&attr_list);
1075 	if (rc != 0) {
1076 		goto exit;
1077 	}
1078 
1079 	curr = role_list->head;
1080 	for (curr = role_list->head; curr != NULL; curr = curr->next) {
1081 		role_node = curr->data;
1082 		if (!is_id_in_ancestor_scope(pdb, decl_stack, role_node->role_name, SYM_ROLES)) {
1083 			continue;
1084 		}
1085 
1086 		ts = &role_node->role->types;
1087 		rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
1088 		if (rc != 0) {
1089 			goto exit;
1090 		}
1091 		for (i = 0; i < num_tnames; i++) {
1092 			if (!strcmp(type_name, tnames[i])) {
1093 				cil_println(indent, "(roletype %s %s)", role_node->role_name, type_name);
1094 			}
1095 		}
1096 		names_destroy(&tnames, &num_tnames);
1097 	}
1098 
1099 	rc = cil_print_attr_list(indent, pdb, attr_list);
1100 	if (rc != 0) {
1101 		goto exit;
1102 	}
1103 
1104 exit:
1105 	attr_list_destroy(&attr_list);
1106 	return rc;
1107 }
1108 
1109 
name_list_to_string(char ** names,int num_names,char ** string)1110 static int name_list_to_string(char **names, int num_names, char **string)
1111 {
1112 	// create a space separated string of the names
1113 	int rc = -1;
1114 	int len = 0;
1115 	int i;
1116 	char *str;
1117 	char *strpos;
1118 	int name_len;
1119 	int rlen;
1120 
1121 	for (i = 0; i < num_names; i++) {
1122 		len += strlen(names[i]);
1123 	}
1124 
1125 	// add spaces + null terminator
1126 	len += (num_names - 1) + 1;
1127 
1128 	str = malloc(len);
1129 	if (str == NULL) {
1130 		log_err("Out of memory");
1131 		rc = -1;
1132 		goto exit;
1133 	}
1134 
1135 	strpos = str;
1136 
1137 	for (i = 0; i < num_names; i++) {
1138 		name_len = strlen(names[i]);
1139 		rlen = snprintf(strpos, len - (strpos - str), "%s", names[i]);
1140 		if (rlen < 0 || rlen >= len) {
1141 			log_err("Failed to generate name list");
1142 			rc = -1;
1143 			goto exit;
1144 		}
1145 
1146 		if (i < num_names - 1) {
1147 			strpos[name_len] = ' ';
1148 		}
1149 		strpos += name_len + 1;
1150 	}
1151 
1152 	*string = str;
1153 
1154 	return 0;
1155 exit:
1156 	free(str);
1157 	return rc;
1158 }
1159 
avrule_list_to_cil(int indent,struct policydb * pdb,struct avrule * avrule_list,struct list * attr_list)1160 static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *avrule_list, struct list *attr_list)
1161 {
1162 	int rc = -1;
1163 	struct avrule *avrule;
1164 	char **snames = NULL;
1165 	char **tnames = NULL;
1166 	int s, t, num_snames, num_tnames;
1167 	struct type_set *ts;
1168 
1169 	for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) {
1170 		if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) &&
1171 		    avrule->source_filename) {
1172 			cil_println(0, ";;* lmx %lu %s\n",avrule->source_line, avrule->source_filename);
1173 		}
1174 
1175 		ts = &avrule->stypes;
1176 		rc = process_typeset(pdb, ts, attr_list, &snames, &num_snames);
1177 		if (rc != 0) {
1178 			goto exit;
1179 		}
1180 
1181 		ts = &avrule->ttypes;
1182 		rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
1183 		if (rc != 0) {
1184 			goto exit;
1185 		}
1186 
1187 		for (s = 0; s < num_snames; s++) {
1188 			for (t = 0; t < num_tnames; t++) {
1189 				if (avrule->specified & AVRULE_XPERMS) {
1190 					rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms, avrule->xperms);
1191 				} else {
1192 					rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms);
1193 				}
1194 				if (rc != 0) {
1195 					goto exit;
1196 				}
1197 			}
1198 
1199 			if (avrule->flags & RULE_SELF) {
1200 				if (avrule->specified & AVRULE_XPERMS) {
1201 					rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms, avrule->xperms);
1202 				} else {
1203 					rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms);
1204 				}
1205 				if (rc != 0) {
1206 					goto exit;
1207 				}
1208 			}
1209 		}
1210 
1211 		names_destroy(&snames, &num_snames);
1212 		names_destroy(&tnames, &num_tnames);
1213 
1214 		if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) &&
1215 		    avrule->source_filename) {
1216 			cil_println(0, ";;* lme\n");
1217 		}
1218 	}
1219 
1220 	return 0;
1221 
1222 exit:
1223 	names_destroy(&snames, &num_snames);
1224 	names_destroy(&tnames, &num_tnames);
1225 
1226 	return rc;
1227 }
1228 
cond_expr_to_cil(int indent,struct policydb * pdb,struct cond_expr * cond_expr,uint32_t flags)1229 static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *cond_expr, uint32_t flags)
1230 {
1231 	int rc = 0;
1232 	struct cond_expr *curr;
1233 	struct stack *stack = NULL;
1234 	int len = 0;
1235 	int rlen;
1236 	char *new_val = NULL;
1237 	char *val1 = NULL;
1238 	char *val2 = NULL;
1239 	int num_params;
1240 	const char *op;
1241 	const char *fmt_str;
1242 	const char *type;
1243 
1244 	rc = stack_init(&stack);
1245 	if (rc != 0) {
1246 		log_err("Out of memory");
1247 		goto exit;
1248 	}
1249 
1250 	for (curr = cond_expr; curr != NULL; curr = curr->next) {
1251 		if (curr->expr_type == COND_BOOL) {
1252 			val1 = pdb->p_bool_val_to_name[curr->bool - 1];
1253 			// length of boolean + 2 parens + null terminator
1254 			len = strlen(val1) + 2 + 1;
1255 			new_val = malloc(len);
1256 			if (new_val == NULL) {
1257 				log_err("Out of memory");
1258 				rc = -1;
1259 				goto exit;
1260 			}
1261 			rlen = snprintf(new_val, len, "(%s)", val1);
1262 			if (rlen < 0 || rlen >= len) {
1263 				log_err("Failed to generate conditional expression");
1264 				rc = -1;
1265 				goto exit;
1266 			}
1267 			num_params = 0;
1268 		} else {
1269 			switch(curr->expr_type) {
1270 			case COND_NOT:	op = "not";	break;
1271 			case COND_OR:	op = "or";	break;
1272 			case COND_AND:	op = "and";	break;
1273 			case COND_XOR:	op = "xor";	break;
1274 			case COND_EQ:	op = "eq";	break;
1275 			case COND_NEQ:	op = "neq";	break;
1276 			default:
1277 				rc = -1;
1278 				goto exit;
1279 			}
1280 
1281 			num_params = curr->expr_type == COND_NOT ? 1 : 2;
1282 
1283 			if (num_params == 1) {
1284 				val1 = stack_pop(stack);
1285 				val2 = strdup("");
1286 				if (val2 == NULL) {
1287 					log_err("Out of memory");
1288 					rc = -1;
1289 					goto exit;
1290 				}
1291 				fmt_str = "(%s %s)";
1292 			} else {
1293 				val2 = stack_pop(stack);
1294 				val1 = stack_pop(stack);
1295 				fmt_str = "(%s %s %s)";
1296 			}
1297 
1298 			if (val1 == NULL || val2 == NULL) {
1299 				log_err("Invalid conditional expression");
1300 				rc = -1;
1301 				goto exit;
1302 			}
1303 
1304 			// length = length of parameters +
1305 			//          length of operator +
1306 			//          1 space preceeding each parameter +
1307 			//          2 parens around the whole expression
1308 			//          + null terminator
1309 			len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1;
1310 			new_val = malloc(len);
1311 			if (new_val == NULL) {
1312 				log_err("Out of memory");
1313 				rc = -1;
1314 				goto exit;
1315 			}
1316 
1317 			// although we always supply val2 and there isn't always a 2nd
1318 			// value, it should only be used when there are actually two values
1319 			// in the format strings
1320 			rlen = snprintf(new_val, len, fmt_str, op, val1, val2);
1321 			if (rlen < 0 || rlen >= len) {
1322 				log_err("Failed to generate conditional expression");
1323 				rc = -1;
1324 				goto exit;
1325 			}
1326 
1327 			free(val1);
1328 			free(val2);
1329 			val1 = NULL;
1330 			val2 = NULL;
1331 		}
1332 
1333 		rc = stack_push(stack, new_val);
1334 		if (rc != 0) {
1335 			log_err("Out of memory");
1336 			goto exit;
1337 		}
1338 		new_val = NULL;
1339 	}
1340 
1341 	if (flags & COND_NODE_FLAGS_TUNABLE) {
1342 		type = "tunableif";
1343 	} else {
1344 		type = "booleanif";
1345 	}
1346 
1347 	val1 = stack_pop(stack);
1348 	if (val1 == NULL || stack_peek(stack) != NULL) {
1349 		log_err("Invalid conditional expression");
1350 		rc = -1;
1351 		goto exit;
1352 	}
1353 
1354 	cil_println(indent, "(%s %s", type, val1);
1355 	free(val1);
1356 	val1 = NULL;
1357 
1358 	rc = 0;
1359 
1360 exit:
1361 	free(new_val);
1362 	free(val1);
1363 	free(val2);
1364 	if (stack != NULL) {
1365 		while ((val1 = stack_pop(stack)) != NULL) {
1366 			free(val1);
1367 		}
1368 		stack_destroy(&stack);
1369 	}
1370 	return rc;
1371 }
1372 
cond_list_to_cil(int indent,struct policydb * pdb,struct cond_node * cond_list,struct list * attr_list)1373 static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node *cond_list, struct list *attr_list)
1374 {
1375 	int rc = 0;
1376 	struct cond_node *cond;
1377 
1378 	for (cond = cond_list; cond != NULL; cond = cond->next) {
1379 
1380 		rc = cond_expr_to_cil(indent, pdb, cond->expr, cond->flags);
1381 		if (rc != 0) {
1382 			goto exit;
1383 		}
1384 
1385 		if (cond->avtrue_list != NULL) {
1386 			cil_println(indent + 1, "(true");
1387 			rc = avrule_list_to_cil(indent + 2, pdb, cond->avtrue_list, attr_list);
1388 			if (rc != 0) {
1389 				goto exit;
1390 			}
1391 			cil_println(indent + 1, ")");
1392 		}
1393 
1394 		if (cond->avfalse_list != NULL) {
1395 			cil_println(indent + 1, "(false");
1396 			rc = avrule_list_to_cil(indent + 2, pdb, cond->avfalse_list, attr_list);
1397 			if (rc != 0) {
1398 				goto exit;
1399 			}
1400 			cil_println(indent + 1, ")");
1401 		}
1402 
1403 		cil_println(indent, ")");
1404 	}
1405 
1406 exit:
1407 	return rc;
1408 }
1409 
role_trans_to_cil(int indent,struct policydb * pdb,struct role_trans_rule * rules,struct list * role_attr_list,struct list * type_attr_list)1410 static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans_rule *rules, struct list *role_attr_list, struct list *type_attr_list)
1411 {
1412 	int rc = 0;
1413 	struct role_trans_rule *rule;
1414 	char **role_names = NULL;
1415 	int num_role_names = 0;
1416 	int role;
1417 	char **type_names = NULL;
1418 	int num_type_names = 0;
1419 	int type;
1420 	uint32_t i;
1421 	struct ebitmap_node *node;
1422 	struct type_set *ts;
1423 	struct role_set *rs;
1424 
1425 	for (rule = rules; rule != NULL; rule = rule->next) {
1426 		rs = &rule->roles;
1427 		rc = process_roleset(pdb, rs, role_attr_list, &role_names, &num_role_names);
1428 		if (rc != 0) {
1429 			goto exit;
1430 		}
1431 
1432 		ts = &rule->types;
1433 		rc = process_typeset(pdb, ts, type_attr_list, &type_names, &num_type_names);
1434 		if (rc != 0) {
1435 			goto exit;
1436 		}
1437 
1438 		for (role = 0; role < num_role_names; role++) {
1439 			for (type = 0; type < num_type_names; type++) {
1440 				ebitmap_for_each_bit(&rule->classes, node, i) {
1441 					if (!ebitmap_get_bit(&rule->classes, i)) {
1442 						continue;
1443 					}
1444 					cil_println(indent, "(roletransition %s %s %s %s)",
1445 						    role_names[role], type_names[type],
1446 						    pdb->p_class_val_to_name[i],
1447 						    pdb->p_role_val_to_name[rule->new_role - 1]);
1448 				}
1449 			}
1450 		}
1451 
1452 		names_destroy(&role_names, &num_role_names);
1453 		names_destroy(&type_names, &num_type_names);
1454 	}
1455 
1456 exit:
1457 	names_destroy(&role_names, &num_role_names);
1458 	names_destroy(&type_names, &num_type_names);
1459 
1460 	return rc;
1461 }
1462 
role_allows_to_cil(int indent,struct policydb * pdb,struct role_allow_rule * rules,struct list * attr_list)1463 static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allow_rule *rules, struct list *attr_list)
1464 {
1465 	int rc = -1;
1466 	struct role_allow_rule *rule;
1467 	char **roles = NULL;
1468 	int num_roles = 0;
1469 	char **new_roles = NULL;
1470 	int num_new_roles = 0;
1471 	int i,j;
1472 	struct role_set *rs;
1473 
1474 	for (rule = rules; rule != NULL; rule = rule->next) {
1475 		rs = &rule->roles;
1476 		rc = process_roleset(pdb, rs, attr_list, &roles, &num_roles);
1477 		if (rc != 0) {
1478 			goto exit;
1479 		}
1480 
1481 		rs = &rule->new_roles;
1482 		rc = process_roleset(pdb, rs, attr_list, &new_roles, &num_new_roles);
1483 		if (rc != 0) {
1484 			goto exit;
1485 		}
1486 
1487 		for (i = 0; i < num_roles; i++) {
1488 			for (j = 0; j < num_new_roles; j++) {
1489 				cil_println(indent, "(roleallow %s %s)", roles[i], new_roles[j]);
1490 			}
1491 		}
1492 
1493 		names_destroy(&roles, &num_roles);
1494 		names_destroy(&new_roles, &num_new_roles);
1495 	}
1496 
1497 	rc = 0;
1498 
1499 exit:
1500 	names_destroy(&roles, &num_roles);
1501 	names_destroy(&new_roles, &num_new_roles);
1502 
1503 	return rc;
1504 }
1505 
range_trans_to_cil(int indent,struct policydb * pdb,struct range_trans_rule * rules,struct list * attr_list)1506 static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_trans_rule *rules, struct list *attr_list)
1507 {
1508 	int rc = -1;
1509 	struct range_trans_rule *rule;
1510 	char **stypes = NULL;
1511 	int num_stypes = 0;
1512 	int stype;
1513 	char **ttypes = NULL;
1514 	int num_ttypes = 0;
1515 	int ttype;
1516 	struct ebitmap_node *node;
1517 	uint32_t i;
1518 	struct type_set *ts;
1519 
1520 	if (!pdb->mls) {
1521 		return 0;
1522 	}
1523 
1524 	for (rule = rules; rule != NULL; rule = rule->next) {
1525 		ts = &rule->stypes;
1526 		rc = process_typeset(pdb, ts, attr_list, &stypes, &num_stypes);
1527 		if (rc != 0) {
1528 			goto exit;
1529 		}
1530 
1531 		ts = &rule->ttypes;
1532 		rc = process_typeset(pdb, ts, attr_list, &ttypes, &num_ttypes);
1533 		if (rc != 0) {
1534 			goto exit;
1535 		}
1536 
1537 		for (stype = 0; stype < num_stypes; stype++) {
1538 			for (ttype = 0; ttype < num_ttypes; ttype++) {
1539 				ebitmap_for_each_bit(&rule->tclasses, node, i) {
1540 					if (!ebitmap_get_bit(&rule->tclasses, i)) {
1541 						continue;
1542 					}
1543 
1544 					cil_indent(indent);
1545 					cil_printf("(rangetransition %s %s %s ", stypes[stype], ttypes[ttype], pdb->p_class_val_to_name[i]);
1546 
1547 					cil_printf("(");
1548 
1549 					rc = semantic_level_to_cil(pdb, 1, &rule->trange.level[0]);
1550 					if (rc != 0) {
1551 						goto exit;
1552 					}
1553 
1554 					cil_printf(" ");
1555 
1556 					rc = semantic_level_to_cil(pdb, 1, &rule->trange.level[1]);
1557 					if (rc != 0) {
1558 						goto exit;
1559 					}
1560 
1561 					cil_printf("))\n");
1562 				}
1563 
1564 			}
1565 		}
1566 
1567 		names_destroy(&stypes, &num_stypes);
1568 		names_destroy(&ttypes, &num_ttypes);
1569 	}
1570 
1571 	rc = 0;
1572 
1573 exit:
1574 	names_destroy(&stypes, &num_stypes);
1575 	names_destroy(&ttypes, &num_ttypes);
1576 
1577 	return rc;
1578 }
1579 
filename_trans_to_cil(int indent,struct policydb * pdb,struct filename_trans_rule * rules,struct list * attr_list)1580 static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filename_trans_rule *rules, struct list *attr_list)
1581 {
1582 	int rc = -1;
1583 	char **stypes = NULL;
1584 	int num_stypes = 0;
1585 	int stype;
1586 	char **ttypes = NULL;
1587 	int num_ttypes = 0;
1588 	int ttype;
1589 	struct type_set *ts;
1590 	struct filename_trans_rule *rule;
1591 
1592 	for (rule = rules; rule != NULL; rule = rule->next) {
1593 		ts = &rule->stypes;
1594 		rc = process_typeset(pdb, ts, attr_list, &stypes, &num_stypes);
1595 		if (rc != 0) {
1596 			goto exit;
1597 		}
1598 
1599 		ts = &rule->ttypes;
1600 		rc = process_typeset(pdb, ts, attr_list, &ttypes, &num_ttypes);
1601 		if (rc != 0) {
1602 			goto exit;
1603 		}
1604 
1605 		for (stype = 0; stype < num_stypes; stype++) {
1606 			for (ttype = 0; ttype < num_ttypes; ttype++) {
1607 				cil_println(indent, "(typetransition %s %s %s \"%s\" %s)",
1608 					    stypes[stype], ttypes[ttype],
1609 					    pdb->p_class_val_to_name[rule->tclass - 1],
1610 					    rule->name,
1611 					    pdb->p_type_val_to_name[rule->otype - 1]);
1612 			}
1613 		}
1614 
1615 		names_destroy(&stypes, &num_stypes);
1616 		names_destroy(&ttypes, &num_ttypes);
1617 	}
1618 
1619 	rc = 0;
1620 exit:
1621 	names_destroy(&stypes, &num_stypes);
1622 	names_destroy(&ttypes, &num_ttypes);
1623 
1624 	return rc;
1625 }
1626 
1627 struct class_perm_datum {
1628 	char *name;
1629 	uint32_t val;
1630 };
1631 
1632 struct class_perm_array {
1633 	struct class_perm_datum *perms;
1634 	uint32_t count;
1635 };
1636 
class_perm_to_array(char * key,void * data,void * args)1637 static int class_perm_to_array(char *key, void *data, void *args)
1638 {
1639 	struct class_perm_array *arr = args;
1640 	struct perm_datum *datum = data;
1641 	arr->perms[arr->count].name = key;
1642 	arr->perms[arr->count].val = datum->s.value;
1643 	arr->count++;
1644 
1645 	return 0;
1646 }
1647 
class_perm_cmp(const void * a,const void * b)1648 static int class_perm_cmp(const void *a, const void *b)
1649 {
1650 	const struct class_perm_datum *aa = a;
1651 	const struct class_perm_datum *bb = b;
1652 
1653 	return aa->val - bb->val;
1654 }
1655 
common_to_cil(char * key,void * data,void * UNUSED (arg))1656 static int common_to_cil(char *key, void *data, void *UNUSED(arg))
1657 {
1658 	int rc = -1;
1659 	struct common_datum *common = data;
1660 	struct class_perm_array arr;
1661 	uint32_t i;
1662 
1663 	arr.count = 0;
1664 	arr.perms = calloc(common->permissions.nprim, sizeof(*arr.perms));
1665 	rc = hashtab_map(common->permissions.table, class_perm_to_array, &arr);
1666 	if (rc != 0) {
1667 		goto exit;
1668 	}
1669 
1670 	qsort(arr.perms, arr.count, sizeof(*arr.perms), class_perm_cmp);
1671 
1672 	cil_printf("(common %s (", key);
1673 	for (i = 0; i < arr.count; i++) {
1674 		cil_printf("%s ", arr.perms[i].name);
1675 	}
1676 	cil_printf("))\n");
1677 
1678 	rc = 0;
1679 
1680 exit:
1681 	free(arr.perms);
1682 	return rc;
1683 }
1684 
1685 
constraint_expr_to_string(struct policydb * pdb,struct constraint_expr * exprs,char ** expr_string)1686 static int constraint_expr_to_string(struct policydb *pdb, struct constraint_expr *exprs, char **expr_string)
1687 {
1688 	int rc = -1;
1689 	struct constraint_expr *expr;
1690 	struct stack *stack = NULL;
1691 	int len = 0;
1692 	int rlen;
1693 	char *new_val = NULL;
1694 	char *val1 = NULL;
1695 	char *val2 = NULL;
1696 	uint32_t num_params;
1697 	const char *op;
1698 	const char *fmt_str;
1699 	const char *attr1;
1700 	const char *attr2;
1701 	char *names = NULL;
1702 	char **name_list = NULL;
1703 	int num_names = 0;
1704 	struct type_set *ts;
1705 
1706 	rc = stack_init(&stack);
1707 	if (rc != 0) {
1708 		goto exit;
1709 	}
1710 
1711 	for (expr = exprs; expr != NULL; expr = expr->next) {
1712 		if (expr->expr_type == CEXPR_ATTR || expr->expr_type == CEXPR_NAMES) {
1713 			switch (expr->op) {
1714 			case CEXPR_EQ:      op = "eq";     break;
1715 			case CEXPR_NEQ:     op = "neq";    break;
1716 			case CEXPR_DOM:     op = "dom";    break;
1717 			case CEXPR_DOMBY:   op = "domby";  break;
1718 			case CEXPR_INCOMP:  op = "incomp"; break;
1719 			default:
1720 				log_err("Unknown constraint operator type: %i", expr->op);
1721 				rc = -1;
1722 				goto exit;
1723 			}
1724 
1725 			switch (expr->attr) {
1726 			case CEXPR_USER:                 attr1 = "u1"; attr2 = "u2"; break;
1727 			case CEXPR_USER | CEXPR_TARGET:  attr1 = "u2"; attr2 = "";   break;
1728 			case CEXPR_USER | CEXPR_XTARGET: attr1 = "u3"; attr2 = "";   break;
1729 			case CEXPR_ROLE:                 attr1 = "r1"; attr2 = "r2"; break;
1730 			case CEXPR_ROLE | CEXPR_TARGET:  attr1 = "r2"; attr2 = "";   break;
1731 			case CEXPR_ROLE | CEXPR_XTARGET: attr1 = "r3"; attr2 = "";   break;
1732 			case CEXPR_TYPE:                 attr1 = "t1"; attr2 = "";   break;
1733 			case CEXPR_TYPE | CEXPR_TARGET:  attr1 = "t2"; attr2 = "";   break;
1734 			case CEXPR_TYPE | CEXPR_XTARGET: attr1 = "t3"; attr2 = "";   break;
1735 			case CEXPR_L1L2:                 attr1 = "l1"; attr2 = "l2"; break;
1736 			case CEXPR_L1H2:                 attr1 = "l1"; attr2 = "h2"; break;
1737 			case CEXPR_H1L2:                 attr1 = "h1"; attr2 = "l2"; break;
1738 			case CEXPR_H1H2:                 attr1 = "h1"; attr2 = "h2"; break;
1739 			case CEXPR_L1H1:                 attr1 = "l1"; attr2 = "h1"; break;
1740 			case CEXPR_L2H2:                 attr1 = "l2"; attr2 = "h2"; break;
1741 			default:
1742 				log_err("Unknown expression attribute type: %i", expr->attr);
1743 				rc = -1;
1744 				goto exit;
1745 			}
1746 
1747 			if (expr->expr_type == CEXPR_ATTR) {
1748 				// length of values/attrs + 2 separating spaces + 2 parens + null terminator
1749 				len = strlen(op) + strlen(attr1) + strlen(attr2) + 2 + 2 + 1;
1750 				new_val = malloc(len);
1751 				if (new_val == NULL) {
1752 					log_err("Out of memory");
1753 					rc = -1;
1754 					goto exit;
1755 				}
1756 				rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, attr2);
1757 				if (rlen < 0 || rlen >= len) {
1758 					log_err("Failed to generate constraint expression");
1759 					rc = -1;
1760 					goto exit;
1761 				}
1762 			} else {
1763 				if (expr->attr & CEXPR_TYPE) {
1764 					ts = expr->type_names;
1765 					rc = ebitmap_to_names(&ts->types, pdb->p_type_val_to_name, &name_list, &num_names);
1766 					if (rc != 0) {
1767 						goto exit;
1768 					}
1769 				} else if (expr->attr & CEXPR_USER) {
1770 					rc = ebitmap_to_names(&expr->names, pdb->p_user_val_to_name, &name_list, &num_names);
1771 					if (rc != 0) {
1772 						goto exit;
1773 					}
1774 				} else if (expr->attr & CEXPR_ROLE) {
1775 					rc = ebitmap_to_names(&expr->names, pdb->p_role_val_to_name, &name_list, &num_names);
1776 					if (rc != 0) {
1777 						goto exit;
1778 					}
1779 				}
1780 				rc = name_list_to_string(name_list, num_names, &names);
1781 				if (rc != 0) {
1782 					goto exit;
1783 				}
1784 
1785 				// length of values/oper + 2 spaces + 2 parens + null terminator
1786 				len = strlen(op) + strlen(attr1) +  strlen(names) + 2 + 2 + 1;
1787 				new_val = malloc(len);
1788 				if (new_val == NULL) {
1789 					log_err("Out of memory");
1790 					rc = -1;
1791 					goto exit;
1792 				}
1793 				rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names);
1794 				if (rlen < 0 || rlen >= len) {
1795 					log_err("Failed to generate constraint expression");
1796 					rc = -1;
1797 					goto exit;
1798 				}
1799 
1800 				names_destroy(&name_list, &num_names);
1801 				free(names);
1802 				names = NULL;
1803 			}
1804 
1805 			num_params = 0;
1806 		} else {
1807 			switch (expr->expr_type) {
1808 			case CEXPR_NOT: op = "not"; break;
1809 			case CEXPR_AND: op = "and"; break;
1810 			case CEXPR_OR:  op = "or"; break;
1811 			default:
1812 				log_err("Unknown constraint expression type: %i", expr->expr_type);
1813 				rc = -1;
1814 				goto exit;
1815 			}
1816 
1817 			num_params = expr->expr_type == CEXPR_NOT ? 1 : 2;
1818 
1819 			if (num_params == 1) {
1820 				val1 = stack_pop(stack);
1821 				val2 = strdup("");
1822 				if (val2 == NULL) {
1823 					log_err("Out of memory");
1824 					rc = -1;
1825 					goto exit;
1826 				}
1827 				fmt_str = "(%s %s)";
1828 			} else {
1829 				val2 = stack_pop(stack);
1830 				val1 = stack_pop(stack);
1831 				fmt_str = "(%s %s %s)";
1832 			}
1833 
1834 			if (val1 == NULL || val2 == NULL) {
1835 				log_err("Invalid constraint expression");
1836 				rc = -1;
1837 				goto exit;
1838 			}
1839 
1840 			// length = length of parameters +
1841 			//          length of operator +
1842 			//          1 space preceeding each parameter +
1843 			//          2 parens around the whole expression
1844 			//          + null terminator
1845 			len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1;
1846 			new_val = malloc(len);
1847 			if (new_val == NULL) {
1848 				log_err("Out of memory");
1849 				rc = -1;
1850 				goto exit;
1851 			}
1852 
1853 			// although we always supply val2 and there isn't always a 2nd
1854 			// value, it should only be used when there are actually two values
1855 			// in the format strings
1856 			rlen = snprintf(new_val, len, fmt_str, op, val1, val2);
1857 			if (rlen < 0 || rlen >= len) {
1858 				log_err("Failed to generate constraint expression");
1859 				rc = -1;
1860 				goto exit;
1861 			}
1862 
1863 			free(val1);
1864 			free(val2);
1865 			val1 = NULL;
1866 			val2 = NULL;
1867 		}
1868 
1869 		rc = stack_push(stack, new_val);
1870 		if (rc != 0) {
1871 			log_err("Out of memory");
1872 			goto exit;
1873 		}
1874 
1875 		new_val = NULL;
1876 	}
1877 
1878 	new_val = stack_pop(stack);
1879 	if (new_val == NULL || stack_peek(stack) != NULL) {
1880 		log_err("Invalid constraint expression");
1881 		rc = -1;
1882 		goto exit;
1883 	}
1884 
1885 	*expr_string = new_val;
1886 	new_val = NULL;
1887 
1888 	rc = 0;
1889 
1890 exit:
1891 	names_destroy(&name_list, &num_names);
1892 	free(names);
1893 
1894 	free(new_val);
1895 	free(val1);
1896 	free(val2);
1897 	while ((val1 = stack_pop(stack)) != NULL) {
1898 		free(val1);
1899 	}
1900 	stack_destroy(&stack);
1901 
1902 	return rc;
1903 }
1904 
1905 
constraints_to_cil(int indent,struct policydb * pdb,char * classkey,struct class_datum * class,struct constraint_node * constraints,int is_constraint)1906 static int constraints_to_cil(int indent, struct policydb *pdb, char *classkey, struct class_datum *class, struct constraint_node *constraints, int is_constraint)
1907 {
1908 	int rc = -1;
1909 	struct constraint_node *node;
1910 	char *expr = NULL;
1911 	const char *mls;
1912 	char *perms;
1913 
1914 	mls = pdb->mls ? "mls" : "";
1915 
1916 	for (node = constraints; node != NULL; node = node->next) {
1917 
1918 		rc = constraint_expr_to_string(pdb, node->expr, &expr);
1919 		if (rc != 0) {
1920 			goto exit;
1921 		}
1922 
1923 		if (is_constraint) {
1924 			perms = sepol_av_to_string(pdb, class->s.value, node->permissions);
1925 			cil_println(indent, "(%sconstrain (%s (%s)) %s)", mls, classkey, perms + 1, expr);
1926 		} else {
1927 			cil_println(indent, "(%svalidatetrans %s %s)", mls, classkey, expr);
1928 		}
1929 
1930 		free(expr);
1931 		expr = NULL;
1932 	}
1933 
1934 	rc = 0;
1935 
1936 exit:
1937 	free(expr);
1938 	return rc;
1939 }
1940 
class_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)1941 static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope)
1942 {
1943 	int rc = -1;
1944 	struct class_datum *class = datum;
1945 	const char *dflt;
1946 	struct class_perm_array arr;
1947 	uint32_t i;
1948 
1949 	if (scope == SCOPE_REQ) {
1950 		return 0;
1951 	}
1952 
1953 	arr.count = 0;
1954 	arr.perms = calloc(class->permissions.nprim, sizeof(*arr.perms));
1955 	rc = hashtab_map(class->permissions.table, class_perm_to_array, &arr);
1956 	if (rc != 0) {
1957 		goto exit;
1958 	}
1959 
1960 	qsort(arr.perms, arr.count, sizeof(*arr.perms), class_perm_cmp);
1961 
1962 	cil_indent(indent);
1963 	cil_printf("(class %s (", key);
1964 	for (i = 0; i < arr.count; i++) {
1965 		cil_printf("%s ", arr.perms[i].name);
1966 	}
1967 	cil_printf("))\n");
1968 
1969 	if (class->comkey != NULL) {
1970 		cil_println(indent, "(classcommon %s %s)", key, class->comkey);
1971 	}
1972 
1973 	if (class->default_user != 0) {
1974 		switch (class->default_user) {
1975 		case DEFAULT_SOURCE:	dflt = "source";	break;
1976 		case DEFAULT_TARGET:	dflt = "target";	break;
1977 		default:
1978 			log_err("Unknown default user value: %i", class->default_user);
1979 			rc = -1;
1980 			goto exit;
1981 		}
1982 		cil_println(indent, "(defaultuser %s %s)", key, dflt);
1983 	}
1984 
1985 	if (class->default_role != 0) {
1986 		switch (class->default_role) {
1987 		case DEFAULT_SOURCE:	dflt = "source";	break;
1988 		case DEFAULT_TARGET:	dflt = "target";	break;
1989 		default:
1990 			log_err("Unknown default role value: %i", class->default_role);
1991 			rc = -1;
1992 			goto exit;
1993 		}
1994 		cil_println(indent, "(defaultrole %s %s)", key, dflt);
1995 	}
1996 
1997 	if (class->default_type != 0) {
1998 		switch (class->default_type) {
1999 		case DEFAULT_SOURCE:	dflt = "source";	break;
2000 		case DEFAULT_TARGET:	dflt = "target";	break;
2001 		default:
2002 			log_err("Unknown default type value: %i", class->default_type);
2003 			rc = -1;
2004 			goto exit;
2005 		}
2006 		cil_println(indent, "(defaulttype %s %s)", key, dflt);
2007 	}
2008 
2009 	if (class->default_range != 0) {
2010 		switch (class->default_range) {
2011 		case DEFAULT_SOURCE_LOW:		dflt = "source low";	break;
2012 		case DEFAULT_SOURCE_HIGH:		dflt = "source high";	break;
2013 		case DEFAULT_SOURCE_LOW_HIGH:	dflt = "source low-high";	break;
2014 		case DEFAULT_TARGET_LOW:		dflt = "target low";	break;
2015 		case DEFAULT_TARGET_HIGH:		dflt = "target high";	break;
2016 		case DEFAULT_TARGET_LOW_HIGH:	dflt = "target low-high";	break;
2017 		default:
2018 			log_err("Unknown default range value: %i", class->default_range);
2019 			rc = -1;
2020 			goto exit;
2021 		}
2022 		cil_println(indent, "(defaultrange %s %s)", key, dflt);
2023 
2024 	}
2025 
2026 	if (class->constraints != NULL) {
2027 		rc = constraints_to_cil(indent, pdb, key, class, class->constraints, 1);
2028 		if (rc != 0) {
2029 			goto exit;
2030 		}
2031 	}
2032 
2033 	if (class->validatetrans != NULL) {
2034 		rc = constraints_to_cil(indent, pdb, key, class, class->validatetrans, 0);
2035 		if (rc != 0) {
2036 			goto exit;
2037 		}
2038 	}
2039 
2040 	rc = 0;
2041 
2042 exit:
2043 	free(arr.perms);
2044 	return rc;
2045 }
2046 
class_order_to_cil(int indent,struct policydb * pdb,struct ebitmap order)2047 static int class_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order)
2048 {
2049 	struct ebitmap_node *node;
2050 	uint32_t i;
2051 
2052 	if (ebitmap_cardinality(&order) == 0) {
2053 		return 0;
2054 	}
2055 
2056 	cil_indent(indent);
2057 	cil_printf("(classorder (");
2058 
2059 	ebitmap_for_each_bit(&order, node, i) {
2060 		if (!ebitmap_get_bit(&order, i)) {
2061 			continue;
2062 		}
2063 		cil_printf("%s ", pdb->sym_val_to_name[SYM_CLASSES][i]);
2064 	}
2065 
2066 	cil_printf("))\n");
2067 
2068 	return 0;
2069 }
2070 
role_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * decl_stack,char * key,void * datum,int scope)2071 static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope)
2072 {
2073 	int rc = -1;
2074 	struct ebitmap_node *node;
2075 	uint32_t i;
2076 	int j;
2077 	char **types = NULL;
2078 	int num_types = 0;
2079 	struct role_datum *role = datum;
2080 	struct type_set *ts;
2081 	struct list *attr_list = NULL;
2082 
2083 	rc = list_init(&attr_list);
2084 	if (rc != 0) {
2085 		goto exit;
2086 	}
2087 
2088 	if (scope == SCOPE_REQ) {
2089 		// if a role/roleattr is in the REQ scope, then it could cause an
2090 		// optional block to fail, even if it is never used. However in CIL,
2091 		// symbols must be used in order to cause an optional block to fail. So
2092 		// for symbols in the REQ scope, add them to a roleattribute as a way
2093 		// to 'use' them in the optional without affecting the resulting policy.
2094 		cil_println(indent, "(roleattributeset " GEN_REQUIRE_ATTR " %s)", key);
2095 	}
2096 
2097 	switch (role->flavor) {
2098 	case ROLE_ROLE:
2099 		if (scope == SCOPE_DECL) {
2100 			// Only declare certain roles if we are reading a base module.
2101 			// These roles are defined in the base module and sometimes in
2102 			// other non-base modules. If we generated the roles regardless of
2103 			// the policy type, it would result in duplicate declarations,
2104 			// which isn't allowed in CIL. Patches have been made to refpolicy
2105 			// to remove these duplicate role declarations, but we need to be
2106 			// backwards compatible and support older policies. Since we know
2107 			// these roles are always declared in base, only print them when we
2108 			// see them in the base module. If the declarations appear in a
2109 			// non-base module, ignore their declarations.
2110 			//
2111 			// Note that this is a hack, and if a policy author does not define
2112 			// one of these roles in base, the declaration will not appear in
2113 			// the resulting policy, likely resulting in a compilation error in
2114 			// CIL.
2115 			//
2116 			// To make things more complicated, the auditadm_r and secadm_r
2117 			// roles could actually be in either the base module or a non-base
2118 			// module, or both. So we can't rely on this same behavior. So for
2119 			// these roles, don't declare them here, even if they are in a base
2120 			// or non-base module. Instead we will just declare them in the
2121 			// base module elsewhere.
2122 			int is_base_role = (!strcmp(key, "user_r") ||
2123 			                    !strcmp(key, "staff_r") ||
2124 			                    !strcmp(key, "sysadm_r") ||
2125 			                    !strcmp(key, "system_r") ||
2126 			                    !strcmp(key, "unconfined_r"));
2127 			int is_builtin_role = (!strcmp(key, "auditadm_r") ||
2128 			                       !strcmp(key, "secadm_r"));
2129 			if ((is_base_role && pdb->policy_type == SEPOL_POLICY_BASE) ||
2130 			    (!is_base_role && !is_builtin_role)) {
2131 				cil_println(indent, "(role %s)", key);
2132 			}
2133 		}
2134 
2135 		if (ebitmap_cardinality(&role->dominates) > 1) {
2136 			log_err("Warning: role 'dominance' statement unsupported in CIL. Dropping from output.");
2137 		}
2138 
2139 		ts = &role->types;
2140 		rc = process_typeset(pdb, ts, attr_list, &types, &num_types);
2141 		if (rc != 0) {
2142 			goto exit;
2143 		}
2144 
2145 		for (j = 0; j < num_types; j++) {
2146 			if (is_id_in_scope(pdb, decl_stack, types[j], SYM_TYPES)) {
2147 				cil_println(indent, "(roletype %s %s)", key, types[j]);
2148 			}
2149 		}
2150 
2151 		if (role->bounds > 0) {
2152 			cil_println(indent, "(rolebounds %s %s)", key, pdb->p_role_val_to_name[role->bounds - 1]);
2153 		}
2154 		break;
2155 
2156 	case ROLE_ATTRIB:
2157 		if (scope == SCOPE_DECL) {
2158 			cil_println(indent, "(roleattribute %s)", key);
2159 		}
2160 
2161 		if (ebitmap_cardinality(&role->roles) > 0) {
2162 			cil_indent(indent);
2163 			cil_printf("(roleattributeset %s (", key);
2164 			ebitmap_for_each_bit(&role->roles, node, i) {
2165 				if (!ebitmap_get_bit(&role->roles, i)) {
2166 					continue;
2167 				}
2168 				cil_printf("%s ", pdb->p_role_val_to_name[i]);
2169 			}
2170 			cil_printf("))\n");
2171 		}
2172 
2173 		ts = &role->types;
2174 		rc = process_typeset(pdb, ts, attr_list, &types, &num_types);
2175 		if (rc != 0) {
2176 			goto exit;
2177 		}
2178 
2179 
2180 		for (j = 0; j < num_types; j++) {
2181 			if (is_id_in_scope(pdb, decl_stack, types[j], SYM_TYPES)) {
2182 				cil_println(indent, "(roletype %s %s)", key, types[j]);
2183 			}
2184 		}
2185 
2186 		break;
2187 
2188 	default:
2189 		log_err("Unknown role type: %i", role->flavor);
2190 		rc = -1;
2191 		goto exit;
2192 	}
2193 
2194 	rc = cil_print_attr_list(indent, pdb, attr_list);
2195 	if (rc != 0) {
2196 		goto exit;
2197 	}
2198 
2199 exit:
2200 	attr_list_destroy(&attr_list);
2201 	names_destroy(&types, &num_types);
2202 
2203 	return rc;
2204 }
2205 
type_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * decl_stack,char * key,void * datum,int scope)2206 static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope)
2207 {
2208 	int rc = -1;
2209 	struct type_datum *type = datum;
2210 
2211 	if (scope == SCOPE_REQ) {
2212 		// if a type/typeattr is in the REQ scope, then it could cause an
2213 		// optional block to fail, even if it is never used. However in CIL,
2214 		// symbols must be used in order to cause an optional block to fail. So
2215 		// for symbols in the REQ scope, add them to a typeattribute as a way
2216 		// to 'use' them in the optional without affecting the resulting policy.
2217 		cil_println(indent, "(typeattributeset " GEN_REQUIRE_ATTR " %s)", key);
2218 	}
2219 
2220 	rc = roletype_role_in_ancestor_to_cil(pdb, decl_stack, key, indent);
2221 	if (rc != 0) {
2222 		goto exit;
2223 	}
2224 
2225 	switch(type->flavor) {
2226 	case TYPE_TYPE:
2227 		if (scope == SCOPE_DECL) {
2228 			cil_println(indent, "(type %s)", key);
2229 			// object_r is implicit in checkmodule, but not with CIL,
2230 			// create it as part of base
2231 			cil_println(indent, "(roletype " DEFAULT_OBJECT " %s)", key);
2232 		}
2233 
2234 		if (type->flags & TYPE_FLAGS_PERMISSIVE) {
2235 			cil_println(indent, "(typepermissive %s)", key);
2236 		}
2237 
2238 		if (type->bounds > 0) {
2239 			cil_println(indent, "(typebounds %s %s)", pdb->p_type_val_to_name[type->bounds - 1], key);
2240 		}
2241 		break;
2242 	case TYPE_ATTRIB:
2243 		if (scope == SCOPE_DECL) {
2244 			cil_println(indent, "(typeattribute %s)", key);
2245 		}
2246 
2247 		if (type->flags & TYPE_FLAGS_EXPAND_ATTR) {
2248 			cil_indent(indent);
2249 			cil_printf("(expandtypeattribute (%s) ", key);
2250 			if (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE) {
2251 				cil_printf("true");
2252 			} else if (type->flags & TYPE_FLAGS_EXPAND_ATTR_FALSE) {
2253 				cil_printf("false");
2254 			}
2255 			cil_printf(")\n");
2256 		}
2257 
2258 		if (ebitmap_cardinality(&type->types) > 0) {
2259 			cil_indent(indent);
2260 			cil_printf("(typeattributeset %s (", key);
2261 			ebitmap_to_cil(pdb, &type->types, SYM_TYPES);
2262 			cil_printf("))\n");
2263 		}
2264 		break;
2265 	default:
2266 		log_err("Unknown flavor (%i) of type %s", type->flavor, key);
2267 		rc = -1;
2268 		goto exit;
2269 	}
2270 
2271 	rc = 0;
2272 
2273 exit:
2274 	return rc;
2275 }
2276 
user_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)2277 static int user_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *UNUSED(decl_stack), char *key, void *datum,  int scope)
2278 {
2279 	struct user_datum *user = datum;
2280 	struct ebitmap roles = user->roles.roles;
2281 	struct mls_semantic_level level = user->dfltlevel;
2282 	struct mls_semantic_range range = user->range;
2283 	struct ebitmap_node *node;
2284 	uint32_t i;
2285 	int sens_offset = 1;
2286 
2287 	if (scope == SCOPE_DECL) {
2288 		cil_println(indent, "(user %s)", key);
2289 		// object_r is implicit in checkmodule, but not with CIL, create it
2290 		// as part of base
2291 		cil_println(indent, "(userrole %s " DEFAULT_OBJECT ")", key);
2292 	}
2293 
2294 	ebitmap_for_each_bit(&roles, node, i) {
2295 		if (!ebitmap_get_bit(&roles, i)) {
2296 			continue;
2297 		}
2298 		cil_println(indent, "(userrole %s %s)", key, pdb->p_role_val_to_name[i]);
2299 	}
2300 
2301 	if (block->flags & AVRULE_OPTIONAL) {
2302 		// sensitivites in user statements in optionals do not have the
2303 		// standard -1 offset
2304 		sens_offset = 0;
2305 	}
2306 
2307 	cil_indent(indent);
2308 	cil_printf("(userlevel %s ", key);
2309 	if (pdb->mls) {
2310 		semantic_level_to_cil(pdb, sens_offset, &level);
2311 	} else {
2312 		cil_printf(DEFAULT_LEVEL);
2313 	}
2314 	cil_printf(")\n");
2315 
2316 	cil_indent(indent);
2317 	cil_printf("(userrange %s (", key);
2318 	if (pdb->mls) {
2319 		semantic_level_to_cil(pdb, sens_offset, &range.level[0]);
2320 		cil_printf(" ");
2321 		semantic_level_to_cil(pdb, sens_offset, &range.level[1]);
2322 	} else {
2323 		cil_printf(DEFAULT_LEVEL " " DEFAULT_LEVEL);
2324 	}
2325 	cil_printf("))\n");
2326 
2327 
2328 	return 0;
2329 }
2330 
boolean_to_cil(int indent,struct policydb * UNUSED (pdb),struct avrule_block * UNUSED (block),struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)2331 static int boolean_to_cil(int indent, struct policydb *UNUSED(pdb), struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum,  int scope)
2332 {
2333 	struct cond_bool_datum *boolean = datum;
2334 	const char *type;
2335 
2336 	if (scope == SCOPE_DECL) {
2337 		if (boolean->flags & COND_BOOL_FLAGS_TUNABLE) {
2338 			type = "tunable";
2339 		} else {
2340 			type = "boolean";
2341 		}
2342 
2343 		cil_println(indent, "(%s %s %s)", type, key, boolean->state ? "true" : "false");
2344 	}
2345 
2346 	return 0;
2347 }
2348 
sens_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)2349 static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope)
2350 {
2351 	struct level_datum *level = datum;
2352 
2353 	if (scope == SCOPE_DECL) {
2354 		if (!level->isalias) {
2355 			cil_println(indent, "(sensitivity %s)", key);
2356 		} else {
2357 			cil_println(indent, "(sensitivityalias %s)", key);
2358 			cil_println(indent, "(sensitivityaliasactual %s %s)", key, pdb->p_sens_val_to_name[level->level->sens - 1]);
2359 		}
2360 	}
2361 
2362 	if (ebitmap_cardinality(&level->level->cat) > 0) {
2363 		cil_indent(indent);
2364 		cil_printf("(sensitivitycategory %s (", key);
2365 		ebitmap_to_cil(pdb, &level->level->cat, SYM_CATS);
2366 		cil_printf("))\n");
2367 	}
2368 
2369 	return 0;
2370 }
2371 
sens_order_to_cil(int indent,struct policydb * pdb,struct ebitmap order)2372 static int sens_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order)
2373 {
2374 	struct ebitmap_node *node;
2375 	uint32_t i;
2376 
2377 	if (ebitmap_cardinality(&order) == 0) {
2378 		return 0;
2379 	}
2380 
2381 	cil_indent(indent);
2382 	cil_printf("(sensitivityorder (");
2383 
2384 	ebitmap_for_each_bit(&order, node, i) {
2385 		if (!ebitmap_get_bit(&order, i)) {
2386 			continue;
2387 		}
2388 		cil_printf("%s ", pdb->p_sens_val_to_name[i]);
2389 	}
2390 
2391 	cil_printf("))\n");
2392 
2393 	return 0;
2394 }
2395 
cat_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)2396 static int cat_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum,  int scope)
2397 {
2398 	struct cat_datum *cat = datum;
2399 
2400 	if (scope == SCOPE_REQ) {
2401 		return 0;
2402 	}
2403 
2404 	if (!cat->isalias) {
2405 		cil_println(indent, "(category %s)", key);
2406 	} else {
2407 		cil_println(indent, "(categoryalias %s)", key);
2408 		cil_println(indent, "(categoryaliasactual %s %s)", key, pdb->p_cat_val_to_name[cat->s.value - 1]);
2409 	}
2410 
2411 	return 0;
2412 }
2413 
cat_order_to_cil(int indent,struct policydb * pdb,struct ebitmap order)2414 static int cat_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order)
2415 {
2416 	int rc = -1;
2417 	struct ebitmap_node *node;
2418 	uint32_t i;
2419 
2420 	if (ebitmap_cardinality(&order) == 0) {
2421 		rc = 0;
2422 		goto exit;
2423 	}
2424 
2425 	cil_indent(indent);
2426 	cil_printf("(categoryorder (");
2427 
2428 	ebitmap_for_each_bit(&order, node, i) {
2429 		if (!ebitmap_get_bit(&order, i)) {
2430 			continue;
2431 		}
2432 		cil_printf("%s ", pdb->p_cat_val_to_name[i]);
2433 	}
2434 
2435 	cil_printf("))\n");
2436 
2437 	return 0;
2438 exit:
2439 	return rc;
2440 }
2441 
polcaps_to_cil(struct policydb * pdb)2442 static int polcaps_to_cil(struct policydb *pdb)
2443 {
2444 	int rc = -1;
2445 	struct ebitmap *map;
2446 	struct ebitmap_node *node;
2447 	uint32_t i;
2448 	const char *name;
2449 
2450 	map = &pdb->policycaps;
2451 
2452 	ebitmap_for_each_bit(map, node, i) {
2453 		if (!ebitmap_get_bit(map, i)) {
2454 			continue;
2455 		}
2456 		name = sepol_polcap_getname(i);
2457 		if (name == NULL) {
2458 			log_err("Unknown policy capability id: %i", i);
2459 			rc = -1;
2460 			goto exit;
2461 		}
2462 
2463 		cil_println(0, "(policycap %s)", name);
2464 	}
2465 
2466 	return 0;
2467 exit:
2468 	return rc;
2469 }
2470 
level_to_cil(struct policydb * pdb,struct mls_level * level)2471 static int level_to_cil(struct policydb *pdb, struct mls_level *level)
2472 {
2473 	struct ebitmap *map = &level->cat;
2474 
2475 	cil_printf("(%s", pdb->p_sens_val_to_name[level->sens - 1]);
2476 
2477 	if (ebitmap_cardinality(map) > 0) {
2478 		cil_printf("(");
2479 		ebitmap_to_cil(pdb, map, SYM_CATS);
2480 		cil_printf(")");
2481 	}
2482 
2483 	cil_printf(")");
2484 
2485 	return 0;
2486 }
2487 
context_to_cil(struct policydb * pdb,struct context_struct * con)2488 static int context_to_cil(struct policydb *pdb, struct context_struct *con)
2489 {
2490 	cil_printf("(%s %s %s (",
2491 		pdb->p_user_val_to_name[con->user - 1],
2492 		pdb->p_role_val_to_name[con->role - 1],
2493 		pdb->p_type_val_to_name[con->type - 1]);
2494 
2495 	if (pdb->mls) {
2496 		level_to_cil(pdb, &con->range.level[0]);
2497 		cil_printf(" ");
2498 		level_to_cil(pdb, &con->range.level[1]);
2499 	} else {
2500 		cil_printf(DEFAULT_LEVEL);
2501 		cil_printf(" ");
2502 		cil_printf(DEFAULT_LEVEL);
2503 	}
2504 
2505 	cil_printf("))");
2506 
2507 	return 0;
2508 }
2509 
ocontext_isid_to_cil(struct policydb * pdb,const char ** sid_to_string,struct ocontext * isids)2510 static int ocontext_isid_to_cil(struct policydb *pdb, const char **sid_to_string, struct ocontext *isids)
2511 {
2512 	int rc = -1;
2513 
2514 	struct ocontext *isid;
2515 
2516 	struct sid_item {
2517 		const char *sid_key;
2518 		struct sid_item *next;
2519 	};
2520 
2521 	struct sid_item *head = NULL;
2522 	struct sid_item *item = NULL;
2523 
2524 	for (isid = isids; isid != NULL; isid = isid->next) {
2525 		cil_println(0, "(sid %s)", sid_to_string[isid->sid[0]]);
2526 		cil_printf("(sidcontext %s ", sid_to_string[isid->sid[0]]);
2527 		context_to_cil(pdb, &isid->context[0]);
2528 		cil_printf(")\n");
2529 
2530 		// get the sid names in the correct order (reverse from the isids
2531 		// ocontext) for sidorder statement
2532 		item = malloc(sizeof(*item));
2533 		if (item == NULL) {
2534 			log_err("Out of memory");
2535 			rc = -1;
2536 			goto exit;
2537 		}
2538 		item->sid_key = sid_to_string[isid->sid[0]];
2539 		item->next = head;
2540 		head = item;
2541 	}
2542 
2543 	if (head != NULL) {
2544 		cil_printf("(sidorder (");
2545 		for (item = head; item != NULL; item = item->next) {
2546 			cil_printf("%s ", item->sid_key);
2547 		}
2548 		cil_printf("))\n");
2549 	}
2550 
2551 	rc = 0;
2552 
2553 exit:
2554 	while(head) {
2555 		item = head;
2556 		head = item->next;
2557 		free(item);
2558 	}
2559 	return rc;
2560 }
2561 
ocontext_selinux_isid_to_cil(struct policydb * pdb,struct ocontext * isids)2562 static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *isids)
2563 {
2564 	int rc = -1;
2565 
2566 	// initial sid names aren't actually stored in the pp files, need to a have
2567 	// a mapping, taken from the linux kernel
2568 	static const char *selinux_sid_to_string[] = {
2569 		"null",
2570 		"kernel",
2571 		"security",
2572 		"unlabeled",
2573 		"fs",
2574 		"file",
2575 		"file_labels",
2576 		"init",
2577 		"any_socket",
2578 		"port",
2579 		"netif",
2580 		"netmsg",
2581 		"node",
2582 		"igmp_packet",
2583 		"icmp_socket",
2584 		"tcp_socket",
2585 		"sysctl_modprobe",
2586 		"sysctl",
2587 		"sysctl_fs",
2588 		"sysctl_kernel",
2589 		"sysctl_net",
2590 		"sysctl_net_unix",
2591 		"sysctl_vm",
2592 		"sysctl_dev",
2593 		"kmod",
2594 		"policy",
2595 		"scmp_packet",
2596 		"devnull",
2597 		NULL
2598 	};
2599 
2600 	rc = ocontext_isid_to_cil(pdb, selinux_sid_to_string, isids);
2601 	if (rc != 0) {
2602 		goto exit;
2603 	}
2604 
2605 	return 0;
2606 
2607 exit:
2608 	return rc;
2609 }
2610 
ocontext_selinux_fs_to_cil(struct policydb * UNUSED (pdb),struct ocontext * fss)2611 static int ocontext_selinux_fs_to_cil(struct policydb *UNUSED(pdb), struct ocontext *fss)
2612 {
2613 	if (fss != NULL) {
2614 		log_err("Warning: 'fscon' statement unsupported in CIL. Dropping from output.");
2615 	}
2616 
2617 	return 0;
2618 }
2619 
ocontext_selinux_port_to_cil(struct policydb * pdb,struct ocontext * portcons)2620 static int ocontext_selinux_port_to_cil(struct policydb *pdb, struct ocontext *portcons)
2621 {
2622 	int rc = -1;
2623 	struct ocontext *portcon;
2624 	const char *protocol;
2625 	uint16_t high;
2626 	uint16_t low;
2627 
2628 	for (portcon = portcons; portcon != NULL; portcon = portcon->next) {
2629 
2630 		switch (portcon->u.port.protocol) {
2631 		case IPPROTO_TCP: protocol = "tcp"; break;
2632 		case IPPROTO_UDP: protocol = "udp"; break;
2633 		case IPPROTO_DCCP: protocol = "dccp"; break;
2634 		default:
2635 			log_err("Unknown portcon protocol: %i", portcon->u.port.protocol);
2636 			rc = -1;
2637 			goto exit;
2638 		}
2639 
2640 		low = portcon->u.port.low_port;
2641 		high = portcon->u.port.high_port;
2642 
2643 		if (low == high) {
2644 			cil_printf("(portcon %s %i ", protocol, low);
2645 		} else {
2646 			cil_printf("(portcon %s (%i %i) ", protocol, low, high);
2647 		}
2648 
2649 		context_to_cil(pdb, &portcon->context[0]);
2650 
2651 		cil_printf(")\n");
2652 	}
2653 
2654 	return 0;
2655 exit:
2656 	return rc;
2657 }
2658 
ocontext_selinux_netif_to_cil(struct policydb * pdb,struct ocontext * netifs)2659 static int ocontext_selinux_netif_to_cil(struct policydb *pdb, struct ocontext *netifs)
2660 {
2661 	struct ocontext *netif;
2662 
2663 	for (netif = netifs; netif != NULL; netif = netif->next) {
2664 		cil_printf("(netifcon %s ", netif->u.name);
2665 		context_to_cil(pdb, &netif->context[0]);
2666 
2667 		cil_printf(" ");
2668 		context_to_cil(pdb, &netif->context[1]);
2669 		cil_printf(")\n");
2670 	}
2671 
2672 	return 0;
2673 }
2674 
ocontext_selinux_node_to_cil(struct policydb * pdb,struct ocontext * nodes)2675 static int ocontext_selinux_node_to_cil(struct policydb *pdb, struct ocontext *nodes)
2676 {
2677 	int rc = -1;
2678 	struct ocontext *node;
2679 	char addr[INET_ADDRSTRLEN];
2680 	char mask[INET_ADDRSTRLEN];
2681 
2682 	for (node = nodes; node != NULL; node = node->next) {
2683 		if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
2684 			log_err("Nodecon address is invalid: %s", strerror(errno));
2685 			rc = -1;
2686 			goto exit;
2687 		}
2688 
2689 		if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
2690 			log_err("Nodecon mask is invalid: %s", strerror(errno));
2691 			rc = -1;
2692 			goto exit;
2693 		}
2694 
2695 		cil_printf("(nodecon (%s) (%s) ", addr, mask);
2696 
2697 		context_to_cil(pdb, &node->context[0]);
2698 
2699 		cil_printf(")\n");
2700 	}
2701 
2702 	return 0;
2703 exit:
2704 	return rc;
2705 }
2706 
ocontext_selinux_node6_to_cil(struct policydb * pdb,struct ocontext * nodes)2707 static int ocontext_selinux_node6_to_cil(struct policydb *pdb, struct ocontext *nodes)
2708 {
2709 	int rc = -1;
2710 	struct ocontext *node;
2711 	char addr[INET6_ADDRSTRLEN];
2712 	char mask[INET6_ADDRSTRLEN];
2713 
2714 	for (node = nodes; node != NULL; node = node->next) {
2715 		if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
2716 			log_err("Nodecon address is invalid: %s", strerror(errno));
2717 			rc = -1;
2718 			goto exit;
2719 		}
2720 
2721 		if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
2722 			log_err("Nodecon mask is invalid: %s", strerror(errno));
2723 			rc = -1;
2724 			goto exit;
2725 		}
2726 
2727 		cil_printf("(nodecon (%s) (%s) ", addr, mask);
2728 
2729 		context_to_cil(pdb, &node->context[0]);
2730 
2731 		cil_printf(")\n");
2732 	}
2733 
2734 	return 0;
2735 exit:
2736 	return rc;
2737 }
2738 
2739 
ocontext_selinux_fsuse_to_cil(struct policydb * pdb,struct ocontext * fsuses)2740 static int ocontext_selinux_fsuse_to_cil(struct policydb *pdb, struct ocontext *fsuses)
2741 {
2742 	int rc = -1;
2743 	struct ocontext *fsuse;
2744 	const char *behavior;
2745 
2746 
2747 	for (fsuse = fsuses; fsuse != NULL; fsuse = fsuse->next) {
2748 		switch (fsuse->v.behavior) {
2749 		case SECURITY_FS_USE_XATTR: behavior = "xattr"; break;
2750 		case SECURITY_FS_USE_TRANS: behavior = "trans"; break;
2751 		case SECURITY_FS_USE_TASK:  behavior = "task"; break;
2752 		default:
2753 			log_err("Unknown fsuse behavior: %i", fsuse->v.behavior);
2754 			rc = -1;
2755 			goto exit;
2756 		}
2757 
2758 		cil_printf("(fsuse %s %s ", behavior, fsuse->u.name);
2759 
2760 		context_to_cil(pdb, &fsuse->context[0]);
2761 
2762 		cil_printf(")\n");
2763 
2764 	}
2765 
2766 	return 0;
2767 exit:
2768 	return rc;
2769 }
2770 
2771 
ocontext_xen_isid_to_cil(struct policydb * pdb,struct ocontext * isids)2772 static int ocontext_xen_isid_to_cil(struct policydb *pdb, struct ocontext *isids)
2773 {
2774 	int rc = -1;
2775 
2776 	// initial sid names aren't actually stored in the pp files, need to a have
2777 	// a mapping, taken from the xen kernel
2778 	static const char *xen_sid_to_string[] = {
2779 		"null",
2780 		"xen",
2781 		"dom0",
2782 		"domio",
2783 		"domxen",
2784 		"unlabeled",
2785 		"security",
2786 		"ioport",
2787 		"iomem",
2788 		"irq",
2789 		"device",
2790 		NULL,
2791 	};
2792 
2793 	rc = ocontext_isid_to_cil(pdb, xen_sid_to_string, isids);
2794 	if (rc != 0) {
2795 		goto exit;
2796 	}
2797 
2798 	return 0;
2799 
2800 exit:
2801 	return rc;
2802 }
2803 
ocontext_xen_pirq_to_cil(struct policydb * pdb,struct ocontext * pirqs)2804 static int ocontext_xen_pirq_to_cil(struct policydb *pdb, struct ocontext *pirqs)
2805 {
2806 	struct ocontext *pirq;
2807 
2808 	for (pirq = pirqs; pirq != NULL; pirq = pirq->next) {
2809 		cil_printf("(pirqcon %i ", pirq->u.pirq);
2810 		context_to_cil(pdb, &pirq->context[0]);
2811 		cil_printf(")\n");
2812 	}
2813 
2814 	return 0;
2815 }
2816 
ocontext_xen_ioport_to_cil(struct policydb * pdb,struct ocontext * ioports)2817 static int ocontext_xen_ioport_to_cil(struct policydb *pdb, struct ocontext *ioports)
2818 {
2819 	struct ocontext *ioport;
2820 	uint32_t low;
2821 	uint32_t high;
2822 
2823 	for (ioport = ioports; ioport != NULL; ioport = ioport->next) {
2824 		low = ioport->u.ioport.low_ioport;
2825 		high = ioport->u.ioport.high_ioport;
2826 
2827 		if (low == high) {
2828 			cil_printf("(ioportcon 0x%x ", low);
2829 		} else {
2830 			cil_printf("(ioportcon (0x%x 0x%x) ", low, high);
2831 		}
2832 
2833 		context_to_cil(pdb, &ioport->context[0]);
2834 
2835 		cil_printf(")\n");
2836 	}
2837 
2838 	return 0;
2839 }
2840 
ocontext_xen_iomem_to_cil(struct policydb * pdb,struct ocontext * iomems)2841 static int ocontext_xen_iomem_to_cil(struct policydb *pdb, struct ocontext *iomems)
2842 {
2843 	struct ocontext *iomem;
2844 	uint64_t low;
2845 	uint64_t high;
2846 
2847 	for (iomem = iomems; iomem != NULL; iomem = iomem->next) {
2848 		low = iomem->u.iomem.low_iomem;
2849 		high = iomem->u.iomem.high_iomem;
2850 
2851 		if (low == high) {
2852 			cil_printf("(iomemcon 0x%"PRIx64" ", low);
2853 		} else {
2854 			cil_printf("(iomemcon (0x%"PRIx64" 0x%"PRIx64") ", low, high);
2855 		}
2856 
2857 		context_to_cil(pdb, &iomem->context[0]);
2858 
2859 		cil_printf(")\n");
2860 	}
2861 
2862 	return 0;
2863 }
2864 
ocontext_xen_pcidevice_to_cil(struct policydb * pdb,struct ocontext * pcids)2865 static int ocontext_xen_pcidevice_to_cil(struct policydb *pdb, struct ocontext *pcids)
2866 {
2867 	struct ocontext *pcid;
2868 
2869 	for (pcid = pcids; pcid != NULL; pcid = pcid->next) {
2870 		cil_printf("(pcidevicecon 0x%lx ", (unsigned long)pcid->u.device);
2871 		context_to_cil(pdb, &pcid->context[0]);
2872 		cil_printf(")\n");
2873 	}
2874 
2875 	return 0;
2876 }
2877 
ocontexts_to_cil(struct policydb * pdb)2878 static int ocontexts_to_cil(struct policydb *pdb)
2879 {
2880 	int rc = -1;
2881 	int ocon;
2882 
2883 	static int (**ocon_funcs)(struct policydb *pdb, struct ocontext *ocon);
2884 	static int (*ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = {
2885 		ocontext_selinux_isid_to_cil,
2886 		ocontext_selinux_fs_to_cil,
2887 		ocontext_selinux_port_to_cil,
2888 		ocontext_selinux_netif_to_cil,
2889 		ocontext_selinux_node_to_cil,
2890 		ocontext_selinux_fsuse_to_cil,
2891 		ocontext_selinux_node6_to_cil,
2892 	};
2893 	static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = {
2894 		ocontext_xen_isid_to_cil,
2895 		ocontext_xen_pirq_to_cil,
2896 		ocontext_xen_ioport_to_cil,
2897 		ocontext_xen_iomem_to_cil,
2898 		ocontext_xen_pcidevice_to_cil,
2899 		NULL,
2900 		NULL,
2901 	};
2902 
2903 	switch (pdb->target_platform) {
2904 	case SEPOL_TARGET_SELINUX:
2905 		ocon_funcs = ocon_selinux_funcs;
2906 		break;
2907 	case SEPOL_TARGET_XEN:
2908 		ocon_funcs = ocon_xen_funcs;
2909 		break;
2910 	default:
2911 		log_err("Unknown target platform: %i", pdb->target_platform);
2912 		rc = -1;
2913 		goto exit;
2914 	}
2915 
2916 	for (ocon = 0; ocon < OCON_NUM; ocon++) {
2917 		if (ocon_funcs[ocon] != NULL) {
2918 			rc = ocon_funcs[ocon](pdb, pdb->ocontexts[ocon]);
2919 			if (rc != 0) {
2920 				goto exit;
2921 			}
2922 		}
2923 	}
2924 
2925 	return 0;
2926 exit:
2927 	return rc;
2928 }
2929 
genfscon_to_cil(struct policydb * pdb)2930 static int genfscon_to_cil(struct policydb *pdb)
2931 {
2932 	struct genfs *genfs;
2933 	struct ocontext *ocon;
2934 
2935 	for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
2936 		for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
2937 			cil_printf("(genfscon %s %s ", genfs->fstype, ocon->u.name);
2938 			context_to_cil(pdb, &ocon->context[0]);
2939 			cil_printf(")\n");
2940 		}
2941 	}
2942 
2943 	return 0;
2944 }
2945 
level_string_to_cil(char * levelstr)2946 static int level_string_to_cil(char *levelstr)
2947 {
2948 	int rc = -1;
2949 	char *sens = NULL;
2950 	char *cats = NULL;
2951 	int matched;
2952 	char *saveptr = NULL;
2953 	char *token = NULL;
2954 	char *ranged = NULL;
2955 
2956 	matched = tokenize(levelstr, ':', 2, &sens, &cats);
2957 	if (matched < 1 || matched > 2) {
2958 		log_err("Invalid level: %s", levelstr);
2959 		rc = -1;
2960 		goto exit;
2961 	}
2962 
2963 	cil_printf("(%s", sens);
2964 
2965 	if (matched == 2) {
2966 		cil_printf("(");
2967 		token = strtok_r(cats, ",", &saveptr);
2968 		while (token != NULL) {
2969 			ranged = strchr(token, '.');
2970 			if (ranged == NULL) {
2971 				cil_printf("%s ", token);
2972 			} else {
2973 				*ranged = '\0';
2974 				cil_printf("(range %s %s) ", token, ranged + 1);
2975 			}
2976 			token = strtok_r(NULL, ",", &saveptr);
2977 		}
2978 		cil_printf(")");
2979 	}
2980 
2981 	cil_printf(")");
2982 
2983 	rc = 0;
2984 exit:
2985 	free(sens);
2986 	free(cats);
2987 	return rc;
2988 }
2989 
level_range_string_to_cil(char * levelrangestr)2990 static int level_range_string_to_cil(char *levelrangestr)
2991 {
2992 	char *ranged = NULL;
2993 	char *low;
2994 	char *high;
2995 
2996 	ranged = strchr(levelrangestr, '-');
2997 	if (ranged == NULL) {
2998 		low = high = levelrangestr;
2999 	} else {
3000 		*ranged = '\0';
3001 		low = levelrangestr;
3002 		high = ranged + 1;
3003 	}
3004 
3005 	level_string_to_cil(low);
3006 	cil_printf(" ");
3007 	level_string_to_cil(high);
3008 
3009 	return 0;
3010 }
3011 
context_string_to_cil(char * contextstr)3012 static int context_string_to_cil(char *contextstr)
3013 {
3014 	int rc = -1;
3015 	int matched;
3016 	char *user = NULL;
3017 	char *role = NULL;
3018 	char *type = NULL;
3019 	char *level = NULL;
3020 
3021 	matched = tokenize(contextstr, ':', 4, &user, &role, &type, &level);
3022 	if (matched < 3 || matched > 4) {
3023 		log_err("Invalid context: %s", contextstr);
3024 		rc = -1;
3025 		goto exit;
3026 	}
3027 
3028 	cil_printf("(%s %s %s (", user, role, type);
3029 
3030 	if (matched == 3) {
3031 		cil_printf(DEFAULT_LEVEL);
3032 		cil_printf(" ");
3033 		cil_printf(DEFAULT_LEVEL);
3034 	} else {
3035 		level_range_string_to_cil(level);
3036 	}
3037 
3038 	cil_printf("))");
3039 
3040 	rc = 0;
3041 
3042 exit:
3043 	free(user);
3044 	free(role);
3045 	free(type);
3046 	free(level);
3047 
3048 	return rc;
3049 }
3050 
seusers_to_cil(struct sepol_module_package * mod_pkg)3051 static int seusers_to_cil(struct sepol_module_package *mod_pkg)
3052 {
3053 	int rc = -1;
3054 	char *seusers = sepol_module_package_get_seusers(mod_pkg);
3055 	size_t seusers_len = sepol_module_package_get_seusers_len(mod_pkg);
3056 	char *cur = seusers;
3057 	char *end = seusers + seusers_len;
3058 	char *line = NULL;
3059 	char *user = NULL;
3060 	char *seuser = NULL;
3061 	char *level = NULL;
3062 	char *tmp = NULL;
3063 	int matched;
3064 
3065 	if (seusers_len == 0) {
3066 		return 0;
3067 	}
3068 
3069 	while ((rc = get_line(&cur, end, &line)) > 0) {
3070 		tmp = line;
3071 		while (isspace(*tmp)) {
3072 			tmp++;
3073 		}
3074 
3075 		if (tmp[0] == '#' || tmp[0] == '\0') {
3076 			free(line);
3077 			line = NULL;
3078 			continue;
3079 		}
3080 
3081 		matched = tokenize(tmp, ':', 3, &user, &seuser, &level);
3082 
3083 		if (matched < 2 || matched > 3) {
3084 			log_err("Invalid seuser line: %s", line);
3085 			rc = -1;
3086 			goto exit;
3087 		}
3088 
3089 		if (!strcmp(user, "__default__")) {
3090 			cil_printf("(selinuxuserdefault %s (", seuser);
3091 		} else {
3092 			cil_printf("(selinuxuser %s %s (", user, seuser);
3093 		}
3094 
3095 		switch (matched) {
3096 		case 2:
3097 			cil_printf("systemlow systemlow");
3098 			break;
3099 		case 3:
3100 			level_range_string_to_cil(level);
3101 			break;
3102 		}
3103 
3104 		cil_printf("))\n");
3105 
3106 		free(user);
3107 		free(seuser);
3108 		free(level);
3109 		free(line);
3110 		user = seuser = level = NULL;
3111 	}
3112 
3113 	if (rc == -1) {
3114 		cil_printf("Failed to read seusers\n");
3115 		goto exit;
3116 	}
3117 
3118 	rc = 0;
3119 exit:
3120 	free(line);
3121 	free(user);
3122 	free(seuser);
3123 	free(level);
3124 
3125 	return rc;
3126 }
3127 
netfilter_contexts_to_cil(struct sepol_module_package * mod_pkg)3128 static int netfilter_contexts_to_cil(struct sepol_module_package *mod_pkg)
3129 {
3130 	size_t netcons_len = sepol_module_package_get_netfilter_contexts_len(mod_pkg);
3131 
3132 	if (netcons_len > 0) {
3133 		log_err("Warning: netfilter_contexts are unsupported in CIL. Dropping from output.");
3134 	}
3135 
3136 	return 0;
3137 }
3138 
user_extra_to_cil(struct sepol_module_package * mod_pkg)3139 static int user_extra_to_cil(struct sepol_module_package *mod_pkg)
3140 {
3141 	int rc = -1;
3142 	char *userx = sepol_module_package_get_user_extra(mod_pkg);
3143 	size_t userx_len = sepol_module_package_get_user_extra_len(mod_pkg);
3144 	char *cur = userx;
3145 	char *end = userx + userx_len;
3146 	char *line;
3147 	int matched;
3148 	char *user = NULL;
3149 	char *prefix = NULL;
3150 	int prefix_len = 0;
3151 	char *user_str = NULL;
3152 	char *prefix_str = NULL;
3153 	char *eol = NULL;
3154 	char *tmp = NULL;
3155 
3156 	if (userx_len == 0) {
3157 		return 0;
3158 	}
3159 
3160 	while ((rc = get_line(&cur, end, &line)) > 0) {
3161 		tmp = line;
3162 		while (isspace(*tmp)) {
3163 			tmp++;
3164 		}
3165 
3166 		if (tmp[0] == '#' || tmp[0] == '\0') {
3167 			free(line);
3168 			line = NULL;
3169 			continue;
3170 		}
3171 
3172 		matched = tokenize(tmp, ' ', 4, &user_str, &user, &prefix_str, &prefix);
3173 		if (matched != 4) {
3174 			rc = -1;
3175 			log_err("Invalid user extra line: %s", line);
3176 			goto exit;
3177 		}
3178 
3179 		prefix_len = strlen(prefix);
3180 		eol = prefix + prefix_len - 1;
3181 		if (*eol != ';' || strcmp(user_str, "user") || strcmp(prefix_str, "prefix")) {
3182 			rc = -1;
3183 			log_err("Invalid user extra line: %s", line);
3184 			goto exit;
3185 		}
3186 		*eol = '\0';
3187 
3188 		cil_println(0, "(userprefix %s %s)", user, prefix);
3189 		free(user);
3190 		free(prefix);
3191 		free(line);
3192 		free(user_str);
3193 		free(prefix_str);
3194 		user = prefix = line = user_str = prefix_str = NULL;
3195 	}
3196 
3197 	if (rc == -1) {
3198 		cil_printf("Failed to read user_extra\n");
3199 		goto exit;
3200 	}
3201 
3202 	rc = 0;
3203 exit:
3204 	free(line);
3205 	free(user);
3206 	free(prefix);
3207 
3208 	return rc;
3209 }
3210 
file_contexts_to_cil(struct sepol_module_package * mod_pkg)3211 static int file_contexts_to_cil(struct sepol_module_package *mod_pkg)
3212 {
3213 	int rc = -1;
3214 	char *fc = sepol_module_package_get_file_contexts(mod_pkg);
3215 	size_t fc_len = sepol_module_package_get_file_contexts_len(mod_pkg);
3216 	char *cur = fc;
3217 	char *end = fc + fc_len;
3218 	char *line = NULL;
3219 	int matched;
3220 	char *regex = NULL;
3221 	char *mode = NULL;
3222 	char *context = NULL;
3223 	const char *cilmode;
3224 	char *tmp = NULL;
3225 
3226 	if (fc_len == 0) {
3227 		return 0;
3228 	}
3229 
3230 	while ((rc = get_line(&cur, end, &line)) > 0) {
3231 		tmp = line;
3232 		while (isspace(*tmp)) {
3233 			tmp++;
3234 		}
3235 
3236 		if (tmp[0] == '#' || tmp[0] == '\0') {
3237 			free(line);
3238 			line = NULL;
3239 			continue;
3240 		}
3241 
3242 		matched = tokenize(tmp, ' ', 3, &regex, &mode, &context);
3243 		if (matched < 2 || matched > 3) {
3244 			rc = -1;
3245 			log_err("Invalid file context line: %s", line);
3246 			goto exit;
3247 		}
3248 
3249 		if (matched == 2) {
3250 			context = mode;
3251 			mode = NULL;
3252 		}
3253 
3254 		if (mode == NULL) {
3255 			cilmode = "any";
3256 		} else if (!strcmp(mode, "--")) {
3257 			cilmode = "file";
3258 		} else if (!strcmp(mode, "-d")) {
3259 			cilmode = "dir";
3260 		} else if (!strcmp(mode, "-c")) {
3261 			cilmode = "char";
3262 		} else if (!strcmp(mode, "-b")) {
3263 			cilmode = "block";
3264 		} else if (!strcmp(mode, "-s")) {
3265 			cilmode = "socket";
3266 		} else if (!strcmp(mode, "-p")) {
3267 			cilmode = "pipe";
3268 		} else if (!strcmp(mode, "-l")) {
3269 			cilmode = "symlink";
3270 		} else {
3271 			rc = -1;
3272 			log_err("Invalid mode in file context line: %s", line);
3273 			goto exit;
3274 		}
3275 
3276 		cil_printf("(filecon \"%s\" %s ", regex, cilmode);
3277 
3278 		if (!strcmp(context, "<<none>>")) {
3279 			cil_printf("()");
3280 		} else {
3281 			context_string_to_cil(context);
3282 		}
3283 
3284 		cil_printf(")\n");
3285 
3286 		free(regex);
3287 		free(mode);
3288 		free(context);
3289 		free(line);
3290 		regex = mode = context = line = NULL;
3291 	}
3292 
3293 	if (rc == -1) {
3294 		cil_printf("Failed to read file_contexts_to_cil\n");
3295 		goto exit;
3296 	}
3297 
3298 	rc = 0;
3299 exit:
3300 	free(line);
3301 	free(regex);
3302 	free(mode);
3303 	free(context);
3304 
3305 	return rc;
3306 }
3307 
3308 
3309 static int (*func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = {
3310 	NULL,	// commons, only stored in the global symtab, handled elsewhere
3311 	class_to_cil,
3312 	role_to_cil,
3313 	type_to_cil,
3314 	user_to_cil,
3315 	boolean_to_cil,
3316 	sens_to_cil,
3317 	cat_to_cil
3318 };
3319 
typealiases_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * decl_stack)3320 static int typealiases_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack)
3321 {
3322 	struct type_datum *alias_datum;
3323 	char *alias_name;
3324 	struct list_node *curr;
3325 	struct avrule_decl *decl = stack_peek(decl_stack);
3326 	struct list *alias_list = typealias_lists[decl->decl_id];
3327 	int rc = -1;
3328 
3329 	if (alias_list == NULL) {
3330 		return 0;
3331 	}
3332 
3333 	for (curr = alias_list->head; curr != NULL; curr = curr->next) {
3334 		alias_name = curr->data;
3335 		alias_datum = hashtab_search(pdb->p_types.table, alias_name);
3336 		if (alias_datum == NULL) {
3337 			rc = -1;
3338 			goto exit;
3339 		}
3340 
3341 		cil_println(indent, "(typealias %s)", alias_name);
3342 		cil_println(indent, "(typealiasactual %s %s)", alias_name, pdb->p_type_val_to_name[alias_datum->s.value - 1]);
3343 	}
3344 
3345 	return 0;
3346 
3347 exit:
3348 	return rc;
3349 }
3350 
declared_scopes_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * decl_stack)3351 static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
3352 {
3353 	int rc = -1;
3354 	struct ebitmap map;
3355 	struct ebitmap_node *node;
3356 	unsigned int i;
3357 	char * key;
3358 	struct scope_datum *scope;
3359 	int sym;
3360 	void *datum;
3361 	struct avrule_decl *decl = stack_peek(decl_stack);
3362 
3363 	for (sym = 0; sym < SYM_NUM; sym++) {
3364 		if (func_to_cil[sym] == NULL) {
3365 			continue;
3366 		}
3367 
3368 		map = decl->declared.scope[sym];
3369 		ebitmap_for_each_bit(&map, node, i) {
3370 			if (!ebitmap_get_bit(&map, i)) {
3371 				continue;
3372 			}
3373 			key = pdb->sym_val_to_name[sym][i];
3374 			datum = hashtab_search(pdb->symtab[sym].table, key);
3375 			if (datum == NULL) {
3376 				rc = -1;
3377 				goto exit;
3378 			}
3379 			scope = hashtab_search(pdb->scope[sym].table, key);
3380 			if (scope == NULL) {
3381 				rc = -1;
3382 				goto exit;
3383 			}
3384 			rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, scope->scope);
3385 			if (rc != 0) {
3386 				goto exit;
3387 			}
3388 		}
3389 
3390 		if (sym == SYM_CATS) {
3391 			rc = cat_order_to_cil(indent, pdb, map);
3392 			if (rc != 0) {
3393 				goto exit;
3394 			}
3395 		}
3396 
3397 		if (sym == SYM_LEVELS) {
3398 			rc = sens_order_to_cil(indent, pdb, map);
3399 			if (rc != 0) {
3400 				goto exit;
3401 			}
3402 		}
3403 
3404 		if (sym == SYM_CLASSES) {
3405 			rc = class_order_to_cil(indent, pdb, map);
3406 			if (rc != 0) {
3407 				goto exit;
3408 			}
3409 		}
3410 	}
3411 
3412 	return 0;
3413 exit:
3414 	return rc;
3415 }
3416 
required_scopes_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * decl_stack)3417 static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
3418 {
3419 	int rc = -1;
3420 	struct ebitmap map;
3421 	struct ebitmap_node *node;
3422 	unsigned int i;
3423 	unsigned int j;
3424 	char * key;
3425 	int sym;
3426 	void *datum;
3427 	struct avrule_decl *decl = stack_peek(decl_stack);
3428 	struct scope_datum *scope_datum;
3429 
3430 	for (sym = 0; sym < SYM_NUM; sym++) {
3431 		if (func_to_cil[sym] == NULL) {
3432 			continue;
3433 		}
3434 
3435 		map = decl->required.scope[sym];
3436 		ebitmap_for_each_bit(&map, node, i) {
3437 			if (!ebitmap_get_bit(&map, i)) {
3438 				continue;
3439 			}
3440 			key = pdb->sym_val_to_name[sym][i];
3441 
3442 			scope_datum = hashtab_search(pdb->scope[sym].table, key);
3443 			if (scope_datum == NULL) {
3444 				rc = -1;
3445 				goto exit;
3446 			}
3447 			for (j = 0; j < scope_datum->decl_ids_len; j++) {
3448 				if (scope_datum->decl_ids[j] == decl->decl_id) {
3449 					break;
3450 				}
3451 			}
3452 			if (j >= scope_datum->decl_ids_len) {
3453 				// Symbols required in the global scope are also in the
3454 				// required scope ebitmap of all avrule decls (i.e. required
3455 				// in all optionals). So we need to look at the scopes of each
3456 				// symbol in this avrule_decl to determine if it actually is
3457 				// required in this decl, or if it's just required in the
3458 				// global scope. If we got here, then this symbol is not
3459 				// actually required in this scope, so skip it.
3460 				continue;
3461 			}
3462 
3463 			datum = hashtab_search(pdb->symtab[sym].table, key);
3464 			if (datum == NULL) {
3465 				rc = -1;
3466 				goto exit;
3467 			}
3468 			rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, SCOPE_REQ);
3469 			if (rc != 0) {
3470 				goto exit;
3471 			}
3472 		}
3473 	}
3474 
3475 	return 0;
3476 exit:
3477 	return rc;
3478 }
3479 
3480 
additive_scopes_to_cil_map(char * key,void * data,void * arg)3481 static int additive_scopes_to_cil_map(char *key, void *data, void *arg)
3482 {
3483 	int rc = -1;
3484 	struct map_args *args = arg;
3485 
3486 	rc = func_to_cil[args->sym_index](args->indent, args->pdb, args->block, args->decl_stack, key, data, SCOPE_REQ);
3487 	if (rc != 0) {
3488 		goto exit;
3489 	}
3490 
3491 	return 0;
3492 
3493 exit:
3494 	return rc;
3495 }
3496 
additive_scopes_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * decl_stack)3497 static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
3498 {
3499 	int rc = -1;
3500 	struct map_args args;
3501 	args.pdb = pdb;
3502 	args.block = block;
3503 	args.decl_stack = decl_stack;
3504 	args.indent = indent;
3505 	struct avrule_decl *decl = stack_peek(decl_stack);
3506 
3507 	for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) {
3508 		if (func_to_cil[args.sym_index] == NULL) {
3509 			continue;
3510 		}
3511 		rc = hashtab_map(decl->symtab[args.sym_index].table, additive_scopes_to_cil_map, &args);
3512 		if (rc != 0) {
3513 			goto exit;
3514 		}
3515 	}
3516 
3517 	return 0;
3518 
3519 exit:
3520 	return rc;
3521 }
3522 
is_scope_superset(struct scope_index * sup,struct scope_index * sub)3523 static int is_scope_superset(struct scope_index *sup, struct scope_index *sub)
3524 {
3525 	// returns 1 if sup is a superset of sub, returns 0 otherwise
3526 
3527 	int rc = 0;
3528 
3529 	uint32_t i;
3530 	struct ebitmap sup_map;
3531 	struct ebitmap sub_map;
3532 	struct ebitmap res;
3533 
3534 	ebitmap_init(&res);
3535 
3536 	for (i = 0; i < SYM_NUM; i++) {
3537 		sup_map = sup->scope[i];
3538 		sub_map = sub->scope[i];
3539 
3540 		ebitmap_and(&res, &sup_map, &sub_map);
3541 		if (!ebitmap_cmp(&res, &sub_map)) {
3542 			goto exit;
3543 		}
3544 		ebitmap_destroy(&res);
3545 	}
3546 
3547 	if (sup->class_perms_len < sub->class_perms_len) {
3548 		goto exit;
3549 	}
3550 
3551 	for (i = 0; i < sub->class_perms_len; i++) {
3552 		sup_map = sup->class_perms_map[i];
3553 		sub_map = sub->class_perms_map[i];
3554 
3555 		ebitmap_and(&res, &sup_map, &sub_map);
3556 		if (!ebitmap_cmp(&res, &sub_map)) {
3557 			goto exit;
3558 		}
3559 		ebitmap_destroy(&res);
3560 	}
3561 
3562 	rc = 1;
3563 
3564 exit:
3565 
3566 	ebitmap_destroy(&res);
3567 	return rc;
3568 }
3569 
block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack,int indent)3570 static int block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int indent)
3571 {
3572 	int rc = -1;
3573 	struct avrule_decl *decl;
3574 	struct list *type_attr_list = NULL;
3575 	struct list *role_attr_list = NULL;
3576 
3577 	decl = block->branch_list;
3578 
3579 	rc = list_init(&type_attr_list);
3580 	if (rc != 0) {
3581 		goto exit;
3582 	}
3583 	rc = list_init(&role_attr_list);
3584 	if (rc != 0) {
3585 		goto exit;
3586 	}
3587 
3588 	rc = typealiases_to_cil(indent, pdb, block, stack);
3589 	if (rc != 0) {
3590 		goto exit;
3591 	}
3592 
3593 	rc = declared_scopes_to_cil(indent, pdb, block, stack);
3594 	if (rc != 0) {
3595 		goto exit;
3596 	}
3597 
3598 	rc = required_scopes_to_cil(indent, pdb, block, stack);
3599 	if (rc != 0) {
3600 		goto exit;
3601 	}
3602 
3603 	rc = additive_scopes_to_cil(indent, pdb, block, stack);
3604 	if (rc != 0) {
3605 		goto exit;
3606 	}
3607 
3608 	rc = avrule_list_to_cil(indent, pdb, decl->avrules, type_attr_list);
3609 	if (rc != 0) {
3610 		goto exit;
3611 	}
3612 
3613 	rc = role_trans_to_cil(indent, pdb, decl->role_tr_rules, role_attr_list, type_attr_list);
3614 	if (rc != 0) {
3615 		goto exit;
3616 	}
3617 
3618 	rc = role_allows_to_cil(indent, pdb, decl->role_allow_rules, role_attr_list);
3619 	if (rc != 0) {
3620 		goto exit;
3621 	}
3622 
3623 	rc = range_trans_to_cil(indent, pdb, decl->range_tr_rules, type_attr_list);
3624 	if (rc != 0) {
3625 		goto exit;
3626 	}
3627 
3628 	rc = filename_trans_to_cil(indent, pdb, decl->filename_trans_rules, type_attr_list);
3629 	if (rc != 0) {
3630 		goto exit;
3631 	}
3632 
3633 	rc = cond_list_to_cil(indent, pdb, decl->cond_list, type_attr_list);
3634 	if (rc != 0) {
3635 		goto exit;
3636 	}
3637 
3638 	rc = cil_print_attr_list(indent, pdb, type_attr_list);
3639 	if (rc != 0) {
3640 		goto exit;
3641 	}
3642 	rc = cil_print_attr_list(indent, pdb, role_attr_list);
3643 	if (rc != 0) {
3644 		goto exit;
3645 	}
3646 
3647 exit:
3648 	attr_list_destroy(&type_attr_list);
3649 	attr_list_destroy(&role_attr_list);
3650 
3651 	return rc;
3652 }
3653 
module_block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack,int * indent)3654 static int module_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int *indent)
3655 {
3656 	int rc = 0;
3657 	struct avrule_decl *decl;
3658 	struct avrule_decl *decl_tmp;
3659 
3660 	decl = block->branch_list;
3661 	if (decl == NULL) {
3662 		goto exit;
3663 	}
3664 
3665 	if (decl->next != NULL) {
3666 		log_err("Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output.");
3667 	}
3668 
3669 	if (block->flags & AVRULE_OPTIONAL) {
3670 		while (stack->pos > 0) {
3671 			decl_tmp = stack_peek(stack);
3672 			if (is_scope_superset(&decl->required, &decl_tmp->required)) {
3673 				break;
3674 			}
3675 
3676 			stack_pop(stack);
3677 			(*indent)--;
3678 			cil_println(*indent, ")");
3679 		}
3680 
3681 		cil_println(*indent, "(optional %s_optional_%i", pdb->name, decl->decl_id);
3682 		(*indent)++;
3683 	}
3684 
3685 	stack_push(stack, decl);
3686 
3687 	rc = block_to_cil(pdb, block, stack, *indent);
3688 	if (rc != 0) {
3689 		goto exit;
3690 	}
3691 
3692 exit:
3693 	return rc;
3694 }
3695 
global_block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack)3696 static int global_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack)
3697 {
3698 	int rc = 0;
3699 	struct avrule_decl *decl;
3700 
3701 	decl = block->branch_list;
3702 	if (decl == NULL) {
3703 		goto exit;
3704 	}
3705 
3706 	if (decl->next != NULL) {
3707 		log_err("Warning: 'else' not allowed in global block. Dropping from output.");
3708 	}
3709 
3710 	stack_push(stack, decl);
3711 
3712 	// type aliases and commons are only stored in the global symtab.
3713 	// However, to get scoping correct, we assume they are in the
3714 	// global block
3715 	rc = hashtab_map(pdb->p_commons.table, common_to_cil, NULL);
3716 	if (rc != 0) {
3717 		goto exit;
3718 	}
3719 
3720 	rc = block_to_cil(pdb, block, stack, 0);
3721 	if (rc != 0) {
3722 		goto exit;
3723 	}
3724 
3725 exit:
3726 	return rc;
3727 }
3728 
blocks_to_cil(struct policydb * pdb)3729 static int blocks_to_cil(struct policydb *pdb)
3730 {
3731 	int rc = -1;
3732 	struct avrule_block *block;
3733 	int indent = 0;
3734 	struct stack *stack = NULL;
3735 
3736 	rc = stack_init(&stack);
3737 	if (rc != 0) {
3738 		goto exit;
3739 	}
3740 
3741 	block = pdb->global;
3742 	rc = global_block_to_cil(pdb, block, stack);
3743 	if (rc != 0) {
3744 		goto exit;
3745 	}
3746 
3747 	for (block = block->next; block != NULL; block = block->next) {
3748 		rc = module_block_to_cil(pdb, block, stack, &indent);
3749 		if (rc != 0) {
3750 			goto exit;
3751 		}
3752 	}
3753 
3754 	while (indent > 0) {
3755 		indent--;
3756 		cil_println(indent, ")");
3757 	}
3758 
3759 exit:
3760 	stack_destroy(&stack);
3761 
3762 	return rc;
3763 }
3764 
linked_block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack)3765 static int linked_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack)
3766 {
3767 	int rc = 0;
3768 	struct avrule_decl *decl;
3769 
3770 	decl = block->branch_list;
3771 	if (decl == NULL) {
3772 		goto exit;
3773 	}
3774 
3775 	if (!decl->enabled) {
3776 		if (decl->next != NULL) {
3777 			decl = decl->next;
3778 		} else {
3779 			goto exit;
3780 		}
3781 	}
3782 
3783 	stack_push(stack, decl);
3784 
3785 	rc = block_to_cil(pdb, block, stack, 0);
3786 	if (rc != 0) {
3787 		goto exit;
3788 	}
3789 
3790 	stack_pop(stack);
3791 
3792 exit:
3793 	return rc;
3794 }
3795 
linked_blocks_to_cil(struct policydb * pdb)3796 static int linked_blocks_to_cil(struct policydb *pdb)
3797 {
3798 	// Convert base module that has been linked to CIL
3799 	// Since it is linked, all optional blocks have been resolved
3800 	int rc = -1;
3801 	struct avrule_block *block;
3802 	struct stack *stack = NULL;
3803 
3804 	rc = stack_init(&stack);
3805 	if (rc != 0) {
3806 		goto exit;
3807 	}
3808 
3809 	block = pdb->global;
3810 	rc = global_block_to_cil(pdb, block, stack);
3811 	if (rc != 0) {
3812 		goto exit;
3813 	}
3814 
3815 	for (block = block->next; block != NULL; block = block->next) {
3816 		rc = linked_block_to_cil(pdb, block, stack);
3817 		if (rc != 0) {
3818 			goto exit;
3819 		}
3820 	}
3821 
3822 exit:
3823 	stack_destroy(&stack);
3824 
3825 	return rc;
3826 }
3827 
handle_unknown_to_cil(struct policydb * pdb)3828 static int handle_unknown_to_cil(struct policydb *pdb)
3829 {
3830 	int rc = -1;
3831 	const char *hu;
3832 
3833 	switch (pdb->handle_unknown) {
3834 	case SEPOL_DENY_UNKNOWN:
3835 		hu = "deny";
3836 		break;
3837 	case SEPOL_REJECT_UNKNOWN:
3838 		hu = "reject";
3839 		break;
3840 	case SEPOL_ALLOW_UNKNOWN:
3841 		hu = "allow";
3842 		break;
3843 	default:
3844 		log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown);
3845 		rc = -1;
3846 		goto exit;
3847 	}
3848 
3849 	cil_println(0, "(handleunknown %s)", hu);
3850 
3851 	return 0;
3852 
3853 exit:
3854 	return rc;
3855 }
3856 
generate_mls(struct policydb * pdb)3857 static int generate_mls(struct policydb *pdb)
3858 {
3859 	const char *mls_str = pdb->mls ? "true" : "false";
3860 	cil_println(0, "(mls %s)", mls_str);
3861 
3862 	return 0;
3863 }
3864 
generate_default_level(void)3865 static int generate_default_level(void)
3866 {
3867 	cil_println(0, "(sensitivity s0)");
3868 	cil_println(0, "(sensitivityorder (s0))");
3869 	cil_println(0, "(level " DEFAULT_LEVEL " (s0))");
3870 
3871 	return 0;
3872 }
3873 
generate_default_object(void)3874 static int generate_default_object(void)
3875 {
3876 	cil_println(0, "(role " DEFAULT_OBJECT ")");
3877 
3878 	return 0;
3879 }
3880 
generate_builtin_roles(void)3881 static int generate_builtin_roles(void)
3882 {
3883 	// due to inconsistentencies between policies and CIL not allowing
3884 	// duplicate roles, some roles are always created, regardless of if they
3885 	// are declared in modules or not
3886 	cil_println(0, "(role auditadm_r)");
3887 	cil_println(0, "(role secadm_r)");
3888 
3889 	return 0;
3890 }
3891 
generate_gen_require_attribute(void)3892 static int generate_gen_require_attribute(void)
3893 {
3894 	cil_println(0, "(typeattribute " GEN_REQUIRE_ATTR ")");
3895 	cil_println(0, "(roleattribute " GEN_REQUIRE_ATTR ")");
3896 
3897 	return 0;
3898 }
3899 
fix_module_name(struct policydb * pdb)3900 static int fix_module_name(struct policydb *pdb)
3901 {
3902 	char *letter;
3903 	int rc = -1;
3904 
3905 	// The base module doesn't have its name set, but we use that for some
3906 	// autogenerated names, like optionals and attributes, to prevent naming
3907 	// collisions. However, they sometimes need to be fixed up.
3908 
3909 	// the base module isn't given a name, so just call it "base"
3910 	if (pdb->policy_type == POLICY_BASE) {
3911 		pdb->name = strdup("base");
3912 		if (pdb->name == NULL) {
3913 			log_err("Out of memory");
3914 			rc = -1;
3915 			goto exit;
3916 		}
3917 	}
3918 
3919 	// CIL is more restrictive in module names than checkmodule. Convert bad
3920 	// characters to underscores
3921 	for (letter = pdb->name; *letter != '\0'; letter++) {
3922 		if (isalnum(*letter)) {
3923 			continue;
3924 		}
3925 
3926 		*letter = '_';
3927 	}
3928 
3929 	return 0;
3930 exit:
3931 	return rc;
3932 }
3933 
sepol_module_policydb_to_cil(FILE * fp,struct policydb * pdb,int linked)3934 int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked)
3935 {
3936 	int rc = -1;
3937 
3938 	out_file = fp;
3939 
3940 	if (pdb == NULL) {
3941 		rc = 0;
3942 		goto exit;
3943 	}
3944 
3945 	if (pdb->policy_type != SEPOL_POLICY_BASE &&
3946 		pdb->policy_type != SEPOL_POLICY_MOD) {
3947 		log_err("Policy pakcage is not a base or module");
3948 		rc = -1;
3949 		goto exit;
3950 	}
3951 
3952 	rc = fix_module_name(pdb);
3953 	if (rc != 0) {
3954 		goto exit;
3955 	}
3956 
3957 	if (pdb->policy_type == SEPOL_POLICY_BASE && !pdb->mls) {
3958 		// If this is a base non-mls policy, we need to define a default level
3959 		// range that can be used for contexts by other non-mls modules, since
3960 		// CIL requires that all contexts have a range, even if they are
3961 		// ignored as in non-mls policies
3962 		rc = generate_default_level();
3963 		if (rc != 0) {
3964 			goto exit;
3965 		}
3966 	}
3967 
3968 	if (pdb->policy_type == SEPOL_POLICY_BASE) {
3969 		// object_r is implicit in checkmodule, but not with CIL, create it
3970 		// as part of base
3971 		rc = generate_default_object();
3972 		if (rc != 0) {
3973 			goto exit;
3974 		}
3975 
3976 		rc = generate_builtin_roles();
3977 		if (rc != 0) {
3978 			goto exit;
3979 		}
3980 
3981 		// default attribute to be used to mimic gen_require in CIL
3982 		rc = generate_gen_require_attribute();
3983 		if (rc != 0) {
3984 			goto exit;
3985 		}
3986 
3987 		// handle_unknown is used from only the base module
3988 		rc = handle_unknown_to_cil(pdb);
3989 		if (rc != 0) {
3990 			goto exit;
3991 		}
3992 
3993 		// mls is used from only the base module
3994 		rc = generate_mls(pdb);
3995 		if (rc != 0) {
3996 			goto exit;
3997 		}
3998 	}
3999 
4000 	rc = role_list_create(pdb->p_roles.table);
4001 	if (rc != 0) {
4002 		goto exit;
4003 	}
4004 
4005 	rc = typealias_list_create(pdb);
4006 	if (rc != 0) {
4007 		goto exit;
4008 	}
4009 
4010 	rc = polcaps_to_cil(pdb);
4011 	if (rc != 0) {
4012 		goto exit;
4013 	}
4014 
4015 	rc = ocontexts_to_cil(pdb);
4016 	if (rc != 0) {
4017 		goto exit;
4018 	}
4019 
4020 	rc = genfscon_to_cil(pdb);
4021 	if (rc != 0) {
4022 		goto exit;
4023 	}
4024 
4025 	// now print everything that is scoped
4026 	if (linked) {
4027 		rc = linked_blocks_to_cil(pdb);
4028 	} else {
4029 		rc = blocks_to_cil(pdb);
4030 	}
4031 	if (rc != 0) {
4032 		goto exit;
4033 	}
4034 
4035 	rc = 0;
4036 
4037 exit:
4038 	role_list_destroy();
4039 	typealias_list_destroy();
4040 
4041 	return rc;
4042 }
4043 
sepol_module_package_to_cil(FILE * fp,struct sepol_module_package * mod_pkg)4044 int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg)
4045 {
4046 	int rc = -1;
4047 	struct sepol_policydb *pdb;
4048 
4049 	out_file = fp;
4050 
4051 	pdb = sepol_module_package_get_policy(mod_pkg);
4052 	if (pdb == NULL) {
4053 		log_err("Failed to get policydb");
4054 		rc = -1;
4055 		goto exit;
4056 	}
4057 
4058 	rc = sepol_module_policydb_to_cil(fp, &pdb->p, 0);
4059 	if (rc != 0) {
4060 		goto exit;
4061 	}
4062 
4063 	rc = seusers_to_cil(mod_pkg);
4064 	if (rc != 0) {
4065 		goto exit;
4066 	}
4067 
4068 	rc = netfilter_contexts_to_cil(mod_pkg);
4069 	if (rc != 0) {
4070 		goto exit;
4071 	}
4072 
4073 	rc = user_extra_to_cil(mod_pkg);
4074 	if (rc != 0) {
4075 		goto exit;
4076 	}
4077 
4078 	rc = file_contexts_to_cil(mod_pkg);
4079 	if (rc != 0) {
4080 		goto exit;
4081 	}
4082 
4083 	rc = 0;
4084 
4085 exit:
4086 	return rc;
4087 }
4088 
fp_to_buffer(FILE * fp,char ** data,size_t * data_len)4089 static int fp_to_buffer(FILE *fp, char **data, size_t *data_len)
4090 {
4091 	int rc = -1;
4092 	char *d = NULL;
4093 	size_t d_len = 0;
4094 	size_t read_len = 0;
4095 	size_t max_len = 1 << 17; // start at 128KB, this is enough to hold about half of all the existing pp files
4096 
4097 	d = malloc(max_len);
4098 	if (d == NULL) {
4099 		log_err("Out of memory");
4100 		rc = -1;
4101 		goto exit;
4102 	}
4103 
4104 	while ((read_len = fread(d + d_len, 1, max_len - d_len, fp)) > 0) {
4105 		d_len += read_len;
4106 		if (d_len == max_len) {
4107 			max_len *= 2;
4108 			d = realloc(d, max_len);
4109 			if (d == NULL) {
4110 				log_err("Out of memory");
4111 				rc = -1;
4112 				goto exit;
4113 			}
4114 		}
4115 	}
4116 
4117 	if (ferror(fp) != 0) {
4118 		log_err("Failed to read pp file");
4119 		rc = -1;
4120 		goto exit;
4121 	}
4122 
4123 	*data = d;
4124 	*data_len = d_len;
4125 
4126 	return 0;
4127 
4128 exit:
4129 	free(d);
4130 	return rc;
4131 }
4132 
sepol_ppfile_to_module_package(FILE * fp,struct sepol_module_package ** mod_pkg)4133 int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg)
4134 {
4135 	int rc = -1;
4136 	FILE *f = NULL;
4137 	struct sepol_policy_file *pf = NULL;
4138 	struct sepol_module_package *pkg = NULL;
4139 	char *data = NULL;
4140 	size_t data_len;
4141 	int fd;
4142 	struct stat sb;
4143 
4144 	rc = sepol_policy_file_create(&pf);
4145 	if (rc != 0) {
4146 		log_err("Failed to create policy file");
4147 		goto exit;
4148 	}
4149 
4150 	fd = fileno(fp);
4151 	if (fstat(fd, &sb) == -1) {
4152 		rc = -1;
4153 		goto exit;
4154 	}
4155 
4156 	if (S_ISFIFO(sb.st_mode) || S_ISSOCK(sb.st_mode)) {
4157 		// libsepol fails when trying to read a policy package from a pipe or a
4158 		// socket due its use of lseek. In this case, read the data into a
4159 		// buffer and provide that to libsepol
4160 		rc = fp_to_buffer(fp, &data, &data_len);
4161 		if (rc != 0) {
4162 			goto exit;
4163 		}
4164 
4165 		sepol_policy_file_set_mem(pf, data, data_len);
4166 	} else {
4167 		sepol_policy_file_set_fp(pf, fp);
4168 	}
4169 
4170 	rc = sepol_module_package_create(&pkg);
4171 	if (rc != 0) {
4172 		log_err("Failed to create module package");
4173 		goto exit;
4174 	}
4175 
4176 	rc = sepol_module_package_read(pkg, pf, 0);
4177 	if (rc != 0) {
4178 		log_err("Failed to read policy package");
4179 		goto exit;
4180 	}
4181 
4182 	*mod_pkg = pkg;
4183 
4184 exit:
4185 	free(data);
4186 
4187 	sepol_policy_file_free(pf);
4188 	if (f != NULL) {
4189 		fclose(f);
4190 	}
4191 
4192 	if (rc != 0) {
4193 		sepol_module_package_free(pkg);
4194 	}
4195 
4196 	return rc;
4197 }
4198