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