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