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