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