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