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