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