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