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