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