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