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