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