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 			//
2039 			// To make things more complicated, the auditadm_r and secadm_r
2040 			// roles could actually be in either the base module or a non-base
2041 			// module, or both. So we can't rely on this same behavior. So for
2042 			// these roles, don't declare them here, even if they are in a base
2043 			// or non-base module. Instead we will just declare them in the
2044 			// base module elsewhere.
2045 			int is_base_role = (!strcmp(key, "user_r") ||
2046 			                    !strcmp(key, "staff_r") ||
2047 			                    !strcmp(key, "sysadm_r") ||
2048 			                    !strcmp(key, "system_r") ||
2049 			                    !strcmp(key, "unconfined_r"));
2050 			int is_builtin_role = (!strcmp(key, "auditadm_r") ||
2051 			                       !strcmp(key, "secadm_r"));
2052 			if ((is_base_role && pdb->policy_type == SEPOL_POLICY_BASE) ||
2053 			    (!is_base_role && !is_builtin_role)) {
2054 				cil_println(indent, "(role %s)", key);
2055 			}
2056 		}
2057 
2058 		if (ebitmap_cardinality(&role->dominates) > 1) {
2059 			log_err("Warning: role 'dominance' statement unsupported in CIL. Dropping from output.");
2060 		}
2061 
2062 		ts = &role->types;
2063 		rc = process_typeset(indent, pdb, ts, NULL, &types, &num_types);
2064 		if (rc != 0) {
2065 			goto exit;
2066 		}
2067 
2068 		for (i = 0; i < num_types; i++) {
2069 			if (is_id_in_scope(pdb, decl_stack, types[i], SYM_TYPES)) {
2070 				cil_println(indent, "(roletype %s %s)", key, types[i]);
2071 			}
2072 		}
2073 
2074 		if (role->bounds > 0) {
2075 			cil_println(indent, "(rolebounds %s %s)", key, pdb->p_role_val_to_name[role->bounds - 1]);
2076 		}
2077 		break;
2078 
2079 	case ROLE_ATTRIB:
2080 		if (scope == SCOPE_DECL) {
2081 			cil_println(indent, "(roleattribute %s)", key);
2082 		}
2083 
2084 		if (ebitmap_cardinality(&role->roles) > 0) {
2085 			cil_indent(indent);
2086 			cil_printf("(roleattributeset %s (", key);
2087 			ebitmap_for_each_bit(&role->roles, node, i) {
2088 				if (!ebitmap_get_bit(&role->roles, i)) {
2089 					continue;
2090 				}
2091 				cil_printf("%s ", pdb->p_role_val_to_name[i]);
2092 			}
2093 			cil_printf("))\n");
2094 		}
2095 
2096 		ts = &role->types;
2097 		rc = process_typeset(indent, pdb, ts, NULL, &types, &num_types);
2098 		if (rc != 0) {
2099 			goto exit;
2100 		}
2101 
2102 
2103 		for (i = 0; i < num_types; i++) {
2104 			if (is_id_in_scope(pdb, decl_stack, types[i], SYM_TYPES)) {
2105 				cil_println(indent, "(roletype %s %s)", key, types[i]);
2106 			}
2107 		}
2108 
2109 		break;
2110 
2111 	default:
2112 		log_err("Unknown role type: %i", role->flavor);
2113 		rc = -1;
2114 		goto exit;
2115 	}
2116 
2117 	rc = 0;
2118 exit:
2119 	names_destroy(&types, &num_types);
2120 
2121 	return rc;
2122 }
2123 
type_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * decl_stack,char * key,void * datum,int scope)2124 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)
2125 {
2126 	int rc = -1;
2127 	struct type_datum *type = datum;
2128 
2129 	if (scope == SCOPE_REQ) {
2130 		// if a type/typeattr is in the REQ scope, then it could cause an
2131 		// optional block to fail, even if it is never used. However in CIL,
2132 		// symbols must be used in order to cause an optional block to fail. So
2133 		// for symbols in the REQ scope, add them to a typeattribute as a way
2134 		// to 'use' them in the optional without affecting the resulting policy.
2135 		cil_println(indent, "(typeattributeset " GEN_REQUIRE_ATTR " %s)", key);
2136 	}
2137 
2138 	rc = roletype_role_in_ancestor_to_cil(pdb, decl_stack, key, indent);
2139 	if (rc != 0) {
2140 		goto exit;
2141 	}
2142 
2143 	switch(type->flavor) {
2144 	case TYPE_TYPE:
2145 		if (scope == SCOPE_DECL) {
2146 			cil_println(indent, "(type %s)", key);
2147 			// object_r is implicit in checkmodule, but not with CIL,
2148 			// create it as part of base
2149 			cil_println(indent, "(roletype " DEFAULT_OBJECT " %s)", key);
2150 		}
2151 
2152 		if (type->flags & TYPE_FLAGS_PERMISSIVE) {
2153 			cil_println(indent, "(typepermissive %s)", key);
2154 		}
2155 
2156 		if (type->bounds > 0) {
2157 			cil_println(indent, "(typebounds %s %s)", pdb->p_type_val_to_name[type->bounds - 1], key);
2158 		}
2159 		break;
2160 	case TYPE_ATTRIB:
2161 		if (scope == SCOPE_DECL) {
2162 			cil_println(indent, "(typeattribute %s)", key);
2163 		}
2164 
2165 		if (ebitmap_cardinality(&type->types) > 0) {
2166 			cil_indent(indent);
2167 			cil_printf("(typeattributeset %s (", key);
2168 			ebitmap_to_cil(pdb, &type->types, SYM_TYPES);
2169 			cil_printf("))\n");
2170 		}
2171 		break;
2172 	default:
2173 		log_err("Unknown flavor (%i) of type %s", type->flavor, key);
2174 		rc = -1;
2175 		goto exit;
2176 	}
2177 
2178 	rc = 0;
2179 
2180 exit:
2181 	return rc;
2182 }
2183 
user_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)2184 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)
2185 {
2186 	struct user_datum *user = datum;
2187 	struct ebitmap roles = user->roles.roles;
2188 	struct mls_semantic_level level = user->dfltlevel;
2189 	struct mls_semantic_range range = user->range;
2190 	struct ebitmap_node *node;
2191 	uint32_t i;
2192 	int sens_offset = 1;
2193 
2194 	if (scope == SCOPE_DECL) {
2195 		cil_println(indent, "(user %s)", key);
2196 		// object_r is implicit in checkmodule, but not with CIL, create it
2197 		// as part of base
2198 		cil_println(indent, "(userrole %s " DEFAULT_OBJECT ")", key);
2199 	}
2200 
2201 	ebitmap_for_each_bit(&roles, node, i) {
2202 		if (!ebitmap_get_bit(&roles, i)) {
2203 			continue;
2204 		}
2205 		cil_println(indent, "(userrole %s %s)", key, pdb->p_role_val_to_name[i]);
2206 	}
2207 
2208 	if (block->flags & AVRULE_OPTIONAL) {
2209 		// sensitivites in user statements in optionals do not have the
2210 		// standard -1 offest
2211 		sens_offset = 0;
2212 	}
2213 
2214 	cil_indent(indent);
2215 	cil_printf("(userlevel %s ", key);
2216 	if (pdb->mls) {
2217 		semantic_level_to_cil(pdb, sens_offset, &level);
2218 	} else {
2219 		cil_printf(DEFAULT_LEVEL);
2220 	}
2221 	cil_printf(")\n");
2222 
2223 	cil_indent(indent);
2224 	cil_printf("(userrange %s (", key);
2225 	if (pdb->mls) {
2226 		semantic_level_to_cil(pdb, sens_offset, &range.level[0]);
2227 		cil_printf(" ");
2228 		semantic_level_to_cil(pdb, sens_offset, &range.level[1]);
2229 	} else {
2230 		cil_printf(DEFAULT_LEVEL " " DEFAULT_LEVEL);
2231 	}
2232 	cil_printf("))\n");
2233 
2234 
2235 	return 0;
2236 }
2237 
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)2238 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)
2239 {
2240 	struct cond_bool_datum *boolean = datum;
2241 	const char *type;
2242 
2243 	if (scope == SCOPE_DECL) {
2244 		if (boolean->flags & COND_BOOL_FLAGS_TUNABLE) {
2245 			type = "tunable";
2246 		} else {
2247 			type = "boolean";
2248 		}
2249 
2250 		cil_println(indent, "(%s %s %s)", type, key, boolean->state ? "true" : "false");
2251 	}
2252 
2253 	return 0;
2254 }
2255 
sens_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)2256 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)
2257 {
2258 	struct level_datum *level = datum;
2259 
2260 	if (scope == SCOPE_DECL) {
2261 		if (!level->isalias) {
2262 			cil_println(indent, "(sensitivity %s)", key);
2263 		} else {
2264 			cil_println(indent, "(sensitivityalias %s)", key);
2265 			cil_println(indent, "(sensitivityaliasactual %s %s)", key, pdb->p_sens_val_to_name[level->level->sens - 1]);
2266 		}
2267 	}
2268 
2269 	if (ebitmap_cardinality(&level->level->cat) > 0) {
2270 		cil_indent(indent);
2271 		cil_printf("(sensitivitycategory %s (", key);
2272 		ebitmap_to_cil(pdb, &level->level->cat, SYM_CATS);
2273 		cil_printf("))\n");
2274 	}
2275 
2276 	return 0;
2277 }
2278 
sens_order_to_cil(int indent,struct policydb * pdb,struct ebitmap order)2279 static int sens_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order)
2280 {
2281 	struct ebitmap_node *node;
2282 	uint32_t i;
2283 
2284 	if (ebitmap_cardinality(&order) == 0) {
2285 		return 0;
2286 	}
2287 
2288 	cil_indent(indent);
2289 	cil_printf("(sensitivityorder (");
2290 
2291 	ebitmap_for_each_bit(&order, node, i) {
2292 		if (!ebitmap_get_bit(&order, i)) {
2293 			continue;
2294 		}
2295 		cil_printf("%s ", pdb->p_sens_val_to_name[i]);
2296 	}
2297 
2298 	cil_printf("))\n");
2299 
2300 	return 0;
2301 }
2302 
cat_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * UNUSED (decl_stack),char * key,void * datum,int scope)2303 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)
2304 {
2305 	struct cat_datum *cat = datum;
2306 
2307 	if (scope == SCOPE_REQ) {
2308 		return 0;
2309 	}
2310 
2311 	if (!cat->isalias) {
2312 		cil_println(indent, "(category %s)", key);
2313 	} else {
2314 		cil_println(indent, "(categoryalias %s)", key);
2315 		cil_println(indent, "(categoryaliasactual %s %s)", key, pdb->p_cat_val_to_name[cat->s.value - 1]);
2316 	}
2317 
2318 	return 0;
2319 }
2320 
cat_order_to_cil(int indent,struct policydb * pdb,struct ebitmap order)2321 static int cat_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order)
2322 {
2323 	int rc = -1;
2324 	struct ebitmap_node *node;
2325 	uint32_t i;
2326 
2327 	if (ebitmap_cardinality(&order) == 0) {
2328 		rc = 0;
2329 		goto exit;
2330 	}
2331 
2332 	cil_indent(indent);
2333 	cil_printf("(categoryorder (");
2334 
2335 	ebitmap_for_each_bit(&order, node, i) {
2336 		if (!ebitmap_get_bit(&order, i)) {
2337 			continue;
2338 		}
2339 		cil_printf("%s ", pdb->p_cat_val_to_name[i]);
2340 	}
2341 
2342 	cil_printf("))\n");
2343 
2344 	return 0;
2345 exit:
2346 	return rc;
2347 }
2348 
polcaps_to_cil(struct policydb * pdb)2349 static int polcaps_to_cil(struct policydb *pdb)
2350 {
2351 	int rc = -1;
2352 	struct ebitmap *map;
2353 	struct ebitmap_node *node;
2354 	uint32_t i;
2355 	const char *name;
2356 
2357 	map = &pdb->policycaps;
2358 
2359 	ebitmap_for_each_bit(map, node, i) {
2360 		if (!ebitmap_get_bit(map, i)) {
2361 			continue;
2362 		}
2363 		name = sepol_polcap_getname(i);
2364 		if (name == NULL) {
2365 			log_err("Unknown policy capability id: %i", i);
2366 			rc = -1;
2367 			goto exit;
2368 		}
2369 
2370 		cil_println(0, "(policycap %s)", name);
2371 	}
2372 
2373 	return 0;
2374 exit:
2375 	return rc;
2376 }
2377 
level_to_cil(struct policydb * pdb,struct mls_level * level)2378 static int level_to_cil(struct policydb *pdb, struct mls_level *level)
2379 {
2380 	struct ebitmap *map = &level->cat;
2381 
2382 	cil_printf("(%s", pdb->p_sens_val_to_name[level->sens - 1]);
2383 
2384 	if (ebitmap_cardinality(map) > 0) {
2385 		cil_printf("(");
2386 		ebitmap_to_cil(pdb, map, SYM_CATS);
2387 		cil_printf(")");
2388 	}
2389 
2390 	cil_printf(")");
2391 
2392 	return 0;
2393 }
2394 
context_to_cil(struct policydb * pdb,struct context_struct * con)2395 static int context_to_cil(struct policydb *pdb, struct context_struct *con)
2396 {
2397 	cil_printf("(%s %s %s (",
2398 		pdb->p_user_val_to_name[con->user - 1],
2399 		pdb->p_role_val_to_name[con->role - 1],
2400 		pdb->p_type_val_to_name[con->type - 1]);
2401 
2402 	if (pdb->mls) {
2403 		level_to_cil(pdb, &con->range.level[0]);
2404 		cil_printf(" ");
2405 		level_to_cil(pdb, &con->range.level[1]);
2406 	} else {
2407 		cil_printf(DEFAULT_LEVEL);
2408 		cil_printf(" ");
2409 		cil_printf(DEFAULT_LEVEL);
2410 	}
2411 
2412 	cil_printf("))");
2413 
2414 	return 0;
2415 }
2416 
ocontext_isid_to_cil(struct policydb * pdb,const char ** sid_to_string,struct ocontext * isids)2417 static int ocontext_isid_to_cil(struct policydb *pdb, const char **sid_to_string, struct ocontext *isids)
2418 {
2419 	int rc = -1;
2420 
2421 	struct ocontext *isid;
2422 
2423 	struct sid_item {
2424 		const char *sid_key;
2425 		struct sid_item *next;
2426 	};
2427 
2428 	struct sid_item *head = NULL;
2429 	struct sid_item *item = NULL;
2430 
2431 	for (isid = isids; isid != NULL; isid = isid->next) {
2432 		cil_println(0, "(sid %s)", sid_to_string[isid->sid[0]]);
2433 		cil_printf("(sidcontext %s ", sid_to_string[isid->sid[0]]);
2434 		context_to_cil(pdb, &isid->context[0]);
2435 		cil_printf(")\n");
2436 
2437 		// get the sid names in the correct order (reverse from the isids
2438 		// ocontext) for sidorder statement
2439 		item = malloc(sizeof(*item));
2440 		if (item == NULL) {
2441 			log_err("Out of memory");
2442 			rc = -1;
2443 			goto exit;
2444 		}
2445 		item->sid_key = sid_to_string[isid->sid[0]];
2446 		item->next = head;
2447 		head = item;
2448 	}
2449 
2450 	if (head != NULL) {
2451 		cil_printf("(sidorder (");
2452 		for (item = head; item != NULL; item = item->next) {
2453 			cil_printf("%s ", item->sid_key);
2454 		}
2455 		cil_printf("))\n");
2456 	}
2457 
2458 	rc = 0;
2459 
2460 exit:
2461 	while(head) {
2462 		item = head;
2463 		head = item->next;
2464 		free(item);
2465 	}
2466 	return rc;
2467 }
2468 
ocontext_selinux_isid_to_cil(struct policydb * pdb,struct ocontext * isids)2469 static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *isids)
2470 {
2471 	int rc = -1;
2472 
2473 	// initial sid names aren't actually stored in the pp files, need to a have
2474 	// a mapping, taken from the linux kernel
2475 	static const char *selinux_sid_to_string[] = {
2476 		"null",
2477 		"kernel",
2478 		"security",
2479 		"unlabeled",
2480 		"fs",
2481 		"file",
2482 		"file_labels",
2483 		"init",
2484 		"any_socket",
2485 		"port",
2486 		"netif",
2487 		"netmsg",
2488 		"node",
2489 		"igmp_packet",
2490 		"icmp_socket",
2491 		"tcp_socket",
2492 		"sysctl_modprobe",
2493 		"sysctl",
2494 		"sysctl_fs",
2495 		"sysctl_kernel",
2496 		"sysctl_net",
2497 		"sysctl_net_unix",
2498 		"sysctl_vm",
2499 		"sysctl_dev",
2500 		"kmod",
2501 		"policy",
2502 		"scmp_packet",
2503 		"devnull",
2504 		NULL
2505 	};
2506 
2507 	rc = ocontext_isid_to_cil(pdb, selinux_sid_to_string, isids);
2508 	if (rc != 0) {
2509 		goto exit;
2510 	}
2511 
2512 	return 0;
2513 
2514 exit:
2515 	return rc;
2516 }
2517 
ocontext_selinux_fs_to_cil(struct policydb * UNUSED (pdb),struct ocontext * fss)2518 static int ocontext_selinux_fs_to_cil(struct policydb *UNUSED(pdb), struct ocontext *fss)
2519 {
2520 	if (fss != NULL) {
2521 		log_err("Warning: 'fscon' statement unsupported in CIL. Dropping from output.");
2522 	}
2523 
2524 	return 0;
2525 }
2526 
ocontext_selinux_port_to_cil(struct policydb * pdb,struct ocontext * portcons)2527 static int ocontext_selinux_port_to_cil(struct policydb *pdb, struct ocontext *portcons)
2528 {
2529 	int rc = -1;
2530 	struct ocontext *portcon;
2531 	const char *protocol;
2532 	uint16_t high;
2533 	uint16_t low;
2534 
2535 	for (portcon = portcons; portcon != NULL; portcon = portcon->next) {
2536 
2537 		switch (portcon->u.port.protocol) {
2538 		case IPPROTO_TCP: protocol = "tcp"; break;
2539 		case IPPROTO_UDP: protocol = "udp"; break;
2540 		default:
2541 			log_err("Unknown portcon protocol: %i", portcon->u.port.protocol);
2542 			rc = -1;
2543 			goto exit;
2544 		}
2545 
2546 		low = portcon->u.port.low_port;
2547 		high = portcon->u.port.high_port;
2548 
2549 		if (low == high) {
2550 			cil_printf("(portcon %s %i ", protocol, low);
2551 		} else {
2552 			cil_printf("(portcon %s (%i %i) ", protocol, low, high);
2553 		}
2554 
2555 		context_to_cil(pdb, &portcon->context[0]);
2556 
2557 		cil_printf(")\n");
2558 	}
2559 
2560 	return 0;
2561 exit:
2562 	return rc;
2563 }
2564 
ocontext_selinux_netif_to_cil(struct policydb * pdb,struct ocontext * netifs)2565 static int ocontext_selinux_netif_to_cil(struct policydb *pdb, struct ocontext *netifs)
2566 {
2567 	struct ocontext *netif;
2568 
2569 	for (netif = netifs; netif != NULL; netif = netif->next) {
2570 		cil_printf("(netifcon %s ", netif->u.name);
2571 		context_to_cil(pdb, &netif->context[0]);
2572 
2573 		cil_printf(" ");
2574 		context_to_cil(pdb, &netif->context[1]);
2575 		cil_printf(")\n");
2576 	}
2577 
2578 	return 0;
2579 }
2580 
ocontext_selinux_node_to_cil(struct policydb * pdb,struct ocontext * nodes)2581 static int ocontext_selinux_node_to_cil(struct policydb *pdb, struct ocontext *nodes)
2582 {
2583 	int rc = -1;
2584 	struct ocontext *node;
2585 	char addr[INET_ADDRSTRLEN];
2586 	char mask[INET_ADDRSTRLEN];
2587 
2588 	for (node = nodes; node != NULL; node = node->next) {
2589 		if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
2590 			log_err("Nodecon address is invalid: %s", strerror(errno));
2591 			rc = -1;
2592 			goto exit;
2593 		}
2594 
2595 		if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
2596 			log_err("Nodecon mask is invalid: %s", strerror(errno));
2597 			rc = -1;
2598 			goto exit;
2599 		}
2600 
2601 		cil_printf("(nodecon %s %s ", addr, mask);
2602 
2603 		context_to_cil(pdb, &node->context[0]);
2604 
2605 		cil_printf(")\n");
2606 	}
2607 
2608 	return 0;
2609 exit:
2610 	return rc;
2611 }
2612 
ocontext_selinux_node6_to_cil(struct policydb * pdb,struct ocontext * nodes)2613 static int ocontext_selinux_node6_to_cil(struct policydb *pdb, struct ocontext *nodes)
2614 {
2615 	int rc = -1;
2616 	struct ocontext *node;
2617 	char addr[INET6_ADDRSTRLEN];
2618 	char mask[INET6_ADDRSTRLEN];
2619 
2620 	for (node = nodes; node != NULL; node = node->next) {
2621 		if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
2622 			log_err("Nodecon address is invalid: %s", strerror(errno));
2623 			rc = -1;
2624 			goto exit;
2625 		}
2626 
2627 		if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
2628 			log_err("Nodecon mask is invalid: %s", strerror(errno));
2629 			rc = -1;
2630 			goto exit;
2631 		}
2632 
2633 		cil_printf("(nodecon %s %s ", addr, mask);
2634 
2635 		context_to_cil(pdb, &node->context[0]);
2636 
2637 		cil_printf(")\n");
2638 	}
2639 
2640 	return 0;
2641 exit:
2642 	return rc;
2643 }
2644 
2645 
ocontext_selinux_fsuse_to_cil(struct policydb * pdb,struct ocontext * fsuses)2646 static int ocontext_selinux_fsuse_to_cil(struct policydb *pdb, struct ocontext *fsuses)
2647 {
2648 	int rc = -1;
2649 	struct ocontext *fsuse;
2650 	const char *behavior;
2651 
2652 
2653 	for (fsuse = fsuses; fsuse != NULL; fsuse = fsuse->next) {
2654 		switch (fsuse->v.behavior) {
2655 		case SECURITY_FS_USE_XATTR: behavior = "xattr"; break;
2656 		case SECURITY_FS_USE_TRANS: behavior = "trans"; break;
2657 		case SECURITY_FS_USE_TASK:  behavior = "task"; break;
2658 		default:
2659 			log_err("Unknown fsuse behavior: %i", fsuse->v.behavior);
2660 			rc = -1;
2661 			goto exit;
2662 		}
2663 
2664 		cil_printf("(fsuse %s %s ", behavior, fsuse->u.name);
2665 
2666 		context_to_cil(pdb, &fsuse->context[0]);
2667 
2668 		cil_printf(")\n");
2669 
2670 	}
2671 
2672 	return 0;
2673 exit:
2674 	return rc;
2675 }
2676 
2677 
ocontext_xen_isid_to_cil(struct policydb * pdb,struct ocontext * isids)2678 static int ocontext_xen_isid_to_cil(struct policydb *pdb, struct ocontext *isids)
2679 {
2680 	int rc = -1;
2681 
2682 	// initial sid names aren't actually stored in the pp files, need to a have
2683 	// a mapping, taken from the xen kernel
2684 	static const char *xen_sid_to_string[] = {
2685 		"null",
2686 		"xen",
2687 		"dom0",
2688 		"domio",
2689 		"domxen",
2690 		"unlabeled",
2691 		"security",
2692 		"ioport",
2693 		"iomem",
2694 		"irq",
2695 		"device",
2696 		NULL,
2697 	};
2698 
2699 	rc = ocontext_isid_to_cil(pdb, xen_sid_to_string, isids);
2700 	if (rc != 0) {
2701 		goto exit;
2702 	}
2703 
2704 	return 0;
2705 
2706 exit:
2707 	return rc;
2708 }
2709 
ocontext_xen_pirq_to_cil(struct policydb * pdb,struct ocontext * pirqs)2710 static int ocontext_xen_pirq_to_cil(struct policydb *pdb, struct ocontext *pirqs)
2711 {
2712 	struct ocontext *pirq;
2713 
2714 	for (pirq = pirqs; pirq != NULL; pirq = pirq->next) {
2715 		cil_printf("(pirqcon %i ", pirq->u.pirq);
2716 		context_to_cil(pdb, &pirq->context[0]);
2717 		cil_printf(")\n");
2718 	}
2719 
2720 	return 0;
2721 }
2722 
ocontext_xen_ioport_to_cil(struct policydb * pdb,struct ocontext * ioports)2723 static int ocontext_xen_ioport_to_cil(struct policydb *pdb, struct ocontext *ioports)
2724 {
2725 	struct ocontext *ioport;
2726 	uint32_t low;
2727 	uint32_t high;
2728 
2729 	for (ioport = ioports; ioport != NULL; ioport = ioport->next) {
2730 		low = ioport->u.ioport.low_ioport;
2731 		high = ioport->u.ioport.high_ioport;
2732 
2733 		if (low == high) {
2734 			cil_printf("(ioportcon %i ", low);
2735 		} else {
2736 			cil_printf("(ioportcon (%i %i) ", low, high);
2737 		}
2738 
2739 		context_to_cil(pdb, &ioport->context[0]);
2740 
2741 		cil_printf(")\n");
2742 	}
2743 
2744 	return 0;
2745 }
2746 
ocontext_xen_iomem_to_cil(struct policydb * pdb,struct ocontext * iomems)2747 static int ocontext_xen_iomem_to_cil(struct policydb *pdb, struct ocontext *iomems)
2748 {
2749 	struct ocontext *iomem;
2750 	uint64_t low;
2751 	uint64_t high;
2752 
2753 	for (iomem = iomems; iomem != NULL; iomem = iomem->next) {
2754 		low = iomem->u.iomem.low_iomem;
2755 		high = iomem->u.iomem.high_iomem;
2756 
2757 		if (low == high) {
2758 			cil_printf("(iomemcon %#lX ", (unsigned long)low);
2759 		} else {
2760 			cil_printf("(iomemcon (%#lX %#lX) ", (unsigned long)low, (unsigned long)high);
2761 		}
2762 
2763 		context_to_cil(pdb, &iomem->context[0]);
2764 
2765 		cil_printf(")\n");
2766 	}
2767 
2768 	return 0;
2769 }
2770 
ocontext_xen_pcidevice_to_cil(struct policydb * pdb,struct ocontext * pcids)2771 static int ocontext_xen_pcidevice_to_cil(struct policydb *pdb, struct ocontext *pcids)
2772 {
2773 	struct ocontext *pcid;
2774 
2775 	for (pcid = pcids; pcid != NULL; pcid = pcid->next) {
2776 		cil_printf("(pcidevicecon %#lx ", (unsigned long)pcid->u.device);
2777 		context_to_cil(pdb, &pcid->context[0]);
2778 		cil_printf(")\n");
2779 	}
2780 
2781 	return 0;
2782 }
2783 
ocontexts_to_cil(struct policydb * pdb)2784 static int ocontexts_to_cil(struct policydb *pdb)
2785 {
2786 	int rc = -1;
2787 	int ocon;
2788 
2789 	static int (**ocon_funcs)(struct policydb *pdb, struct ocontext *ocon);
2790 	static int (*ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = {
2791 		ocontext_selinux_isid_to_cil,
2792 		ocontext_selinux_fs_to_cil,
2793 		ocontext_selinux_port_to_cil,
2794 		ocontext_selinux_netif_to_cil,
2795 		ocontext_selinux_node_to_cil,
2796 		ocontext_selinux_fsuse_to_cil,
2797 		ocontext_selinux_node6_to_cil,
2798 	};
2799 	static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = {
2800 		ocontext_xen_isid_to_cil,
2801 		ocontext_xen_pirq_to_cil,
2802 		ocontext_xen_ioport_to_cil,
2803 		ocontext_xen_iomem_to_cil,
2804 		ocontext_xen_pcidevice_to_cil,
2805 		NULL,
2806 		NULL,
2807 	};
2808 
2809 	switch (pdb->target_platform) {
2810 	case SEPOL_TARGET_SELINUX:
2811 		ocon_funcs = ocon_selinux_funcs;
2812 		break;
2813 	case SEPOL_TARGET_XEN:
2814 		ocon_funcs = ocon_xen_funcs;
2815 		break;
2816 	default:
2817 		log_err("Unknown target platform: %i", pdb->target_platform);
2818 		rc = -1;
2819 		goto exit;
2820 	}
2821 
2822 	for (ocon = 0; ocon < OCON_NUM; ocon++) {
2823 		if (ocon_funcs[ocon] != NULL) {
2824 			rc = ocon_funcs[ocon](pdb, pdb->ocontexts[ocon]);
2825 			if (rc != 0) {
2826 				goto exit;
2827 			}
2828 		}
2829 	}
2830 
2831 	return 0;
2832 exit:
2833 	return rc;
2834 }
2835 
genfscon_to_cil(struct policydb * pdb)2836 static int genfscon_to_cil(struct policydb *pdb)
2837 {
2838 	struct genfs *genfs;
2839 	struct ocontext *ocon;
2840 
2841 	for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
2842 		for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
2843 			cil_printf("(genfscon %s %s ", genfs->fstype, ocon->u.name);
2844 			context_to_cil(pdb, &ocon->context[0]);
2845 			cil_printf(")\n");
2846 		}
2847 	}
2848 
2849 	return 0;
2850 }
2851 
level_string_to_cil(char * levelstr)2852 static int level_string_to_cil(char *levelstr)
2853 {
2854 	int rc = -1;
2855 	char *sens = NULL;
2856 	char *cats = NULL;
2857 	int matched;
2858 	char *saveptr = NULL;
2859 	char *token = NULL;
2860 	char *ranged = NULL;
2861 
2862 	matched = tokenize(levelstr, ':', 2, &sens, &cats);
2863 	if (matched < 1 || matched > 2) {
2864 		log_err("Invalid level: %s", levelstr);
2865 		rc = -1;
2866 		goto exit;
2867 	}
2868 
2869 	cil_printf("(%s", sens);
2870 
2871 	if (matched == 2) {
2872 		cil_printf("(");
2873 		token = strtok_r(cats, ",", &saveptr);
2874 		while (token != NULL) {
2875 			ranged = strchr(token, '.');
2876 			if (ranged == NULL) {
2877 				cil_printf("%s ", token);
2878 			} else {
2879 				*ranged = '\0';
2880 				cil_printf("(range %s %s) ", token, ranged + 1);
2881 			}
2882 			token = strtok_r(NULL, ",", &saveptr);
2883 		}
2884 		cil_printf(")");
2885 	}
2886 
2887 	cil_printf(")");
2888 
2889 	rc = 0;
2890 exit:
2891 	free(sens);
2892 	free(cats);
2893 	return rc;
2894 }
2895 
level_range_string_to_cil(char * levelrangestr)2896 static int level_range_string_to_cil(char *levelrangestr)
2897 {
2898 	char *ranged = NULL;
2899 	char *low;
2900 	char *high;
2901 
2902 	ranged = strchr(levelrangestr, '-');
2903 	if (ranged == NULL) {
2904 		low = high = levelrangestr;
2905 	} else {
2906 		*ranged = '\0';
2907 		low = levelrangestr;
2908 		high = ranged + 1;
2909 	}
2910 
2911 	level_string_to_cil(low);
2912 	cil_printf(" ");
2913 	level_string_to_cil(high);
2914 
2915 	return 0;
2916 }
2917 
context_string_to_cil(char * contextstr)2918 static int context_string_to_cil(char *contextstr)
2919 {
2920 	int rc = -1;
2921 	int matched;
2922 	char *user = NULL;
2923 	char *role = NULL;
2924 	char *type = NULL;
2925 	char *level = NULL;
2926 
2927 	matched = tokenize(contextstr, ':', 4, &user, &role, &type, &level);
2928 	if (matched < 3 || matched > 4) {
2929 		log_err("Invalid context: %s", contextstr);
2930 		rc = -1;
2931 		goto exit;
2932 	}
2933 
2934 	cil_printf("(%s %s %s (", user, role, type);
2935 
2936 	if (matched == 3) {
2937 		cil_printf(DEFAULT_LEVEL);
2938 		cil_printf(" ");
2939 		cil_printf(DEFAULT_LEVEL);
2940 	} else {
2941 		level_range_string_to_cil(level);
2942 	}
2943 
2944 	cil_printf("))");
2945 
2946 	rc = 0;
2947 
2948 exit:
2949 	free(user);
2950 	free(role);
2951 	free(type);
2952 	free(level);
2953 
2954 	return rc;
2955 }
2956 
seusers_to_cil(struct sepol_module_package * mod_pkg)2957 static int seusers_to_cil(struct sepol_module_package *mod_pkg)
2958 {
2959 	int rc = -1;
2960 	char *seusers = sepol_module_package_get_seusers(mod_pkg);
2961 	size_t seusers_len = sepol_module_package_get_seusers_len(mod_pkg);
2962 	char *cur = seusers;
2963 	char *end = seusers + seusers_len;
2964 	char *line = NULL;
2965 	char *user = NULL;
2966 	char *seuser = NULL;
2967 	char *level = NULL;
2968 	char *tmp = NULL;
2969 	int matched;
2970 
2971 	if (seusers_len == 0) {
2972 		return 0;
2973 	}
2974 
2975 	while ((rc = get_line(&cur, end, &line)) > 0) {
2976 		tmp = line;
2977 		while (isspace(*tmp)) {
2978 			tmp++;
2979 		}
2980 
2981 		if (tmp[0] == '#' || tmp[0] == '\0') {
2982 			free(line);
2983 			line = NULL;
2984 			continue;
2985 		}
2986 
2987 		matched = tokenize(tmp, ':', 3, &user, &seuser, &level);
2988 
2989 		if (matched < 2 || matched > 3) {
2990 			log_err("Invalid seuser line: %s", line);
2991 			rc = -1;
2992 			goto exit;
2993 		}
2994 
2995 		if (!strcmp(user, "__default__")) {
2996 			cil_printf("(selinuxuserdefault %s (", seuser);
2997 		} else {
2998 			cil_printf("(selinuxuser %s %s (", user, seuser);
2999 		}
3000 
3001 		switch (matched) {
3002 		case 2:
3003 			cil_printf("systemlow systemlow");
3004 			break;
3005 		case 3:
3006 			level_range_string_to_cil(level);
3007 			break;
3008 		}
3009 
3010 		cil_printf("))\n");
3011 
3012 		free(user);
3013 		free(seuser);
3014 		free(level);
3015 		free(line);
3016 		user = seuser = level = NULL;
3017 	}
3018 
3019 	if (rc == -1) {
3020 		cil_printf("Failed to read seusers\n");
3021 		goto exit;
3022 	}
3023 
3024 	rc = 0;
3025 exit:
3026 	free(line);
3027 	free(user);
3028 	free(seuser);
3029 	free(level);
3030 
3031 	return rc;
3032 }
3033 
netfilter_contexts_to_cil(struct sepol_module_package * mod_pkg)3034 static int netfilter_contexts_to_cil(struct sepol_module_package *mod_pkg)
3035 {
3036 	size_t netcons_len = sepol_module_package_get_netfilter_contexts_len(mod_pkg);
3037 
3038 	if (netcons_len > 0) {
3039 		log_err("Warning: netfilter_contexts are unsupported in CIL. Dropping from output.");
3040 	}
3041 
3042 	return 0;
3043 }
3044 
user_extra_to_cil(struct sepol_module_package * mod_pkg)3045 static int user_extra_to_cil(struct sepol_module_package *mod_pkg)
3046 {
3047 	int rc = -1;
3048 	char *userx = sepol_module_package_get_user_extra(mod_pkg);
3049 	size_t userx_len = sepol_module_package_get_user_extra_len(mod_pkg);
3050 	char *cur = userx;
3051 	char *end = userx + userx_len;
3052 	char *line;
3053 	int matched;
3054 	char *user = NULL;
3055 	char *prefix = NULL;
3056 	int prefix_len = 0;
3057 	char *user_str = NULL;
3058 	char *prefix_str = NULL;
3059 	char *eol = NULL;
3060 	char *tmp = NULL;
3061 
3062 	if (userx_len == 0) {
3063 		return 0;
3064 	}
3065 
3066 	while ((rc = get_line(&cur, end, &line)) > 0) {
3067 		tmp = line;
3068 		while (isspace(*tmp)) {
3069 			tmp++;
3070 		}
3071 
3072 		if (tmp[0] == '#' || tmp[0] == '\0') {
3073 			free(line);
3074 			line = NULL;
3075 			continue;
3076 		}
3077 
3078 		matched = tokenize(tmp, ' ', 4, &user_str, &user, &prefix_str, &prefix);
3079 		if (matched != 4) {
3080 			rc = -1;
3081 			log_err("Invalid user extra line: %s", line);
3082 			goto exit;
3083 		}
3084 
3085 		prefix_len = strlen(prefix);
3086 		eol = prefix + prefix_len - 1;
3087 		if (*eol != ';' || strcmp(user_str, "user") || strcmp(prefix_str, "prefix")) {
3088 			rc = -1;
3089 			log_err("Invalid user extra line: %s", line);
3090 			goto exit;
3091 		}
3092 		*eol = '\0';
3093 
3094 		cil_println(0, "(userprefix %s %s)", user, prefix);
3095 		free(user);
3096 		free(prefix);
3097 		free(line);
3098 		free(user_str);
3099 		free(prefix_str);
3100 		user = prefix = line = user_str = prefix_str = NULL;
3101 	}
3102 
3103 	if (rc == -1) {
3104 		cil_printf("Failed to read user_extra\n");
3105 		goto exit;
3106 	}
3107 
3108 	rc = 0;
3109 exit:
3110 	free(line);
3111 	free(user);
3112 	free(prefix);
3113 
3114 	return rc;
3115 }
3116 
file_contexts_to_cil(struct sepol_module_package * mod_pkg)3117 static int file_contexts_to_cil(struct sepol_module_package *mod_pkg)
3118 {
3119 	int rc = -1;
3120 	char *fc = sepol_module_package_get_file_contexts(mod_pkg);
3121 	size_t fc_len = sepol_module_package_get_file_contexts_len(mod_pkg);
3122 	char *cur = fc;
3123 	char *end = fc + fc_len;
3124 	char *line = NULL;
3125 	int matched;
3126 	char *regex = NULL;
3127 	char *mode = NULL;
3128 	char *context = NULL;
3129 	const char *cilmode;
3130 	char *tmp = NULL;
3131 
3132 	if (fc_len == 0) {
3133 		return 0;
3134 	}
3135 
3136 	while ((rc = get_line(&cur, end, &line)) > 0) {
3137 		tmp = line;
3138 		while (isspace(*tmp)) {
3139 			tmp++;
3140 		}
3141 
3142 		if (tmp[0] == '#' || tmp[0] == '\0') {
3143 			free(line);
3144 			line = NULL;
3145 			continue;
3146 		}
3147 
3148 		matched = tokenize(tmp, ' ', 3, &regex, &mode, &context);
3149 		if (matched < 2 || matched > 3) {
3150 			rc = -1;
3151 			log_err("Invalid file context line: %s", line);
3152 			goto exit;
3153 		}
3154 
3155 		if (matched == 2) {
3156 			context = mode;
3157 			mode = NULL;
3158 		}
3159 
3160 		if (mode == NULL) {
3161 			cilmode = "any";
3162 		} else if (!strcmp(mode, "--")) {
3163 			cilmode = "file";
3164 		} else if (!strcmp(mode, "-d")) {
3165 			cilmode = "dir";
3166 		} else if (!strcmp(mode, "-c")) {
3167 			cilmode = "char";
3168 		} else if (!strcmp(mode, "-b")) {
3169 			cilmode = "block";
3170 		} else if (!strcmp(mode, "-s")) {
3171 			cilmode = "socket";
3172 		} else if (!strcmp(mode, "-p")) {
3173 			cilmode = "pipe";
3174 		} else if (!strcmp(mode, "-l")) {
3175 			cilmode = "symlink";
3176 		} else {
3177 			rc = -1;
3178 			log_err("Invalid mode in file context line: %s", line);
3179 			goto exit;
3180 		}
3181 
3182 		cil_printf("(filecon \"%s\" %s ", regex, cilmode);
3183 
3184 		if (!strcmp(context, "<<none>>")) {
3185 			cil_printf("()");
3186 		} else {
3187 			context_string_to_cil(context);
3188 		}
3189 
3190 		cil_printf(")\n");
3191 
3192 		free(regex);
3193 		free(mode);
3194 		free(context);
3195 		free(line);
3196 		regex = mode = context = line = NULL;
3197 	}
3198 
3199 	if (rc == -1) {
3200 		cil_printf("Failed to read file_contexts_to_cil\n");
3201 		goto exit;
3202 	}
3203 
3204 	rc = 0;
3205 exit:
3206 	free(line);
3207 	free(regex);
3208 	free(mode);
3209 	free(context);
3210 
3211 	return rc;
3212 }
3213 
3214 
3215 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) = {
3216 	NULL,	// commons, only stored in the global symtab, handled elsewhere
3217 	class_to_cil,
3218 	role_to_cil,
3219 	type_to_cil,
3220 	user_to_cil,
3221 	boolean_to_cil,
3222 	sens_to_cil,
3223 	cat_to_cil
3224 };
3225 
typealiases_to_cil(int indent,struct policydb * pdb,struct avrule_block * UNUSED (block),struct stack * decl_stack)3226 static int typealiases_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack)
3227 {
3228 	struct type_datum *alias_datum;
3229 	char *alias_name;
3230 	struct list_node *curr;
3231 	struct avrule_decl *decl = stack_peek(decl_stack);
3232 	struct list *alias_list = typealias_lists[decl->decl_id];
3233 	int rc = -1;
3234 
3235 	if (alias_list == NULL) {
3236 		return 0;
3237 	}
3238 
3239 	for (curr = alias_list->head; curr != NULL; curr = curr->next) {
3240 		alias_name = curr->data;
3241 		alias_datum = hashtab_search(pdb->p_types.table, alias_name);
3242 		if (alias_datum == NULL) {
3243 			rc = -1;
3244 			goto exit;
3245 		}
3246 
3247 		cil_println(indent, "(typealias %s)", alias_name);
3248 		cil_println(indent, "(typealiasactual %s %s)", alias_name, pdb->p_type_val_to_name[alias_datum->s.value - 1]);
3249 	}
3250 
3251 	return 0;
3252 
3253 exit:
3254 	return rc;
3255 }
3256 
declared_scopes_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * decl_stack)3257 static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
3258 {
3259 	int rc = -1;
3260 	struct ebitmap map;
3261 	struct ebitmap_node *node;
3262 	unsigned int i;
3263 	char * key;
3264 	struct scope_datum *scope;
3265 	int sym;
3266 	void *datum;
3267 	struct avrule_decl *decl = stack_peek(decl_stack);
3268 
3269 	for (sym = 0; sym < SYM_NUM; sym++) {
3270 		if (func_to_cil[sym] == NULL) {
3271 			continue;
3272 		}
3273 
3274 		map = decl->declared.scope[sym];
3275 		ebitmap_for_each_bit(&map, node, i) {
3276 			if (!ebitmap_get_bit(&map, i)) {
3277 				continue;
3278 			}
3279 			key = pdb->sym_val_to_name[sym][i];
3280 			datum = hashtab_search(pdb->symtab[sym].table, key);
3281 			if (datum == NULL) {
3282 				rc = -1;
3283 				goto exit;
3284 			}
3285 			scope = hashtab_search(pdb->scope[sym].table, key);
3286 			if (scope == NULL) {
3287 				rc = -1;
3288 				goto exit;
3289 			}
3290 			rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, scope->scope);
3291 			if (rc != 0) {
3292 				goto exit;
3293 			}
3294 		}
3295 
3296 		if (sym == SYM_CATS) {
3297 			rc = cat_order_to_cil(indent, pdb, map);
3298 			if (rc != 0) {
3299 				goto exit;
3300 			}
3301 		}
3302 
3303 		if (sym == SYM_LEVELS) {
3304 			rc = sens_order_to_cil(indent, pdb, map);
3305 			if (rc != 0) {
3306 				goto exit;
3307 			}
3308 		}
3309 
3310 		if (sym == SYM_CLASSES) {
3311 			rc = class_order_to_cil(indent, pdb, map);
3312 			if (rc != 0) {
3313 				goto exit;
3314 			}
3315 		}
3316 	}
3317 
3318 	return 0;
3319 exit:
3320 	return rc;
3321 }
3322 
required_scopes_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * decl_stack)3323 static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
3324 {
3325 	int rc = -1;
3326 	struct ebitmap map;
3327 	struct ebitmap_node *node;
3328 	unsigned int i;
3329 	unsigned int j;
3330 	char * key;
3331 	int sym;
3332 	void *datum;
3333 	struct avrule_decl *decl = stack_peek(decl_stack);
3334 	struct scope_datum *scope_datum;
3335 
3336 	for (sym = 0; sym < SYM_NUM; sym++) {
3337 		if (func_to_cil[sym] == NULL) {
3338 			continue;
3339 		}
3340 
3341 		map = decl->required.scope[sym];
3342 		ebitmap_for_each_bit(&map, node, i) {
3343 			if (!ebitmap_get_bit(&map, i)) {
3344 				continue;
3345 			}
3346 			key = pdb->sym_val_to_name[sym][i];
3347 
3348 			scope_datum = hashtab_search(pdb->scope[sym].table, key);
3349 			for (j = 0; j < scope_datum->decl_ids_len; j++) {
3350 				if (scope_datum->decl_ids[j] == decl->decl_id) {
3351 					break;
3352 				}
3353 			}
3354 			if (j >= scope_datum->decl_ids_len) {
3355 				// Symbols required in the global scope are also in the
3356 				// required scope ebitmap of all avrule decls (i.e. required
3357 				// in all optionals). So we need to look at the scopes of each
3358 				// symbol in this avrule_decl to determine if it actually is
3359 				// required in this decl, or if it's just required in the
3360 				// global scope. If we got here, then this symbol is not
3361 				// actually required in this scope, so skip it.
3362 				continue;
3363 			}
3364 
3365 			datum = hashtab_search(pdb->symtab[sym].table, key);
3366 			if (datum == NULL) {
3367 				rc = -1;
3368 				goto exit;
3369 			}
3370 			rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, SCOPE_REQ);
3371 			if (rc != 0) {
3372 				goto exit;
3373 			}
3374 		}
3375 	}
3376 
3377 	return 0;
3378 exit:
3379 	return rc;
3380 }
3381 
3382 
additive_scopes_to_cil_map(char * key,void * data,void * arg)3383 static int additive_scopes_to_cil_map(char *key, void *data, void *arg)
3384 {
3385 	int rc = -1;
3386 	struct map_args *args = arg;
3387 
3388 	rc = func_to_cil[args->sym_index](args->indent, args->pdb, args->block, args->decl_stack, key, data, SCOPE_REQ);
3389 	if (rc != 0) {
3390 		goto exit;
3391 	}
3392 
3393 	return 0;
3394 
3395 exit:
3396 	return rc;
3397 }
3398 
additive_scopes_to_cil(int indent,struct policydb * pdb,struct avrule_block * block,struct stack * decl_stack)3399 static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
3400 {
3401 	int rc = -1;
3402 	struct map_args args;
3403 	args.pdb = pdb;
3404 	args.block = block;
3405 	args.decl_stack = decl_stack;
3406 	args.indent = indent;
3407 	struct avrule_decl *decl = stack_peek(decl_stack);
3408 
3409 	for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) {
3410 		rc = hashtab_map(decl->symtab[args.sym_index].table, additive_scopes_to_cil_map, &args);
3411 		if (rc != 0) {
3412 			goto exit;
3413 		}
3414 	}
3415 
3416 	return 0;
3417 
3418 exit:
3419 	return rc;
3420 }
3421 
is_scope_superset(struct scope_index * sup,struct scope_index * sub)3422 static int is_scope_superset(struct scope_index *sup, struct scope_index *sub)
3423 {
3424 	// returns 1 if sup is a superset of sub, returns 0 otherwise
3425 
3426 	int rc = 0;
3427 
3428 	uint32_t i;
3429 	struct ebitmap sup_map;
3430 	struct ebitmap sub_map;
3431 	struct ebitmap res;
3432 
3433 	ebitmap_init(&res);
3434 
3435 	for (i = 0; i < SYM_NUM; i++) {
3436 		sup_map = sup->scope[i];
3437 		sub_map = sub->scope[i];
3438 
3439 		ebitmap_and(&res, &sup_map, &sub_map);
3440 		if (!ebitmap_cmp(&res, &sub_map)) {
3441 			goto exit;
3442 		}
3443 		ebitmap_destroy(&res);
3444 	}
3445 
3446 	if (sup->class_perms_len < sub->class_perms_len) {
3447 		goto exit;
3448 	}
3449 
3450 	for (i = 0; i < sub->class_perms_len; i++) {
3451 		sup_map = sup->class_perms_map[i];
3452 		sub_map = sub->class_perms_map[i];
3453 
3454 		ebitmap_and(&res, &sup_map, &sub_map);
3455 		if (!ebitmap_cmp(&res, &sub_map)) {
3456 			goto exit;
3457 		}
3458 		ebitmap_destroy(&res);
3459 	}
3460 
3461 	rc = 1;
3462 
3463 exit:
3464 
3465 	ebitmap_destroy(&res);
3466 	return rc;
3467 }
3468 
block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack,int indent)3469 static int block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int indent)
3470 {
3471 	int rc = -1;
3472 	struct avrule_decl *decl;
3473 	struct list *attr_list;
3474 
3475 	decl = block->branch_list;
3476 
3477 	rc = list_init(&attr_list);
3478 	if (rc != 0) {
3479 		goto exit;
3480 	}
3481 
3482 	rc = typealiases_to_cil(indent, pdb, block, stack);
3483 	if (rc != 0) {
3484 		goto exit;
3485 	}
3486 
3487 	rc = declared_scopes_to_cil(indent, pdb, block, stack);
3488 	if (rc != 0) {
3489 		goto exit;
3490 	}
3491 
3492 	rc = required_scopes_to_cil(indent, pdb, block, stack);
3493 	if (rc != 0) {
3494 		goto exit;
3495 	}
3496 
3497 	rc = additive_scopes_to_cil(indent, pdb, block, stack);
3498 	if (rc != 0) {
3499 		goto exit;
3500 	}
3501 
3502 	rc = avrule_list_to_cil(indent, pdb, decl->avrules, attr_list);
3503 	if (rc != 0) {
3504 		goto exit;
3505 	}
3506 
3507 	rc = role_trans_to_cil(indent, pdb, decl->role_tr_rules);
3508 	if (rc != 0) {
3509 		goto exit;
3510 	}
3511 
3512 	rc = role_allows_to_cil(indent, pdb, decl->role_allow_rules);
3513 	if (rc != 0) {
3514 		goto exit;
3515 	}
3516 
3517 	rc = range_trans_to_cil(indent, pdb, decl->range_tr_rules);
3518 	if (rc != 0) {
3519 		goto exit;
3520 	}
3521 
3522 	rc = filename_trans_to_cil(indent, pdb, decl->filename_trans_rules);
3523 	if (rc != 0) {
3524 		goto exit;
3525 	}
3526 
3527 	rc = cond_list_to_cil(indent, pdb, decl->cond_list);
3528 	if (rc != 0) {
3529 		goto exit;
3530 	}
3531 
3532 	rc = cil_print_attr_list(indent, pdb, attr_list);
3533 	if (rc != 0) {
3534 		goto exit;
3535 	}
3536 
3537 exit:
3538 	attr_list_destroy(&attr_list);
3539 	return rc;
3540 }
3541 
module_block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack,int * indent)3542 static int module_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int *indent)
3543 {
3544 	int rc = 0;
3545 	struct avrule_decl *decl;
3546 	struct avrule_decl *decl_tmp;
3547 
3548 	decl = block->branch_list;
3549 	if (decl == NULL) {
3550 		goto exit;
3551 	}
3552 
3553 	if (decl->next != NULL) {
3554 		log_err("Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output.");
3555 	}
3556 
3557 	if (block->flags & AVRULE_OPTIONAL) {
3558 		while (stack->pos > 0) {
3559 			decl_tmp = stack_peek(stack);
3560 			if (is_scope_superset(&decl->required, &decl_tmp->required)) {
3561 				break;
3562 			}
3563 
3564 			stack_pop(stack);
3565 			(*indent)--;
3566 			cil_println(*indent, ")");
3567 		}
3568 
3569 		cil_println(*indent, "(optional %s_optional_%i", pdb->name, decl->decl_id);
3570 		(*indent)++;
3571 	}
3572 
3573 	stack_push(stack, decl);
3574 
3575 	rc = block_to_cil(pdb, block, stack, *indent);
3576 	if (rc != 0) {
3577 		goto exit;
3578 	}
3579 
3580 exit:
3581 	return rc;
3582 }
3583 
global_block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack)3584 static int global_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack)
3585 {
3586 	int rc = 0;
3587 	struct avrule_decl *decl;
3588 
3589 	decl = block->branch_list;
3590 	if (decl == NULL) {
3591 		goto exit;
3592 	}
3593 
3594 	if (decl->next != NULL) {
3595 		log_err("Warning: 'else' not allowed in global block. Dropping from output.");
3596 	}
3597 
3598 	stack_push(stack, decl);
3599 
3600 	// type aliases and commons are only stored in the global symtab.
3601 	// However, to get scoping correct, we assume they are in the
3602 	// global block
3603 	rc = hashtab_map(pdb->p_commons.table, common_to_cil, NULL);
3604 	if (rc != 0) {
3605 		goto exit;
3606 	}
3607 
3608 	rc = block_to_cil(pdb, block, stack, 0);
3609 	if (rc != 0) {
3610 		goto exit;
3611 	}
3612 
3613 exit:
3614 	return rc;
3615 }
3616 
blocks_to_cil(struct policydb * pdb)3617 static int blocks_to_cil(struct policydb *pdb)
3618 {
3619 	int rc = -1;
3620 	struct avrule_block *block;
3621 	int indent = 0;
3622 	struct stack *stack;
3623 
3624 	rc = stack_init(&stack);
3625 	if (rc != 0) {
3626 		goto exit;
3627 	}
3628 
3629 	block = pdb->global;
3630 	rc = global_block_to_cil(pdb, block, stack);
3631 	if (rc != 0) {
3632 		goto exit;
3633 	}
3634 
3635 	for (block = block->next; block != NULL; block = block->next) {
3636 		rc = module_block_to_cil(pdb, block, stack, &indent);
3637 		if (rc != 0) {
3638 			goto exit;
3639 		}
3640 	}
3641 
3642 	while (indent > 0) {
3643 		indent--;
3644 		cil_println(indent, ")");
3645 	}
3646 
3647 exit:
3648 	stack_destroy(&stack);
3649 
3650 	return rc;
3651 }
3652 
linked_block_to_cil(struct policydb * pdb,struct avrule_block * block,struct stack * stack)3653 static int linked_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack)
3654 {
3655 	int rc = 0;
3656 	struct avrule_decl *decl;
3657 
3658 	decl = block->branch_list;
3659 	if (decl == NULL) {
3660 		goto exit;
3661 	}
3662 
3663 	if (!decl->enabled) {
3664 		if (decl->next != NULL) {
3665 			decl = decl->next;
3666 		} else {
3667 			goto exit;
3668 		}
3669 	}
3670 
3671 	stack_push(stack, decl);
3672 
3673 	rc = block_to_cil(pdb, block, stack, 0);
3674 	if (rc != 0) {
3675 		goto exit;
3676 	}
3677 
3678 	stack_pop(stack);
3679 
3680 exit:
3681 	return rc;
3682 }
3683 
linked_blocks_to_cil(struct policydb * pdb)3684 static int linked_blocks_to_cil(struct policydb *pdb)
3685 {
3686 	// Convert base module that has been linked to CIL
3687 	// Since it is linked, all optional blocks have been resolved
3688 	int rc = -1;
3689 	struct avrule_block *block;
3690 	struct stack *stack;
3691 
3692 	rc = stack_init(&stack);
3693 	if (rc != 0) {
3694 		goto exit;
3695 	}
3696 
3697 	block = pdb->global;
3698 	rc = global_block_to_cil(pdb, block, stack);
3699 	if (rc != 0) {
3700 		goto exit;
3701 	}
3702 
3703 	for (block = block->next; block != NULL; block = block->next) {
3704 		rc = linked_block_to_cil(pdb, block, stack);
3705 		if (rc != 0) {
3706 			goto exit;
3707 		}
3708 	}
3709 
3710 exit:
3711 	stack_destroy(&stack);
3712 
3713 	return rc;
3714 }
3715 
handle_unknown_to_cil(struct policydb * pdb)3716 static int handle_unknown_to_cil(struct policydb *pdb)
3717 {
3718 	int rc = -1;
3719 	const char *hu;
3720 
3721 	switch (pdb->handle_unknown) {
3722 	case SEPOL_DENY_UNKNOWN:
3723 		hu = "deny";
3724 		break;
3725 	case SEPOL_REJECT_UNKNOWN:
3726 		hu = "reject";
3727 		break;
3728 	case SEPOL_ALLOW_UNKNOWN:
3729 		hu = "allow";
3730 		break;
3731 	default:
3732 		log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown);
3733 		rc = -1;
3734 		goto exit;
3735 	}
3736 
3737 	cil_println(0, "(handleunknown %s)", hu);
3738 
3739 	return 0;
3740 
3741 exit:
3742 	return rc;
3743 }
3744 
generate_mls(struct policydb * pdb)3745 static int generate_mls(struct policydb *pdb)
3746 {
3747 	const char *mls_str = pdb->mls ? "true" : "false";
3748 	cil_println(0, "(mls %s)", mls_str);
3749 
3750 	return 0;
3751 }
3752 
generate_default_level(void)3753 static int generate_default_level(void)
3754 {
3755 	cil_println(0, "(sensitivity s0)");
3756 	cil_println(0, "(sensitivityorder (s0))");
3757 	cil_println(0, "(level " DEFAULT_LEVEL " (s0))");
3758 
3759 	return 0;
3760 }
3761 
generate_default_object(void)3762 static int generate_default_object(void)
3763 {
3764 	cil_println(0, "(role " DEFAULT_OBJECT ")");
3765 
3766 	return 0;
3767 }
3768 
generate_builtin_roles(void)3769 static int generate_builtin_roles(void)
3770 {
3771 	// due to inconsistentencies between policies and CIL not allowing
3772 	// duplicate roles, some roles are always created, regardless of if they
3773 	// are declared in modules or not
3774 	cil_println(0, "(role auditadm_r)");
3775 	cil_println(0, "(role secadm_r)");
3776 
3777 	return 0;
3778 }
3779 
generate_gen_require_attribute(void)3780 static int generate_gen_require_attribute(void)
3781 {
3782 	cil_println(0, "(typeattribute " GEN_REQUIRE_ATTR ")");
3783 	cil_println(0, "(roleattribute " GEN_REQUIRE_ATTR ")");
3784 
3785 	return 0;
3786 }
3787 
fix_module_name(struct policydb * pdb)3788 static int fix_module_name(struct policydb *pdb)
3789 {
3790 	char *letter;
3791 	int rc = -1;
3792 
3793 	// The base module doesn't have its name set, but we use that for some
3794 	// autogenerated names, like optionals and attributes, to prevent naming
3795 	// collisions. However, they sometimes need to be fixed up.
3796 
3797 	// the base module isn't given a name, so just call it "base"
3798 	if (pdb->policy_type == POLICY_BASE) {
3799 		pdb->name = strdup("base");
3800 		if (pdb->name == NULL) {
3801 			log_err("Out of memory");
3802 			rc = -1;
3803 			goto exit;
3804 		}
3805 	}
3806 
3807 	// CIL is more restrictive in module names than checkmodule. Convert bad
3808 	// characters to underscores
3809 	for (letter = pdb->name; *letter != '\0'; letter++) {
3810 		if (isalnum(*letter)) {
3811 			continue;
3812 		}
3813 
3814 		*letter = '_';
3815 	}
3816 
3817 	return 0;
3818 exit:
3819 	return rc;
3820 }
3821 
sepol_module_policydb_to_cil(FILE * fp,struct policydb * pdb,int linked)3822 int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked)
3823 {
3824 	int rc = -1;
3825 
3826 	out_file = fp;
3827 
3828 	if (pdb == NULL) {
3829 		rc = 0;
3830 		goto exit;
3831 	}
3832 
3833 	if (pdb->policy_type != SEPOL_POLICY_BASE &&
3834 		pdb->policy_type != SEPOL_POLICY_MOD) {
3835 		log_err("Policy pakcage is not a base or module");
3836 		rc = -1;
3837 		goto exit;
3838 	}
3839 
3840 	rc = fix_module_name(pdb);
3841 	if (rc != 0) {
3842 		goto exit;
3843 	}
3844 
3845 	if (pdb->policy_type == SEPOL_POLICY_BASE && !pdb->mls) {
3846 		// If this is a base non-mls policy, we need to define a default level
3847 		// range that can be used for contexts by other non-mls modules, since
3848 		// CIL requires that all contexts have a range, even if they are
3849 		// ignored as in non-mls policies
3850 		rc = generate_default_level();
3851 		if (rc != 0) {
3852 			goto exit;
3853 		}
3854 	}
3855 
3856 	if (pdb->policy_type == SEPOL_POLICY_BASE) {
3857 		// object_r is implicit in checkmodule, but not with CIL, create it
3858 		// as part of base
3859 		rc = generate_default_object();
3860 		if (rc != 0) {
3861 			goto exit;
3862 		}
3863 
3864 		rc = generate_builtin_roles();
3865 		if (rc != 0) {
3866 			goto exit;
3867 		}
3868 
3869 		// default attribute to be used to mimic gen_require in CIL
3870 		rc = generate_gen_require_attribute();
3871 		if (rc != 0) {
3872 			goto exit;
3873 		}
3874 
3875 		// handle_unknown is used from only the base module
3876 		rc = handle_unknown_to_cil(pdb);
3877 		if (rc != 0) {
3878 			goto exit;
3879 		}
3880 
3881 		// mls is used from only the base module
3882 		rc = generate_mls(pdb);
3883 		if (rc != 0) {
3884 			goto exit;
3885 		}
3886 	}
3887 
3888 	rc = role_list_create(pdb->p_roles.table);
3889 	if (rc != 0) {
3890 		goto exit;
3891 	}
3892 
3893 	rc = typealias_list_create(pdb);
3894 	if (rc != 0) {
3895 		goto exit;
3896 	}
3897 
3898 	rc = polcaps_to_cil(pdb);
3899 	if (rc != 0) {
3900 		goto exit;
3901 	}
3902 
3903 	rc = ocontexts_to_cil(pdb);
3904 	if (rc != 0) {
3905 		goto exit;
3906 	}
3907 
3908 	rc = genfscon_to_cil(pdb);
3909 	if (rc != 0) {
3910 		goto exit;
3911 	}
3912 
3913 	// now print everything that is scoped
3914 	if (linked) {
3915 		rc = linked_blocks_to_cil(pdb);
3916 	} else {
3917 		rc = blocks_to_cil(pdb);
3918 	}
3919 	if (rc != 0) {
3920 		goto exit;
3921 	}
3922 
3923 	rc = 0;
3924 
3925 exit:
3926 	role_list_destroy();
3927 	typealias_list_destroy();
3928 
3929 	return rc;
3930 }
3931 
sepol_module_package_to_cil(FILE * fp,struct sepol_module_package * mod_pkg)3932 int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg)
3933 {
3934 	int rc = -1;
3935 	struct sepol_policydb *pdb;
3936 
3937 	out_file = fp;
3938 
3939 	pdb = sepol_module_package_get_policy(mod_pkg);
3940 	if (pdb == NULL) {
3941 		log_err("Failed to get policydb");
3942 		rc = -1;
3943 		goto exit;
3944 	}
3945 
3946 	rc = sepol_module_policydb_to_cil(fp, &pdb->p, 0);
3947 	if (rc != 0) {
3948 		goto exit;
3949 	}
3950 
3951 	rc = seusers_to_cil(mod_pkg);
3952 	if (rc != 0) {
3953 		goto exit;
3954 	}
3955 
3956 	rc = netfilter_contexts_to_cil(mod_pkg);
3957 	if (rc != 0) {
3958 		goto exit;
3959 	}
3960 
3961 	rc = user_extra_to_cil(mod_pkg);
3962 	if (rc != 0) {
3963 		goto exit;
3964 	}
3965 
3966 	rc = file_contexts_to_cil(mod_pkg);
3967 	if (rc != 0) {
3968 		goto exit;
3969 	}
3970 
3971 	rc = 0;
3972 
3973 exit:
3974 	return rc;
3975 }
3976 
fp_to_buffer(FILE * fp,char ** data,size_t * data_len)3977 static int fp_to_buffer(FILE *fp, char **data, size_t *data_len)
3978 {
3979 	int rc = -1;
3980 	char *d = NULL;
3981 	size_t d_len = 0;
3982 	size_t read_len = 0;
3983 	size_t max_len = 1 << 17; // start at 128KB, this is enough to hold about half of all the existing pp files
3984 
3985 	d = malloc(max_len);
3986 	if (d == NULL) {
3987 		log_err("Out of memory");
3988 		rc = -1;
3989 		goto exit;
3990 	}
3991 
3992 	while ((read_len = fread(d + d_len, 1, max_len - d_len, fp)) > 0) {
3993 		d_len += read_len;
3994 		if (d_len == max_len) {
3995 			max_len *= 2;
3996 			d = realloc(d, max_len);
3997 			if (d == NULL) {
3998 				log_err("Out of memory");
3999 				rc = -1;
4000 				goto exit;
4001 			}
4002 		}
4003 	}
4004 
4005 	if (ferror(fp) != 0) {
4006 		log_err("Failed to read pp file");
4007 		rc = -1;
4008 		goto exit;
4009 	}
4010 
4011 	*data = d;
4012 	*data_len = d_len;
4013 
4014 	return 0;
4015 
4016 exit:
4017 	free(d);
4018 	return rc;
4019 }
4020 
sepol_ppfile_to_module_package(FILE * fp,struct sepol_module_package ** mod_pkg)4021 int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg)
4022 {
4023 	int rc = -1;
4024 	FILE *f = NULL;
4025 	struct sepol_policy_file *pf = NULL;
4026 	struct sepol_module_package *pkg = NULL;
4027 	char *data = NULL;
4028 	size_t data_len;
4029 	int fd;
4030 	struct stat sb;
4031 
4032 	rc = sepol_policy_file_create(&pf);
4033 	if (rc != 0) {
4034 		log_err("Failed to create policy file");
4035 		goto exit;
4036 	}
4037 
4038 	fd = fileno(fp);
4039 	if (fstat(fd, &sb) == -1) {
4040 		rc = -1;
4041 		goto exit;
4042 	}
4043 
4044 	if (S_ISFIFO(sb.st_mode) || S_ISSOCK(sb.st_mode)) {
4045 		// libsepol fails when trying to read a policy package from a pipe or a
4046 		// socket due its use of lseek. In this case, read the data into a
4047 		// buffer and provide that to libsepol
4048 		rc = fp_to_buffer(fp, &data, &data_len);
4049 		if (rc != 0) {
4050 			goto exit;
4051 		}
4052 
4053 		sepol_policy_file_set_mem(pf, data, data_len);
4054 	} else {
4055 		sepol_policy_file_set_fp(pf, fp);
4056 	}
4057 
4058 	rc = sepol_module_package_create(&pkg);
4059 	if (rc != 0) {
4060 		log_err("Failed to create module package");
4061 		goto exit;
4062 	}
4063 
4064 	rc = sepol_module_package_read(pkg, pf, 0);
4065 	if (rc != 0) {
4066 		log_err("Failed to read policy package");
4067 		goto exit;
4068 	}
4069 
4070 	*mod_pkg = pkg;
4071 
4072 exit:
4073 	free(data);
4074 
4075 	sepol_policy_file_free(pf);
4076 	if (f != NULL) {
4077 		fclose(f);
4078 	}
4079 
4080 	if (rc != 0) {
4081 		sepol_module_package_free(pkg);
4082 	}
4083 
4084 	return rc;
4085 }
4086