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