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