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