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