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