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