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