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