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