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