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