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