1#include <stdarg.h> 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <inttypes.h> 6#include <sys/types.h> 7#include <unistd.h> 8 9#include <arpa/inet.h> 10#include <errno.h> 11#include <netinet/in.h> 12#ifndef IPPROTO_DCCP 13#define IPPROTO_DCCP 33 14#endif 15#ifndef IPPROTO_SCTP 16#define IPPROTO_SCTP 132 17#endif 18 19#include <sepol/kernel_to_cil.h> 20#include <sepol/policydb/avtab.h> 21#include <sepol/policydb/conditional.h> 22#include <sepol/policydb/hashtab.h> 23#include <sepol/policydb/polcaps.h> 24#include <sepol/policydb/policydb.h> 25#include <sepol/policydb/services.h> 26#include <sepol/policydb/util.h> 27 28#include "kernel_to_common.h" 29 30 31static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) 32{ 33 struct cond_expr *curr; 34 struct strs *stack; 35 char *new_val; 36 char *str = NULL; 37 int rc; 38 39 rc = strs_stack_init(&stack); 40 if (rc != 0) { 41 goto exit; 42 } 43 44 for (curr = expr; curr != NULL; curr = curr->next) { 45 if (curr->expr_type == COND_BOOL) { 46 char *val1 = pdb->p_bool_val_to_name[curr->bool - 1]; 47 new_val = create_str("%s", 1, val1); 48 } else { 49 const char *op; 50 uint32_t num_params; 51 char *val1 = NULL; 52 char *val2 = NULL; 53 54 switch(curr->expr_type) { 55 case COND_NOT: op = "not"; num_params = 1; break; 56 case COND_OR: op = "or"; num_params = 2; break; 57 case COND_AND: op = "and"; num_params = 2; break; 58 case COND_XOR: op = "xor"; num_params = 2; break; 59 case COND_EQ: op = "eq"; num_params = 2; break; 60 case COND_NEQ: op = "neq"; num_params = 2; break; 61 default: 62 sepol_log_err("Unknown conditional operator: %i", 63 curr->expr_type); 64 goto exit; 65 } 66 67 if (num_params == 2) { 68 val2 = strs_stack_pop(stack); 69 if (!val2) { 70 sepol_log_err("Invalid conditional expression"); 71 goto exit; 72 } 73 } 74 val1 = strs_stack_pop(stack); 75 if (!val1) { 76 sepol_log_err("Invalid conditional expression"); 77 free(val2); 78 goto exit; 79 } 80 if (num_params == 2) { 81 new_val = create_str("(%s %s %s)", 3, op, val1, val2); 82 free(val2); 83 } else { 84 new_val = create_str("(%s %s)", 2, op, val1); 85 } 86 free(val1); 87 } 88 if (!new_val) { 89 sepol_log_err("Invalid conditional expression"); 90 goto exit; 91 } 92 rc = strs_stack_push(stack, new_val); 93 if (rc != 0) { 94 sepol_log_err("Out of memory"); 95 goto exit; 96 } 97 } 98 99 new_val = strs_stack_pop(stack); 100 if (!new_val || !strs_stack_empty(stack)) { 101 sepol_log_err("Invalid conditional expression"); 102 goto exit; 103 } 104 105 str = new_val; 106 107 strs_stack_destroy(&stack); 108 return str; 109 110exit: 111 if (stack) { 112 while ((new_val = strs_stack_pop(stack)) != NULL) { 113 free(new_val); 114 } 115 strs_stack_destroy(&stack); 116 } 117 118 return NULL; 119} 120 121static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls) 122{ 123 struct constraint_expr *curr; 124 struct strs *stack = NULL; 125 char *new_val = NULL; 126 const char *op; 127 char *str = NULL; 128 int rc; 129 130 *use_mls = 0; 131 132 rc = strs_stack_init(&stack); 133 if (rc != 0) { 134 goto exit; 135 } 136 137 for (curr = expr; curr; curr = curr->next) { 138 if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) { 139 const char *attr1 = NULL; 140 const char *attr2 = NULL; 141 142 switch (curr->op) { 143 case CEXPR_EQ: op = "eq"; break; 144 case CEXPR_NEQ: op = "neq"; break; 145 case CEXPR_DOM: op = "dom"; break; 146 case CEXPR_DOMBY: op = "domby"; break; 147 case CEXPR_INCOMP: op = "incomp"; break; 148 default: 149 sepol_log_err("Unknown constraint operator: %i", curr->op); 150 goto exit; 151 } 152 153 switch (curr->attr) { 154 case CEXPR_USER: attr1 ="u1"; attr2 ="u2"; break; 155 case CEXPR_USER | CEXPR_TARGET: attr1 ="u2"; attr2 =""; break; 156 case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 =""; break; 157 case CEXPR_ROLE: attr1 ="r1"; attr2 ="r2"; break; 158 case CEXPR_ROLE | CEXPR_TARGET: attr1 ="r2"; attr2 =""; break; 159 case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 =""; break; 160 case CEXPR_TYPE: attr1 ="t1"; attr2 ="t2"; break; 161 case CEXPR_TYPE | CEXPR_TARGET: attr1 ="t2"; attr2 =""; break; 162 case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 =""; break; 163 case CEXPR_L1L2: attr1 ="l1"; attr2 ="l2"; break; 164 case CEXPR_L1H2: attr1 ="l1"; attr2 ="h2"; break; 165 case CEXPR_H1L2: attr1 ="h1"; attr2 ="l2"; break; 166 case CEXPR_H1H2: attr1 ="h1"; attr2 ="h2"; break; 167 case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break; 168 case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break; 169 default: 170 sepol_log_err("Unknown constraint attribute: %i", 171 curr->attr); 172 goto exit; 173 } 174 175 if (curr->attr >= CEXPR_XTARGET) { 176 *use_mls = 1; 177 } 178 179 if (curr->expr_type == CEXPR_ATTR) { 180 new_val = create_str("(%s %s %s)", 3, op, attr1, attr2); 181 } else { 182 char *names = NULL; 183 if (curr->attr & CEXPR_TYPE) { 184 struct type_set *ts = curr->type_names; 185 names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1); 186 } else if (curr->attr & CEXPR_USER) { 187 names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1); 188 } else if (curr->attr & CEXPR_ROLE) { 189 names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1); 190 } 191 if (!names) { 192 names = strdup("NO_IDENTIFIER"); 193 if (!names) { 194 sepol_log_err("Out of memory"); 195 goto exit; 196 } 197 } 198 if (strchr(names, ' ')) { 199 new_val = create_str("(%s %s (%s))", 3, op, attr1, names); 200 } else { 201 new_val = create_str("(%s %s %s)", 3, op, attr1, names); 202 } 203 free(names); 204 } 205 } else { 206 uint32_t num_params; 207 char *val1 = NULL; 208 char *val2 = NULL; 209 210 switch (curr->expr_type) { 211 case CEXPR_NOT: op = "not"; num_params = 1; break; 212 case CEXPR_AND: op = "and"; num_params = 2; break; 213 case CEXPR_OR: op = "or"; num_params = 2; break; 214 default: 215 sepol_log_err("Unknown constraint expression type: %i", 216 curr->expr_type); 217 goto exit; 218 } 219 220 if (num_params == 2) { 221 val2 = strs_stack_pop(stack); 222 if (!val2) { 223 sepol_log_err("Invalid constraint expression"); 224 goto exit; 225 } 226 } 227 val1 = strs_stack_pop(stack); 228 if (!val1) { 229 sepol_log_err("Invalid constraint expression"); 230 goto exit; 231 } 232 233 if (num_params == 2) { 234 new_val = create_str("(%s %s %s)", 3, op, val1, val2); 235 free(val2); 236 } else { 237 new_val = create_str("(%s %s)", 2, op, val1); 238 } 239 free(val1); 240 } 241 if (!new_val) { 242 goto exit; 243 } 244 rc = strs_stack_push(stack, new_val); 245 if (rc != 0) { 246 sepol_log_err("Out of memory"); 247 goto exit; 248 } 249 } 250 251 new_val = strs_stack_pop(stack); 252 if (!new_val || !strs_stack_empty(stack)) { 253 sepol_log_err("Invalid constraint expression"); 254 goto exit; 255 } 256 257 str = new_val; 258 259 strs_stack_destroy(&stack); 260 261 return str; 262 263exit: 264 if (stack) { 265 while ((new_val = strs_stack_pop(stack)) != NULL) { 266 free(new_val); 267 } 268 strs_stack_destroy(&stack); 269 } 270 271 return NULL; 272} 273 274static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, 275 class_datum_t *class, 276 struct constraint_node *constraint_rules, 277 struct strs *mls_list, 278 struct strs *non_mls_list) 279{ 280 int rc = 0; 281 struct constraint_node *curr; 282 char *expr = NULL; 283 int is_mls; 284 char *perms; 285 const char *key_word; 286 struct strs *strs; 287 288 for (curr = constraint_rules; curr != NULL; curr = curr->next) { 289 if (curr->permissions == 0) { 290 continue; 291 } 292 expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); 293 if (!expr) { 294 rc = -1; 295 goto exit; 296 } 297 298 perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); 299 300 if (is_mls) { 301 key_word = "mlsconstrain"; 302 strs = mls_list; 303 } else { 304 key_word = "constrain"; 305 strs = non_mls_list; 306 } 307 308 rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", 4, key_word, classkey, perms+1, expr); 309 free(expr); 310 if (rc != 0) { 311 goto exit; 312 } 313 } 314 315 return 0; 316exit: 317 sepol_log_err("Error gathering constraint rules\n"); 318 return rc; 319} 320 321static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey, 322 struct constraint_node *validatetrans_rules, 323 struct strs *mls_list, 324 struct strs *non_mls_list) 325{ 326 struct constraint_node *curr; 327 char *expr = NULL; 328 int is_mls; 329 const char *key_word; 330 struct strs *strs; 331 int rc = 0; 332 333 for (curr = validatetrans_rules; curr != NULL; curr = curr->next) { 334 expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); 335 if (!expr) { 336 rc = -1; 337 goto exit; 338 } 339 340 if (is_mls) { 341 key_word = "mlsvalidatetrans"; 342 strs = mls_list; 343 } else { 344 key_word = "validatetrans"; 345 strs = non_mls_list; 346 } 347 348 rc = strs_create_and_add(strs, "(%s %s %s)", 3, key_word, classkey, expr); 349 free(expr); 350 if (rc != 0) { 351 goto exit; 352 } 353 } 354 355exit: 356 return rc; 357} 358 359static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) 360{ 361 class_datum_t *class; 362 char *name; 363 unsigned i; 364 int rc = 0; 365 366 for (i=0; i < pdb->p_classes.nprim; i++) { 367 class = pdb->class_val_to_struct[i]; 368 if (!class) continue; 369 if (class->constraints) { 370 name = pdb->p_class_val_to_name[i]; 371 rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs); 372 if (rc != 0) { 373 goto exit; 374 } 375 } 376 } 377 378 strs_sort(mls_strs); 379 strs_sort(non_mls_strs); 380 381exit: 382 return rc; 383} 384 385static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) 386{ 387 class_datum_t *class; 388 char *name; 389 unsigned i; 390 int rc = 0; 391 392 for (i=0; i < pdb->p_classes.nprim; i++) { 393 class = pdb->class_val_to_struct[i]; 394 if (!class) continue; 395 if (class->validatetrans) { 396 name = pdb->p_class_val_to_name[i]; 397 rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs); 398 if (rc != 0) { 399 goto exit; 400 } 401 } 402 } 403 404 strs_sort(mls_strs); 405 strs_sort(non_mls_strs); 406 407exit: 408 return rc; 409} 410 411static int write_handle_unknown_to_cil(FILE *out, struct policydb *pdb) 412{ 413 const char *action; 414 415 switch (pdb->handle_unknown) { 416 case SEPOL_DENY_UNKNOWN: 417 action = "deny"; 418 break; 419 case SEPOL_REJECT_UNKNOWN: 420 action = "reject"; 421 break; 422 case SEPOL_ALLOW_UNKNOWN: 423 action = "allow"; 424 break; 425 default: 426 sepol_log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown); 427 return -1; 428 } 429 430 sepol_printf(out, "(handleunknown %s)\n", action); 431 432 return 0; 433} 434 435static char *class_or_common_perms_to_str(symtab_t *permtab) 436{ 437 struct strs *strs; 438 char *perms = NULL; 439 int rc; 440 441 rc = strs_init(&strs, permtab->nprim); 442 if (rc != 0) { 443 goto exit; 444 } 445 446 rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs); 447 if (rc != 0) { 448 goto exit; 449 } 450 451 if (strs_num_items(strs) > 0) { 452 perms = strs_to_str(strs); 453 } 454 455exit: 456 strs_destroy(&strs); 457 458 return perms; 459} 460 461static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb) 462{ 463 class_datum_t *class; 464 common_datum_t *common; 465 int *used; 466 char *name, *perms; 467 unsigned i; 468 int rc = 0; 469 470 /* class */ 471 for (i=0; i < pdb->p_classes.nprim; i++) { 472 class = pdb->class_val_to_struct[i]; 473 if (!class) continue; 474 name = pdb->p_class_val_to_name[i]; 475 perms = class_or_common_perms_to_str(&class->permissions); 476 if (perms) { 477 sepol_printf(out, "(class %s (%s))\n", name, perms); 478 free(perms); 479 } else { 480 sepol_printf(out, "(class %s ())\n", name); 481 } 482 } 483 484 /* classorder */ 485 sepol_printf(out, "(classorder ("); 486 name = NULL; 487 for (i=0; i < pdb->p_classes.nprim; i++) { 488 if (name) { 489 sepol_printf(out, "%s ", name); 490 } 491 name = pdb->p_class_val_to_name[i]; 492 } 493 if (name) { 494 sepol_printf(out, "%s", name); 495 } 496 sepol_printf(out, "))\n"); 497 498 /* classcommon */ 499 for (i=0; i < pdb->p_classes.nprim; i++) { 500 class = pdb->class_val_to_struct[i]; 501 if (!class) continue; 502 name = pdb->p_class_val_to_name[i]; 503 if (class->comkey != NULL) { 504 sepol_printf(out, "(classcommon %s %s)\n", name, class->comkey); 505 } 506 } 507 508 /* common */ 509 used = calloc(pdb->p_commons.nprim, sizeof(*used)); 510 if (!used) { 511 sepol_log_err("Out of memory"); 512 rc = -1; 513 goto exit; 514 } 515 for (i=0; i < pdb->p_classes.nprim; i++) { 516 class = pdb->class_val_to_struct[i]; 517 if (!class) continue; 518 name = class->comkey; 519 if (name != NULL) { 520 common = hashtab_search(pdb->p_commons.table, name); 521 if (!common) { 522 rc = -1; 523 free(used); 524 goto exit; 525 } 526 /* Only write common rule once */ 527 if (!used[common->s.value-1]) { 528 perms = class_or_common_perms_to_str(&common->permissions); 529 if (!perms) { 530 rc = -1; 531 free(perms); 532 free(used); 533 goto exit; 534 } 535 536 sepol_printf(out, "(common %s (%s))\n", name, perms); 537 free(perms); 538 used[common->s.value-1] = 1; 539 } 540 } 541 } 542 free(used); 543 544exit: 545 if (rc != 0) { 546 sepol_log_err("Error writing class rules to CIL\n"); 547 } 548 549 return rc; 550} 551 552static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, 553 unsigned num_sids, struct ocontext *isids) 554{ 555 struct ocontext *isid; 556 struct strs *strs; 557 char *sid; 558 char *prev; 559 char unknown[18]; 560 unsigned i; 561 int rc; 562 563 rc = strs_init(&strs, num_sids+1); 564 if (rc != 0) { 565 goto exit; 566 } 567 568 for (isid = isids; isid != NULL; isid = isid->next) { 569 i = isid->sid[0]; 570 if (i < num_sids) { 571 sid = (char *)sid_to_str[i]; 572 } else { 573 snprintf(unknown, 18, "%s%u", "UNKNOWN", i); 574 sid = strdup(unknown); 575 if (!sid) { 576 sepol_log_err("Out of memory"); 577 rc = -1; 578 goto exit; 579 } 580 } 581 rc = strs_add_at_index(strs, sid, i); 582 if (rc != 0) { 583 goto exit; 584 } 585 } 586 587 for (i=0; i<strs_num_items(strs); i++) { 588 sid = strs_read_at_index(strs, i); 589 if (!sid) { 590 continue; 591 } 592 sepol_printf(out, "(sid %s)\n", sid); 593 } 594 595 sepol_printf(out, "(sidorder ("); 596 prev = NULL; 597 for (i=0; i<strs_num_items(strs); i++) { 598 sid = strs_read_at_index(strs, i); 599 if (!sid) { 600 continue; 601 } 602 if (prev) { 603 sepol_printf(out, "%s ", prev); 604 } 605 prev = sid; 606 } 607 if (prev) { 608 sepol_printf(out, "%s", prev); 609 } 610 sepol_printf(out, "))\n"); 611 612exit: 613 for (i=num_sids; i<strs_num_items(strs); i++) { 614 sid = strs_read_at_index(strs, i); 615 free(sid); 616 } 617 strs_destroy(&strs); 618 if (rc != 0) { 619 sepol_log_err("Error writing sid rules to CIL\n"); 620 } 621 622 return rc; 623} 624 625static int write_sid_decl_rules_to_cil(FILE *out, struct policydb *pdb) 626{ 627 int rc = 0; 628 629 if (pdb->target_platform == SEPOL_TARGET_SELINUX) { 630 rc = write_sids_to_cil(out, selinux_sid_to_str, SELINUX_SID_SZ, 631 pdb->ocontexts[0]); 632 } else if (pdb->target_platform == SEPOL_TARGET_XEN) { 633 rc = write_sids_to_cil(out, xen_sid_to_str, XEN_SID_SZ, 634 pdb->ocontexts[0]); 635 } else { 636 sepol_log_err("Unknown target platform: %i", pdb->target_platform); 637 rc = -1; 638 } 639 640 return rc; 641} 642 643static int write_default_user_to_cil(FILE *out, char *class_name, class_datum_t *class) 644{ 645 const char *dft; 646 647 switch (class->default_user) { 648 case DEFAULT_SOURCE: 649 dft = "source"; 650 break; 651 case DEFAULT_TARGET: 652 dft = "target"; 653 break; 654 default: 655 sepol_log_err("Unknown default role value: %i", class->default_user); 656 return -1; 657 } 658 sepol_printf(out, "(defaultuser %s %s)\n", class_name, dft); 659 660 return 0; 661} 662 663static int write_default_role_to_cil(FILE *out, char *class_name, class_datum_t *class) 664{ 665 const char *dft; 666 667 switch (class->default_role) { 668 case DEFAULT_SOURCE: 669 dft = "source"; 670 break; 671 case DEFAULT_TARGET: 672 dft = "target"; 673 break; 674 default: 675 sepol_log_err("Unknown default role value: %i", class->default_role); 676 return -1; 677 } 678 sepol_printf(out, "(defaultrole %s %s)\n", class_name, dft); 679 680 return 0; 681} 682 683static int write_default_type_to_cil(FILE *out, char *class_name, class_datum_t *class) 684{ 685 const char *dft; 686 687 switch (class->default_type) { 688 case DEFAULT_SOURCE: 689 dft = "source"; 690 break; 691 case DEFAULT_TARGET: 692 dft = "target"; 693 break; 694 default: 695 sepol_log_err("Unknown default type value: %i", class->default_type); 696 return -1; 697 } 698 sepol_printf(out, "(defaulttype %s %s)\n", class_name, dft); 699 700 return 0; 701} 702 703static int write_default_range_to_cil(FILE *out, char *class_name, class_datum_t *class) 704{ 705 const char *dft; 706 707 switch (class->default_range) { 708 case DEFAULT_SOURCE_LOW: 709 dft = "source low"; 710 break; 711 case DEFAULT_SOURCE_HIGH: 712 dft = "source high"; 713 break; 714 case DEFAULT_SOURCE_LOW_HIGH: 715 dft = "source low-high"; 716 break; 717 case DEFAULT_TARGET_LOW: 718 dft = "target low"; 719 break; 720 case DEFAULT_TARGET_HIGH: 721 dft = "target high"; 722 break; 723 case DEFAULT_TARGET_LOW_HIGH: 724 dft = "target low-high"; 725 break; 726 case DEFAULT_GLBLUB: 727 dft = "glblub"; 728 break; 729 default: 730 sepol_log_err("Unknown default type value: %i", class->default_range); 731 return -1; 732 } 733 sepol_printf(out, "(defaultrange %s %s)\n", class_name, dft); 734 735 return 0; 736} 737 738static int write_default_rules_to_cil(FILE *out, struct policydb *pdb) 739{ 740 class_datum_t *class; 741 unsigned i; 742 int rc = 0; 743 744 /* default_user */ 745 for (i=0; i < pdb->p_classes.nprim; i++) { 746 class = pdb->class_val_to_struct[i]; 747 if (!class) continue; 748 if (class->default_user != 0) { 749 rc = write_default_user_to_cil(out, pdb->p_class_val_to_name[i], class); 750 if (rc != 0) { 751 goto exit; 752 } 753 } 754 } 755 756 /* default_role */ 757 for (i=0; i < pdb->p_classes.nprim; i++) { 758 class = pdb->class_val_to_struct[i]; 759 if (!class) continue; 760 if (class->default_role != 0) { 761 rc = write_default_role_to_cil(out, pdb->p_class_val_to_name[i], class); 762 if (rc != 0) { 763 goto exit; 764 } 765 } 766 } 767 768 /* default_type */ 769 for (i=0; i < pdb->p_classes.nprim; i++) { 770 class = pdb->class_val_to_struct[i]; 771 if (!class) continue; 772 if (class->default_type != 0) { 773 rc = write_default_type_to_cil(out, pdb->p_class_val_to_name[i], class); 774 if (rc != 0) { 775 goto exit; 776 } 777 } 778 } 779 780 if (!pdb->mls) { 781 return 0; 782 } 783 784 /* default_range */ 785 for (i=0; i < pdb->p_classes.nprim; i++) { 786 class = pdb->class_val_to_struct[i]; 787 if (!class) continue; 788 if (class->default_range) { 789 rc = write_default_range_to_cil(out, pdb->p_class_val_to_name[i], class); 790 if (rc != 0) { 791 goto exit; 792 } 793 } 794 } 795 796exit: 797 if (rc != 0) { 798 sepol_log_err("Error writing default rules to CIL\n"); 799 } 800 801 return rc; 802} 803 804static void write_default_mls_level(FILE *out) 805{ 806 sepol_printf(out, "(sensitivity s0)\n"); 807 sepol_printf(out, "(sensitivityorder (s0))\n"); 808 sepol_printf(out, "(level %s (s0))\n", DEFAULT_LEVEL); 809} 810 811static int map_count_sensitivity_aliases(__attribute__((unused)) char *key, void *data, void *args) 812{ 813 level_datum_t *sens = data; 814 unsigned *count = args; 815 816 if (sens->isalias) 817 (*count)++; 818 819 return SEPOL_OK; 820} 821 822static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args) 823{ 824 level_datum_t *sens = data; 825 struct strs *strs = args; 826 int rc = 0; 827 828 if (sens->isalias) { 829 rc = strs_add(strs, key); 830 } 831 832 return rc; 833} 834 835static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb) 836{ 837 level_datum_t *level; 838 char *prev, *name, *actual; 839 struct strs *strs = NULL; 840 unsigned i, num = 0; 841 int rc = 0; 842 843 /* sensitivities */ 844 for (i=0; i < pdb->p_levels.nprim; i++) { 845 name = pdb->p_sens_val_to_name[i]; 846 sepol_printf(out, "(sensitivity %s)\n", name); 847 } 848 849 /* sensitivityorder */ 850 sepol_printf(out, "(sensitivityorder ("); 851 prev = NULL; 852 for (i=0; i < pdb->p_levels.nprim; i++) { 853 name = pdb->p_sens_val_to_name[i]; 854 if (prev) { 855 sepol_printf(out, "%s ", prev); 856 } 857 prev = name; 858 } 859 if (prev) { 860 sepol_printf(out, "%s", prev); 861 } 862 sepol_printf(out, "))\n"); 863 864 rc = hashtab_map(pdb->p_levels.table, map_count_sensitivity_aliases, &num); 865 if (rc != 0) { 866 goto exit; 867 } 868 869 if (num == 0) { 870 /* No aliases, so skip sensitivity alias rules */ 871 rc = 0; 872 goto exit; 873 } 874 875 rc = strs_init(&strs, num); 876 if (rc != 0) { 877 goto exit; 878 } 879 880 rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs); 881 if (rc != 0) { 882 goto exit; 883 } 884 885 strs_sort(strs); 886 887 /* sensitivity aliases */ 888 for (i=0; i < num; i++) { 889 name = strs_read_at_index(strs, i); 890 sepol_printf(out, "(sensitivityalias %s)\n", name); 891 } 892 893 /* sensitivity aliases to actual */ 894 for (i=0; i < num; i++) { 895 name = strs_read_at_index(strs, i); 896 level = hashtab_search(pdb->p_levels.table, name); 897 if (!level) { 898 rc = -1; 899 goto exit; 900 } 901 actual = pdb->p_sens_val_to_name[level->level->sens - 1]; 902 sepol_printf(out, "(sensitivityaliasactual %s %s)\n", name, actual); 903 } 904 905exit: 906 strs_destroy(&strs); 907 908 if (rc != 0) { 909 sepol_log_err("Error writing sensitivity rules to CIL\n"); 910 } 911 912 return rc; 913} 914 915static int map_count_category_aliases(__attribute__((unused)) char *key, void *data, void *args) 916{ 917 cat_datum_t *cat = data; 918 unsigned *count = args; 919 920 if (cat->isalias) 921 (*count)++; 922 923 return SEPOL_OK; 924} 925 926static int map_category_aliases_to_strs(char *key, void *data, void *args) 927{ 928 cat_datum_t *cat = data; 929 struct strs *strs = args; 930 int rc = 0; 931 932 if (cat->isalias) { 933 rc = strs_add(strs, key); 934 } 935 936 return rc; 937} 938 939static int write_category_rules_to_cil(FILE *out, struct policydb *pdb) 940{ 941 cat_datum_t *cat; 942 char *prev, *name, *actual; 943 struct strs *strs = NULL; 944 unsigned i, num = 0; 945 int rc = 0; 946 947 /* categories */ 948 for (i=0; i < pdb->p_cats.nprim; i++) { 949 name = pdb->p_cat_val_to_name[i]; 950 sepol_printf(out, "(category %s)\n", name); 951 } 952 953 /* categoryorder */ 954 sepol_printf(out, "(categoryorder ("); 955 prev = NULL; 956 for (i=0; i < pdb->p_cats.nprim; i++) { 957 name = pdb->p_cat_val_to_name[i]; 958 if (prev) { 959 sepol_printf(out, "%s ", prev); 960 } 961 prev = name; 962 } 963 if (prev) { 964 sepol_printf(out, "%s", prev); 965 } 966 sepol_printf(out, "))\n"); 967 968 rc = hashtab_map(pdb->p_cats.table, map_count_category_aliases, &num); 969 if (rc != 0) { 970 goto exit; 971 } 972 973 if (num == 0) { 974 /* No aliases, so skip category alias rules */ 975 rc = 0; 976 goto exit; 977 } 978 979 rc = strs_init(&strs, num); 980 if (rc != 0) { 981 goto exit; 982 } 983 984 rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs); 985 if (rc != 0) { 986 goto exit; 987 } 988 989 strs_sort(strs); 990 991 /* category aliases */ 992 for (i=0; i < num; i++) { 993 name = strs_read_at_index(strs, i); 994 sepol_printf(out, "(categoryalias %s)\n", name); 995 } 996 997 /* category aliases to actual */ 998 for (i=0; i < num; i++) { 999 name = strs_read_at_index(strs, i); 1000 cat = hashtab_search(pdb->p_cats.table, name); 1001 if (!cat) { 1002 rc = -1; 1003 goto exit; 1004 } 1005 actual = pdb->p_cat_val_to_name[cat->s.value - 1]; 1006 sepol_printf(out, "(categoryaliasactual %s %s)\n", name, actual); 1007 } 1008 1009exit: 1010 strs_destroy(&strs); 1011 1012 if (rc != 0) { 1013 sepol_log_err("Error writing category rules to CIL\n"); 1014 } 1015 1016 return rc; 1017} 1018 1019static size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name) 1020{ 1021 struct ebitmap_node *node; 1022 uint32_t i, start, range; 1023 size_t len = 0; 1024 1025 range = 0; 1026 ebitmap_for_each_positive_bit(cats, node, i) { 1027 if (range == 0) 1028 start = i; 1029 1030 range++; 1031 1032 if (ebitmap_get_bit(cats, i+1)) 1033 continue; 1034 1035 len += strlen(val_to_name[start]); 1036 if (range > 2) { 1037 len += strlen(val_to_name[i-1]) + strlen("(range ) "); 1038 } else if (range == 2) { 1039 len += strlen(val_to_name[i-1]) + 2; 1040 } else if (range == 1) { 1041 len += 1; 1042 } 1043 1044 range = 0; 1045 } 1046 1047 if (len > 0) { 1048 len += 2; /* For '(' and ')'. '\0' overwrites last ' ' */ 1049 } 1050 1051 return len; 1052} 1053 1054static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) 1055{ 1056 struct ebitmap_node *node; 1057 uint32_t i, start, range; 1058 char *catsbuf = NULL, *p; 1059 int len, remaining; 1060 1061 remaining = (int)cats_ebitmap_len(cats, val_to_name); 1062 if (remaining == 0) { 1063 goto exit; 1064 } 1065 catsbuf = malloc(remaining); 1066 if (!catsbuf) { 1067 goto exit; 1068 } 1069 1070 p = catsbuf; 1071 1072 *p++ = '('; 1073 remaining--; 1074 1075 range = 0; 1076 ebitmap_for_each_positive_bit(cats, node, i) { 1077 if (range == 0) 1078 start = i; 1079 1080 range++; 1081 1082 if (ebitmap_get_bit(cats, i+1)) 1083 continue; 1084 1085 if (range > 1) { 1086 if (range == 2) { 1087 len = snprintf(p, remaining, "%s %s ", 1088 val_to_name[start], 1089 val_to_name[i]); 1090 } else { 1091 len = snprintf(p, remaining, "(range %s %s) ", 1092 val_to_name[start], 1093 val_to_name[i]); 1094 } 1095 } else { 1096 len = snprintf(p, remaining, "%s ", val_to_name[start]); 1097 } 1098 if (len < 0 || len >= remaining) { 1099 goto exit; 1100 } 1101 p += len; 1102 remaining -= len; 1103 1104 range = 0; 1105 } 1106 1107 *(p-1) = ')'; /* Remove trailing ' ' */ 1108 *p = '\0'; 1109 1110 return catsbuf; 1111 1112exit: 1113 free(catsbuf); 1114 return NULL; 1115} 1116 1117static int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pdb) 1118{ 1119 level_datum_t *level; 1120 char *name, *cats; 1121 unsigned i; 1122 int rc = 0; 1123 1124 /* sensitivities */ 1125 for (i=0; i < pdb->p_levels.nprim; i++) { 1126 name = pdb->p_sens_val_to_name[i]; 1127 if (!name) continue; 1128 level = hashtab_search(pdb->p_levels.table, name); 1129 if (!level) { 1130 rc = -1; 1131 goto exit; 1132 } 1133 if (level->isalias) continue; 1134 1135 if (!ebitmap_is_empty(&level->level->cat)) { 1136 cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name); 1137 sepol_printf(out, "(sensitivitycategory %s %s)\n", name, cats); 1138 free(cats); 1139 } 1140 } 1141 1142exit: 1143 if (rc != 0) { 1144 sepol_log_err("Error writing sensitivitycategory rules to CIL\n"); 1145 } 1146 1147 return rc; 1148} 1149 1150static int write_mls_rules_to_cil(FILE *out, struct policydb *pdb) 1151{ 1152 int rc = 0; 1153 1154 if (!pdb->mls) { 1155 sepol_printf(out, "(mls false)\n"); 1156 /* CIL requires MLS, even if the kernel binary won't have it */ 1157 write_default_mls_level(out); 1158 return 0; 1159 } 1160 1161 sepol_printf(out, "(mls true)\n"); 1162 1163 rc = write_sensitivity_rules_to_cil(out, pdb); 1164 if (rc != 0) { 1165 goto exit; 1166 } 1167 1168 rc = write_category_rules_to_cil(out, pdb); 1169 if (rc != 0) { 1170 goto exit; 1171 } 1172 1173 rc = write_sensitivitycategory_rules_to_cil(out, pdb); 1174 if (rc != 0) { 1175 goto exit; 1176 } 1177 1178exit: 1179 if (rc != 0) { 1180 sepol_log_err("Error writing mls rules to CIL\n"); 1181 } 1182 1183 return rc; 1184} 1185 1186static int write_polcap_rules_to_cil(FILE *out, struct policydb *pdb) 1187{ 1188 struct strs *strs; 1189 struct ebitmap_node *node; 1190 const char *name; 1191 uint32_t i; 1192 int rc = 0; 1193 1194 rc = strs_init(&strs, 32); 1195 if (rc != 0) { 1196 goto exit; 1197 } 1198 1199 ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) { 1200 name = sepol_polcap_getname(i); 1201 if (name == NULL) { 1202 sepol_log_err("Unknown policy capability id: %i", i); 1203 rc = -1; 1204 goto exit; 1205 } 1206 1207 rc = strs_create_and_add(strs, "(policycap %s)", 1, name); 1208 if (rc != 0) { 1209 goto exit; 1210 } 1211 } 1212 1213 strs_sort(strs); 1214 strs_write_each(strs, out); 1215 1216exit: 1217 strs_free_all(strs); 1218 strs_destroy(&strs); 1219 1220 if (rc != 0) { 1221 sepol_log_err("Error writing polcap rules to CIL\n"); 1222 } 1223 1224 return rc; 1225} 1226 1227static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb) 1228{ 1229 type_datum_t *type; 1230 char *name; 1231 struct strs *strs; 1232 unsigned i, num; 1233 int rc = 0; 1234 1235 rc = strs_init(&strs, pdb->p_types.nprim); 1236 if (rc != 0) { 1237 goto exit; 1238 } 1239 1240 for (i=0; i < pdb->p_types.nprim; i++) { 1241 type = pdb->type_val_to_struct[i]; 1242 if (type && type->flavor == TYPE_ATTRIB) { 1243 rc = strs_add(strs, pdb->p_type_val_to_name[i]); 1244 if (rc != 0) { 1245 goto exit; 1246 } 1247 } 1248 } 1249 1250 strs_sort(strs); 1251 1252 num = strs_num_items(strs); 1253 for (i = 0; i < num; i++) { 1254 name = strs_read_at_index(strs, i); 1255 if (!name) { 1256 rc = -1; 1257 goto exit; 1258 } 1259 sepol_printf(out, "(typeattribute %s)\n", name); 1260 } 1261 1262exit: 1263 strs_destroy(&strs); 1264 1265 if (rc != 0) { 1266 sepol_log_err("Error writing typeattribute rules to CIL\n"); 1267 } 1268 1269 return rc; 1270} 1271 1272static int write_role_attributes_to_cil(FILE *out, struct policydb *pdb) 1273{ 1274 role_datum_t *role; 1275 char *name; 1276 struct strs *strs; 1277 unsigned i, num; 1278 int rc = 0; 1279 1280 rc = strs_init(&strs, pdb->p_roles.nprim); 1281 if (rc != 0) { 1282 goto exit; 1283 } 1284 1285 for (i=0; i < pdb->p_roles.nprim; i++) { 1286 role = pdb->role_val_to_struct[i]; 1287 if (role && role->flavor == ROLE_ATTRIB) { 1288 rc = strs_add(strs, pdb->p_role_val_to_name[i]); 1289 if (rc != 0) { 1290 goto exit; 1291 } 1292 } 1293 } 1294 1295 strs_sort(strs); 1296 1297 num = strs_num_items(strs); 1298 for (i=0; i<num; i++) { 1299 name = strs_read_at_index(strs, i); 1300 if (!name) { 1301 rc = -1; 1302 goto exit; 1303 } 1304 sepol_printf(out, "(roleattribute %s)\n", name); 1305 } 1306 1307exit: 1308 strs_destroy(&strs); 1309 1310 if (rc != 0) { 1311 sepol_log_err("Error writing roleattribute rules to CIL\n"); 1312 } 1313 1314 return rc; 1315} 1316 1317static int map_boolean_to_strs(char *key, void *data, void *args) 1318{ 1319 struct strs *strs = (struct strs *)args; 1320 struct cond_bool_datum *boolean = data; 1321 const char *value; 1322 1323 value = boolean->state ? "true" : "false"; 1324 1325 return strs_create_and_add(strs, "(boolean %s %s)", 2, key, value); 1326} 1327 1328static int write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb) 1329{ 1330 struct strs *strs; 1331 int rc = 0; 1332 1333 rc = strs_init(&strs, 32); 1334 if (rc != 0) { 1335 goto exit; 1336 } 1337 1338 rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs); 1339 if (rc != 0) { 1340 goto exit; 1341 } 1342 1343 strs_sort(strs); 1344 strs_write_each(strs, out); 1345 1346exit: 1347 strs_free_all(strs); 1348 strs_destroy(&strs); 1349 1350 if (rc != 0) { 1351 sepol_log_err("Error writing boolean declarations to CIL\n"); 1352 } 1353 1354 return rc; 1355} 1356 1357static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb) 1358{ 1359 type_datum_t *type; 1360 struct strs *strs; 1361 char *name; 1362 unsigned i, num; 1363 int rc = 0; 1364 1365 rc = strs_init(&strs, pdb->p_types.nprim); 1366 if (rc != 0) { 1367 goto exit; 1368 } 1369 1370 for (i=0; i < pdb->p_types.nprim; i++) { 1371 type = pdb->type_val_to_struct[i]; 1372 if (type && type->flavor == TYPE_TYPE && type->primary) { 1373 rc = strs_add(strs, pdb->p_type_val_to_name[i]); 1374 if (rc != 0) { 1375 goto exit; 1376 } 1377 } 1378 } 1379 1380 strs_sort(strs); 1381 1382 num = strs_num_items(strs); 1383 for (i=0; i<num; i++) { 1384 name = strs_read_at_index(strs, i); 1385 if (!name) { 1386 rc = -1; 1387 goto exit; 1388 } 1389 sepol_printf(out, "(type %s)\n", name); 1390 } 1391 1392exit: 1393 strs_destroy(&strs); 1394 1395 if (rc != 0) { 1396 sepol_log_err("Error writing type declarations to CIL\n"); 1397 } 1398 1399 return rc; 1400} 1401 1402static int map_count_type_aliases(__attribute__((unused)) char *key, void *data, void *args) 1403{ 1404 type_datum_t *datum = data; 1405 unsigned *count = args; 1406 1407 if (datum->primary == 0 && datum->flavor == TYPE_TYPE) 1408 (*count)++; 1409 1410 return SEPOL_OK; 1411} 1412 1413static int map_type_aliases_to_strs(char *key, void *data, void *args) 1414{ 1415 type_datum_t *datum = data; 1416 struct strs *strs = args; 1417 int rc = 0; 1418 1419 if (datum->primary == 0 && datum->flavor == TYPE_TYPE) 1420 rc = strs_add(strs, key); 1421 1422 return rc; 1423} 1424 1425static int write_type_alias_rules_to_cil(FILE *out, struct policydb *pdb) 1426{ 1427 type_datum_t *alias; 1428 struct strs *strs; 1429 char *name; 1430 char *type; 1431 unsigned i, num = 0; 1432 int rc = 0; 1433 1434 rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num); 1435 if (rc != 0) { 1436 goto exit; 1437 } 1438 1439 rc = strs_init(&strs, num); 1440 if (rc != 0) { 1441 goto exit; 1442 } 1443 1444 rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs); 1445 if (rc != 0) { 1446 goto exit; 1447 } 1448 1449 strs_sort(strs); 1450 1451 for (i=0; i<num; i++) { 1452 name = strs_read_at_index(strs, i); 1453 if (!name) { 1454 rc = -1; 1455 goto exit; 1456 } 1457 sepol_printf(out, "(typealias %s)\n", name); 1458 } 1459 1460 for (i=0; i<num; i++) { 1461 name = strs_read_at_index(strs, i); 1462 if (!name) { 1463 rc = -1; 1464 goto exit; 1465 } 1466 alias = hashtab_search(pdb->p_types.table, name); 1467 if (!alias) { 1468 rc = -1; 1469 goto exit; 1470 } 1471 type = pdb->p_type_val_to_name[alias->s.value - 1]; 1472 sepol_printf(out, "(typealiasactual %s %s)\n", name, type); 1473 } 1474 1475exit: 1476 strs_destroy(&strs); 1477 1478 if (rc != 0) { 1479 sepol_log_err("Error writing type alias rules to CIL\n"); 1480 } 1481 1482 return rc; 1483} 1484 1485static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb) 1486{ 1487 type_datum_t *type; 1488 struct strs *strs; 1489 char *parent; 1490 char *child; 1491 unsigned i, num; 1492 int rc = 0; 1493 1494 rc = strs_init(&strs, pdb->p_types.nprim); 1495 if (rc != 0) { 1496 goto exit; 1497 } 1498 1499 for (i=0; i < pdb->p_types.nprim; i++) { 1500 type = pdb->type_val_to_struct[i]; 1501 if (type && type->flavor == TYPE_TYPE) { 1502 if (type->bounds > 0) { 1503 rc = strs_add(strs, pdb->p_type_val_to_name[i]); 1504 if (rc != 0) { 1505 goto exit; 1506 } 1507 } 1508 } 1509 } 1510 1511 strs_sort(strs); 1512 1513 num = strs_num_items(strs); 1514 for (i=0; i<num; i++) { 1515 child = strs_read_at_index(strs, i); 1516 if (!child) { 1517 rc = -1; 1518 goto exit; 1519 } 1520 type = hashtab_search(pdb->p_types.table, child); 1521 if (!type) { 1522 rc = -1; 1523 goto exit; 1524 } 1525 parent = pdb->p_type_val_to_name[type->bounds - 1]; 1526 sepol_printf(out, "(typebounds %s %s)\n", parent, child); 1527 } 1528 1529exit: 1530 strs_destroy(&strs); 1531 1532 if (rc != 0) { 1533 sepol_log_err("Error writing type bounds rules to CIL\n"); 1534 } 1535 1536 return rc; 1537} 1538 1539static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb) 1540{ 1541 type_datum_t *attr; 1542 struct strs *strs; 1543 ebitmap_t *typemap; 1544 char *name, *types; 1545 unsigned i; 1546 int rc; 1547 1548 rc = strs_init(&strs, pdb->p_types.nprim); 1549 if (rc != 0) { 1550 goto exit; 1551 } 1552 1553 for (i=0; i < pdb->p_types.nprim; i++) { 1554 attr = pdb->type_val_to_struct[i]; 1555 if (!attr || attr->flavor != TYPE_ATTRIB) continue; 1556 name = pdb->p_type_val_to_name[i]; 1557 typemap = &pdb->attr_type_map[i]; 1558 if (ebitmap_is_empty(typemap)) continue; 1559 types = ebitmap_to_str(typemap, pdb->p_type_val_to_name, 1); 1560 if (!types) { 1561 rc = -1; 1562 goto exit; 1563 } 1564 1565 rc = strs_create_and_add(strs, "(typeattributeset %s (%s))", 1566 2, name, types); 1567 free(types); 1568 if (rc != 0) { 1569 goto exit; 1570 } 1571 } 1572 1573 strs_sort(strs); 1574 strs_write_each(strs, out); 1575 1576exit: 1577 strs_free_all(strs); 1578 strs_destroy(&strs); 1579 1580 if (rc != 0) { 1581 sepol_log_err("Error writing typeattributeset rules to CIL\n"); 1582 } 1583 1584 return rc; 1585} 1586 1587static int write_type_permissive_rules_to_cil(FILE *out, struct policydb *pdb) 1588{ 1589 struct strs *strs; 1590 char *name; 1591 struct ebitmap_node *node; 1592 unsigned i, num; 1593 int rc = 0; 1594 1595 rc = strs_init(&strs, pdb->p_types.nprim); 1596 if (rc != 0) { 1597 goto exit; 1598 } 1599 1600 ebitmap_for_each_positive_bit(&pdb->permissive_map, node, i) { 1601 rc = strs_add(strs, pdb->p_type_val_to_name[i-1]); 1602 if (rc != 0) { 1603 goto exit; 1604 } 1605 } 1606 1607 strs_sort(strs); 1608 1609 num = strs_num_items(strs); 1610 for (i=0; i<num; i++) { 1611 name = strs_read_at_index(strs, i); 1612 if (!name) { 1613 rc = -1; 1614 goto exit; 1615 } 1616 sepol_printf(out, "(typepermissive %s)\n", name); 1617 } 1618 1619exit: 1620 strs_destroy(&strs); 1621 1622 if (rc != 0) { 1623 sepol_log_err("Error writing typepermissive rules to CIL\n"); 1624 } 1625 1626 return rc; 1627} 1628 1629#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) 1630 1631static char *xperms_to_str(avtab_extended_perms_t *xperms) 1632{ 1633 uint16_t value; 1634 uint16_t low_bit; 1635 uint16_t low_value; 1636 unsigned int bit; 1637 unsigned int in_range = 0; 1638 static char xpermsbuf[2048]; 1639 char *p; 1640 int len, remaining; 1641 1642 p = xpermsbuf; 1643 remaining = sizeof(xpermsbuf); 1644 1645 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) 1646 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) { 1647 return NULL; 1648 } 1649 1650 for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { 1651 len = 0; 1652 1653 if (!xperm_test(bit, xperms->perms)) 1654 continue; 1655 1656 if (in_range && next_bit_in_range(bit, xperms->perms)) { 1657 /* continue until high value found */ 1658 continue; 1659 } else if (next_bit_in_range(bit, xperms->perms)) { 1660 /* low value */ 1661 low_bit = bit; 1662 in_range = 1; 1663 continue; 1664 } 1665 1666 if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) { 1667 value = xperms->driver<<8 | bit; 1668 if (in_range) { 1669 low_value = xperms->driver<<8 | low_bit; 1670 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value); 1671 in_range = 0; 1672 } else { 1673 len = snprintf(p, remaining, " 0x%hx", value); 1674 } 1675 } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { 1676 value = bit << 8; 1677 if (in_range) { 1678 low_value = low_bit << 8; 1679 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff)); 1680 in_range = 0; 1681 } else { 1682 len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff)); 1683 } 1684 1685 } 1686 if (len < 0 || len >= remaining) { 1687 return NULL; 1688 } 1689 p += len; 1690 remaining -= len; 1691 } 1692 1693 if (remaining < 2) { 1694 return NULL; 1695 } 1696 1697 xpermsbuf[0] = '('; 1698 *p++ = ')'; 1699 *p = '\0'; 1700 1701 return xpermsbuf; 1702} 1703 1704static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum) 1705{ 1706 uint32_t data = datum->data; 1707 type_datum_t *type; 1708 const char *flavor, *tgt; 1709 char *src, *class, *perms, *new; 1710 char *rule = NULL; 1711 1712 switch (0xFFF & key->specified) { 1713 case AVTAB_ALLOWED: 1714 flavor = "allow"; 1715 break; 1716 case AVTAB_AUDITALLOW: 1717 flavor = "auditallow"; 1718 break; 1719 case AVTAB_AUDITDENY: 1720 flavor = "dontaudit"; 1721 data = ~data; 1722 break; 1723 case AVTAB_XPERMS_ALLOWED: 1724 flavor = "allowx"; 1725 break; 1726 case AVTAB_XPERMS_AUDITALLOW: 1727 flavor = "auditallowx"; 1728 break; 1729 case AVTAB_XPERMS_DONTAUDIT: 1730 flavor = "dontauditx"; 1731 break; 1732 case AVTAB_TRANSITION: 1733 flavor = "typetransition"; 1734 break; 1735 case AVTAB_MEMBER: 1736 flavor = "typemember"; 1737 break; 1738 case AVTAB_CHANGE: 1739 flavor = "typechange"; 1740 break; 1741 default: 1742 sepol_log_err("Unknown avtab type: %i", key->specified); 1743 goto exit; 1744 } 1745 1746 src = pdb->p_type_val_to_name[key->source_type - 1]; 1747 tgt = pdb->p_type_val_to_name[key->target_type - 1]; 1748 if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) { 1749 type = pdb->type_val_to_struct[key->source_type - 1]; 1750 if (type->flavor != TYPE_ATTRIB) { 1751 tgt = "self"; 1752 } 1753 } 1754 class = pdb->p_class_val_to_name[key->target_class - 1]; 1755 1756 if (key->specified & AVTAB_AV) { 1757 perms = sepol_av_to_string(pdb, key->target_class, data); 1758 if (perms == NULL) { 1759 sepol_log_err("Failed to generate permission string"); 1760 goto exit; 1761 } 1762 rule = create_str("(%s %s %s (%s (%s)))", 5, 1763 flavor, src, tgt, class, perms+1); 1764 } else if (key->specified & AVTAB_XPERMS) { 1765 perms = xperms_to_str(datum->xperms); 1766 if (perms == NULL) { 1767 sepol_log_err("Failed to generate extended permission string"); 1768 goto exit; 1769 } 1770 1771 rule = create_str("(%s %s %s (%s %s (%s)))", 6, 1772 flavor, src, tgt, "ioctl", class, perms); 1773 } else { 1774 new = pdb->p_type_val_to_name[data - 1]; 1775 1776 rule = create_str("(%s %s %s %s %s)", 5, flavor, src, tgt, class, new); 1777 } 1778 1779 if (!rule) { 1780 goto exit; 1781 } 1782 1783 return rule; 1784 1785exit: 1786 return NULL; 1787} 1788 1789struct map_avtab_args { 1790 struct policydb *pdb; 1791 uint32_t flavor; 1792 struct strs *strs; 1793}; 1794 1795static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args) 1796{ 1797 struct map_avtab_args *map_args = args; 1798 uint32_t flavor = map_args->flavor; 1799 struct policydb *pdb = map_args->pdb; 1800 struct strs *strs = map_args->strs; 1801 char *rule; 1802 int rc = 0; 1803 1804 if (key->specified & flavor) { 1805 rule = avtab_node_to_str(pdb, key, datum); 1806 if (!rule) { 1807 rc = -1; 1808 goto exit; 1809 } 1810 rc = strs_add(strs, rule); 1811 if (rc != 0) { 1812 free(rule); 1813 goto exit; 1814 } 1815 } 1816 1817exit: 1818 return rc; 1819} 1820 1821static int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent) 1822{ 1823 struct map_avtab_args args; 1824 struct strs *strs; 1825 int rc = 0; 1826 1827 rc = strs_init(&strs, 1000); 1828 if (rc != 0) { 1829 goto exit; 1830 } 1831 1832 args.pdb = pdb; 1833 args.flavor = flavor; 1834 args.strs = strs; 1835 1836 rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args); 1837 if (rc != 0) { 1838 goto exit; 1839 } 1840 1841 strs_sort(strs); 1842 strs_write_each_indented(strs, out, indent); 1843 1844exit: 1845 strs_free_all(strs); 1846 strs_destroy(&strs); 1847 1848 return rc; 1849} 1850 1851static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent) 1852{ 1853 unsigned i; 1854 int rc = 0; 1855 1856 for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { 1857 rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent); 1858 if (rc != 0) { 1859 goto exit; 1860 } 1861 } 1862 1863exit: 1864 if (rc != 0) { 1865 sepol_log_err("Error writing avtab rules to CIL\n"); 1866 } 1867 1868 return rc; 1869} 1870 1871struct map_filename_trans_args { 1872 struct policydb *pdb; 1873 struct strs *strs; 1874}; 1875 1876static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) 1877{ 1878 filename_trans_key_t *ft = (filename_trans_key_t *)key; 1879 filename_trans_datum_t *datum = data; 1880 struct map_filename_trans_args *map_args = arg; 1881 struct policydb *pdb = map_args->pdb; 1882 struct strs *strs = map_args->strs; 1883 char *src, *tgt, *class, *filename, *new; 1884 struct ebitmap_node *node; 1885 uint32_t bit; 1886 int rc; 1887 1888 tgt = pdb->p_type_val_to_name[ft->ttype - 1]; 1889 class = pdb->p_class_val_to_name[ft->tclass - 1]; 1890 filename = ft->name; 1891 do { 1892 new = pdb->p_type_val_to_name[datum->otype - 1]; 1893 1894 ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { 1895 src = pdb->p_type_val_to_name[bit]; 1896 rc = strs_create_and_add(strs, 1897 "(typetransition %s %s %s \"%s\" %s)", 1898 5, src, tgt, class, filename, new); 1899 if (rc) 1900 return rc; 1901 } 1902 1903 datum = datum->next; 1904 } while (datum); 1905 1906 return 0; 1907} 1908 1909static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb) 1910{ 1911 struct map_filename_trans_args args; 1912 struct strs *strs; 1913 int rc = 0; 1914 1915 rc = strs_init(&strs, 100); 1916 if (rc != 0) { 1917 goto exit; 1918 } 1919 1920 args.pdb = pdb; 1921 args.strs = strs; 1922 1923 rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args); 1924 if (rc != 0) { 1925 goto exit; 1926 } 1927 1928 strs_sort(strs); 1929 strs_write_each(strs, out); 1930 1931exit: 1932 strs_free_all(strs); 1933 strs_destroy(&strs); 1934 1935 if (rc != 0) { 1936 sepol_log_err("Error writing filename typetransition rules to CIL\n"); 1937 } 1938 1939 return rc; 1940} 1941 1942static char *level_to_str(struct policydb *pdb, struct mls_level *level) 1943{ 1944 ebitmap_t *cats = &level->cat; 1945 char *level_str = NULL; 1946 char *sens_str = pdb->p_sens_val_to_name[level->sens - 1]; 1947 char *cats_str; 1948 1949 if (!ebitmap_is_empty(cats)) { 1950 cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name); 1951 level_str = create_str("(%s %s)", 2, sens_str, cats_str); 1952 free(cats_str); 1953 } else { 1954 level_str = create_str("(%s)", 1, sens_str); 1955 } 1956 1957 return level_str; 1958} 1959 1960static char *range_to_str(struct policydb *pdb, mls_range_t *range) 1961{ 1962 char *low = NULL; 1963 char *high = NULL; 1964 char *range_str = NULL; 1965 1966 low = level_to_str(pdb, &range->level[0]); 1967 if (!low) { 1968 goto exit; 1969 } 1970 1971 high = level_to_str(pdb, &range->level[1]); 1972 if (!high) { 1973 goto exit; 1974 } 1975 1976 range_str = create_str("(%s %s)", 2, low, high); 1977 1978exit: 1979 free(low); 1980 free(high); 1981 1982 return range_str; 1983} 1984 1985struct map_range_trans_args { 1986 struct policydb *pdb; 1987 struct strs *strs; 1988}; 1989 1990static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg) 1991{ 1992 range_trans_t *rt = (range_trans_t *)key; 1993 mls_range_t *mls_range = data; 1994 struct map_range_trans_args *map_args = arg; 1995 struct policydb *pdb = map_args->pdb; 1996 struct strs *strs = map_args->strs; 1997 char *src, *tgt, *class, *range; 1998 int rc; 1999 2000 src = pdb->p_type_val_to_name[rt->source_type - 1]; 2001 tgt = pdb->p_type_val_to_name[rt->target_type - 1]; 2002 class = pdb->p_class_val_to_name[rt->target_class - 1]; 2003 range = range_to_str(pdb, mls_range); 2004 if (!range) { 2005 rc = -1; 2006 goto exit; 2007 } 2008 2009 rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)", 4, 2010 src, tgt, class, range); 2011 free(range); 2012 if (rc != 0) { 2013 goto exit; 2014 } 2015 2016exit: 2017 return rc; 2018} 2019 2020static int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb) 2021{ 2022 struct map_range_trans_args args; 2023 struct strs *strs; 2024 int rc = 0; 2025 2026 rc = strs_init(&strs, 100); 2027 if (rc != 0) { 2028 goto exit; 2029 } 2030 2031 args.pdb = pdb; 2032 args.strs = strs; 2033 2034 rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args); 2035 if (rc != 0) { 2036 goto exit; 2037 } 2038 2039 strs_sort(strs); 2040 strs_write_each(strs, out); 2041 2042exit: 2043 strs_free_all(strs); 2044 strs_destroy(&strs); 2045 2046 if (rc != 0) { 2047 sepol_log_err("Error writing range transition rules to CIL\n"); 2048 } 2049 2050 return rc; 2051} 2052 2053static int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent) 2054{ 2055 cond_av_list_t *cond_av; 2056 avtab_ptr_t node; 2057 uint32_t flavor; 2058 avtab_key_t *key; 2059 avtab_datum_t *datum; 2060 struct strs *strs; 2061 char *rule; 2062 unsigned i; 2063 int rc; 2064 2065 for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { 2066 flavor = avtab_flavors[i]; 2067 rc = strs_init(&strs, 64); 2068 if (rc != 0) { 2069 goto exit; 2070 } 2071 2072 for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) { 2073 node = cond_av->node; 2074 key = &node->key; 2075 datum = &node->datum; 2076 if (key->specified & flavor) { 2077 rule = avtab_node_to_str(pdb, key, datum); 2078 if (!rule) { 2079 rc = -1; 2080 goto exit; 2081 } 2082 rc = strs_add(strs, rule); 2083 if (rc != 0) { 2084 free(rule); 2085 goto exit; 2086 } 2087 } 2088 } 2089 2090 strs_sort(strs); 2091 strs_write_each_indented(strs, out, indent); 2092 strs_free_all(strs); 2093 strs_destroy(&strs); 2094 } 2095 2096 return 0; 2097 2098exit: 2099 strs_free_all(strs); 2100 strs_destroy(&strs); 2101 return rc; 2102} 2103 2104struct cond_data { 2105 char *expr; 2106 struct cond_node *cond; 2107}; 2108 2109static int cond_node_cmp(const void *a, const void *b) 2110{ 2111 const struct cond_data *aa = a; 2112 const struct cond_data *bb = b; 2113 return strcmp(aa->expr, bb->expr); 2114} 2115 2116static int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb) 2117{ 2118 struct cond_data *cond_data; 2119 char *expr; 2120 struct cond_node *cond; 2121 unsigned i, num = 0; 2122 int rc = 0; 2123 2124 for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { 2125 num++; 2126 } 2127 2128 cond_data = calloc(num, sizeof(struct cond_data)); 2129 if (!cond_data) { 2130 rc = -1; 2131 goto exit; 2132 } 2133 2134 i = 0; 2135 for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { 2136 cond_data[i].cond = cond; 2137 expr = cond_expr_to_str(pdb, cond->expr); 2138 if (!expr) { 2139 num = i; 2140 goto exit; 2141 } 2142 cond_data[i].expr = expr; 2143 i++; 2144 } 2145 2146 qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp); 2147 2148 for (i=0; i<num; i++) { 2149 expr = cond_data[i].expr; 2150 cond = cond_data[i].cond; 2151 2152 sepol_printf(out, "(booleanif %s\n", expr); 2153 2154 if (cond->true_list != NULL) { 2155 sepol_indent(out, 1); 2156 sepol_printf(out, "(true\n"); 2157 rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2); 2158 if (rc != 0) { 2159 goto exit; 2160 } 2161 sepol_indent(out, 1); 2162 sepol_printf(out, ")\n"); 2163 } 2164 2165 if (cond->false_list != NULL) { 2166 sepol_indent(out, 1); 2167 sepol_printf(out, "(false\n"); 2168 rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2); 2169 if (rc != 0) { 2170 goto exit; 2171 } 2172 sepol_indent(out, 1); 2173 sepol_printf(out, ")\n"); 2174 } 2175 sepol_printf(out, ")\n"); 2176 } 2177 2178exit: 2179 if (cond_data) { 2180 for (i=0; i<num; i++) { 2181 free(cond_data[i].expr); 2182 } 2183 free(cond_data); 2184 } 2185 2186 if (rc != 0) { 2187 sepol_log_err("Error writing conditional rules to CIL\n"); 2188 } 2189 2190 return rc; 2191} 2192 2193static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb) 2194{ 2195 struct role_datum *role; 2196 struct strs *strs, *type_strs; 2197 char *name, *parent, *child, *type; 2198 struct ebitmap *types; 2199 struct type_datum *type_datum; 2200 unsigned i, num, j, num_types; 2201 int rc = 0; 2202 2203 rc = strs_init(&strs, pdb->p_roles.nprim); 2204 if (rc != 0) { 2205 goto exit; 2206 } 2207 2208 for (i=0; i < pdb->p_roles.nprim; i++) { 2209 role = pdb->role_val_to_struct[i]; 2210 if (role && role->flavor == ROLE_ROLE) { 2211 rc = strs_add(strs, pdb->p_role_val_to_name[i]); 2212 if (rc != 0) { 2213 goto exit; 2214 } 2215 } 2216 } 2217 2218 strs_sort(strs); 2219 2220 num = strs_num_items(strs); 2221 2222 for (i=0; i<num; i++) { 2223 name = strs_read_at_index(strs, i); 2224 if (!name) { 2225 continue; 2226 } 2227 sepol_printf(out, "(role %s)\n", name); 2228 } 2229 2230 for (i=0; i<num; i++) { 2231 child = strs_read_at_index(strs, i); 2232 if (!child) { 2233 continue; 2234 } 2235 role = hashtab_search(pdb->p_roles.table, child); 2236 if (!role) { 2237 rc = -1; 2238 goto exit; 2239 } 2240 2241 if (role->bounds > 0) { 2242 parent = pdb->p_role_val_to_name[role->bounds - 1]; 2243 sepol_printf(out, "(rolebounds %s %s)\n", parent, child); 2244 } 2245 } 2246 2247 for (i=0; i<num; i++) { 2248 name = strs_read_at_index(strs, i); 2249 if (!name) { 2250 continue; 2251 } 2252 role = hashtab_search(pdb->p_roles.table, name); 2253 if (!role) { 2254 rc = -1; 2255 goto exit; 2256 } 2257 types = &role->types.types; 2258 if (types && !ebitmap_is_empty(types)) { 2259 rc = strs_init(&type_strs, pdb->p_types.nprim); 2260 if (rc != 0) { 2261 goto exit; 2262 } 2263 rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name); 2264 if (rc != 0) { 2265 strs_destroy(&type_strs); 2266 goto exit; 2267 } 2268 strs_sort(type_strs); 2269 2270 num_types = strs_num_items(type_strs); 2271 for (j=0; j<num_types; j++) { 2272 type = strs_read_at_index(type_strs, j); 2273 sepol_printf(out, "(roletype %s %s)\n", name, type); 2274 } 2275 strs_destroy(&type_strs); 2276 } 2277 } 2278 2279 strs_destroy(&strs); 2280 2281 rc = strs_init(&strs, pdb->p_types.nprim); 2282 if (rc != 0) { 2283 goto exit; 2284 } 2285 2286 for (i=0; i < pdb->p_types.nprim; i++) { 2287 type_datum = pdb->type_val_to_struct[i]; 2288 if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) { 2289 rc = strs_add(strs, pdb->p_type_val_to_name[i]); 2290 if (rc != 0) { 2291 goto exit; 2292 } 2293 } 2294 } 2295 2296 strs_sort(strs); 2297 2298 num = strs_num_items(strs); 2299 2300 for (i=0; i<num; i++) { 2301 name = strs_read_at_index(strs, i); 2302 if (!name) { 2303 continue; 2304 } 2305 sepol_printf(out, "(roletype %s %s)\n", DEFAULT_OBJECT, name); 2306 } 2307 2308exit: 2309 strs_destroy(&strs); 2310 2311 if (rc != 0) { 2312 sepol_log_err("Error writing role declarations to CIL\n"); 2313 } 2314 2315 return rc; 2316} 2317 2318static int write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb) 2319{ 2320 role_trans_t *curr = pdb->role_tr; 2321 struct strs *strs; 2322 char *role, *type, *class, *new; 2323 int rc = 0; 2324 2325 rc = strs_init(&strs, 32); 2326 if (rc != 0) { 2327 goto exit; 2328 } 2329 2330 while (curr) { 2331 role = pdb->p_role_val_to_name[curr->role - 1]; 2332 type = pdb->p_type_val_to_name[curr->type - 1]; 2333 class = pdb->p_class_val_to_name[curr->tclass - 1]; 2334 new = pdb->p_role_val_to_name[curr->new_role - 1]; 2335 2336 rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)", 4, 2337 role, type, class, new); 2338 if (rc != 0) { 2339 goto exit; 2340 } 2341 2342 curr = curr->next; 2343 } 2344 2345 strs_sort(strs); 2346 strs_write_each(strs, out); 2347 2348exit: 2349 strs_free_all(strs); 2350 strs_destroy(&strs); 2351 2352 if (rc != 0) { 2353 sepol_log_err("Error writing role transition rules to CIL\n"); 2354 } 2355 2356 return rc; 2357} 2358 2359static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb) 2360{ 2361 role_allow_t *curr = pdb->role_allow; 2362 struct strs *strs; 2363 char *role, *new; 2364 int rc = 0; 2365 2366 rc = strs_init(&strs, 32); 2367 if (rc != 0) { 2368 goto exit; 2369 } 2370 2371 while (curr) { 2372 role = pdb->p_role_val_to_name[curr->role - 1]; 2373 new = pdb->p_role_val_to_name[curr->new_role - 1]; 2374 2375 rc = strs_create_and_add(strs, "(roleallow %s %s)", 2, role, new); 2376 if (rc != 0) { 2377 goto exit; 2378 } 2379 2380 curr = curr->next; 2381 } 2382 2383 strs_sort(strs); 2384 strs_write_each(strs, out); 2385 2386exit: 2387 strs_free_all(strs); 2388 strs_destroy(&strs); 2389 2390 if (rc != 0) { 2391 sepol_log_err("Error writing role allow rules to CIL\n"); 2392 } 2393 2394 return rc; 2395} 2396 2397static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb) 2398{ 2399 struct user_datum *user; 2400 struct strs *strs, *role_strs; 2401 char *name, *role, *level, *range; 2402 struct ebitmap *roles; 2403 unsigned i, j, num, num_roles; 2404 int rc = 0; 2405 2406 rc = strs_init(&strs, pdb->p_users.nprim); 2407 if (rc != 0) { 2408 goto exit; 2409 } 2410 2411 for (i=0; i < pdb->p_users.nprim; i++) { 2412 if (!pdb->p_user_val_to_name[i]) continue; 2413 rc = strs_add(strs, pdb->p_user_val_to_name[i]); 2414 if (rc != 0) { 2415 goto exit; 2416 } 2417 } 2418 2419 strs_sort(strs); 2420 2421 num = strs_num_items(strs); 2422 2423 for (i=0; i<num; i++) { 2424 name = strs_read_at_index(strs, i); 2425 if (!name) { 2426 continue; 2427 } 2428 sepol_printf(out, "(user %s)\n", name); 2429 } 2430 2431 for (i=0; i<num; i++) { 2432 name = strs_read_at_index(strs, i); 2433 if (!name) { 2434 continue; 2435 } 2436 2437 user = hashtab_search(pdb->p_users.table, name); 2438 if (!user) { 2439 rc = -1; 2440 goto exit; 2441 } 2442 2443 roles = &user->roles.roles; 2444 if (roles && !ebitmap_is_empty(roles)) { 2445 rc = strs_init(&role_strs, pdb->p_roles.nprim); 2446 if (rc != 0) { 2447 goto exit; 2448 } 2449 rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name); 2450 if (rc != 0) { 2451 strs_destroy(&role_strs); 2452 goto exit; 2453 } 2454 2455 rc = strs_add(role_strs, (char *)DEFAULT_OBJECT); 2456 if (rc != 0) { 2457 strs_destroy(&role_strs); 2458 goto exit; 2459 } 2460 2461 strs_sort(role_strs); 2462 2463 num_roles = strs_num_items(role_strs); 2464 for (j=0; j<num_roles; j++) { 2465 role = strs_read_at_index(role_strs, j); 2466 sepol_printf(out, "(userrole %s %s)\n", name, role); 2467 } 2468 strs_destroy(&role_strs); 2469 } 2470 } 2471 2472 for (i=0; i<num; i++) { 2473 name = strs_read_at_index(strs, i); 2474 if (!name) { 2475 continue; 2476 } 2477 2478 user = hashtab_search(pdb->p_users.table, name); 2479 if (!user) { 2480 rc = -1; 2481 goto exit; 2482 } 2483 2484 sepol_printf(out, "(userlevel %s ", name); 2485 2486 if (pdb->mls) { 2487 level = level_to_str(pdb, &user->exp_dfltlevel); 2488 if (!level) { 2489 rc = -1; 2490 goto exit; 2491 } 2492 sepol_printf(out, "%s", level); 2493 free(level); 2494 } else { 2495 sepol_printf(out, "%s", DEFAULT_LEVEL); 2496 } 2497 sepol_printf(out, ")\n"); 2498 } 2499 2500 for (i=0; i<num; i++) { 2501 name = strs_read_at_index(strs, i); 2502 if (!name) { 2503 continue; 2504 } 2505 2506 user = hashtab_search(pdb->p_users.table, name); 2507 if (!user) { 2508 rc = -1; 2509 goto exit; 2510 } 2511 2512 sepol_printf(out, "(userrange %s ", name); 2513 if (pdb->mls) { 2514 range = range_to_str(pdb, &user->exp_range); 2515 if (!range) { 2516 rc = -1; 2517 goto exit; 2518 } 2519 sepol_printf(out, "%s", range); 2520 free(range); 2521 } else { 2522 sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL); 2523 } 2524 sepol_printf(out, ")\n"); 2525 } 2526 2527exit: 2528 if (strs) 2529 strs_destroy(&strs); 2530 2531 if (rc != 0) { 2532 sepol_log_err("Error writing user declarations to CIL\n"); 2533 } 2534 2535 return rc; 2536} 2537 2538static char *context_to_str(struct policydb *pdb, struct context_struct *con) 2539{ 2540 char *user, *role, *type, *range; 2541 char *ctx = NULL; 2542 2543 user = pdb->p_user_val_to_name[con->user - 1]; 2544 role = pdb->p_role_val_to_name[con->role - 1]; 2545 type = pdb->p_type_val_to_name[con->type - 1]; 2546 2547 if (pdb->mls) { 2548 range = range_to_str(pdb, &con->range); 2549 } else { 2550 range = create_str("(%s %s)", 2, DEFAULT_LEVEL, DEFAULT_LEVEL); 2551 } 2552 if (!range) { 2553 goto exit; 2554 } 2555 2556 ctx = create_str("(%s %s %s %s)", 4, user, role, type, range); 2557 free(range); 2558 2559exit: 2560 return ctx; 2561} 2562 2563static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids) 2564{ 2565 struct ocontext *isid; 2566 struct strs *strs; 2567 char *sid; 2568 char unknown[18]; 2569 char *ctx, *rule; 2570 unsigned i; 2571 int rc = -1; 2572 2573 rc = strs_init(&strs, 32); 2574 if (rc != 0) { 2575 goto exit; 2576 } 2577 2578 for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) { 2579 i = isid->sid[0]; 2580 if (i < num_sids) { 2581 sid = (char *)sid_to_str[i]; 2582 } else { 2583 snprintf(unknown, 18, "%s%u", "UNKNOWN", i); 2584 sid = unknown; 2585 } 2586 2587 ctx = context_to_str(pdb, &isid->context[0]); 2588 if (!ctx) { 2589 rc = -1; 2590 goto exit; 2591 } 2592 2593 rule = create_str("(sidcontext %s %s)", 2, sid, ctx); 2594 free(ctx); 2595 if (!rule) { 2596 rc = -1; 2597 goto exit; 2598 } 2599 2600 rc = strs_add_at_index(strs, rule, i); 2601 if (rc != 0) { 2602 free(rule); 2603 goto exit; 2604 } 2605 } 2606 2607 strs_write_each(strs, out); 2608 2609exit: 2610 strs_free_all(strs); 2611 strs_destroy(&strs); 2612 2613 if (rc != 0) { 2614 sepol_log_err("Error writing sidcontext rules to CIL\n"); 2615 } 2616 2617 return rc; 2618} 2619 2620static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb) 2621{ 2622 return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str, 2623 SELINUX_SID_SZ); 2624} 2625 2626static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb) 2627{ 2628 struct ocontext *fsuse; 2629 const char *behavior; 2630 char *name, *ctx; 2631 int rc = 0; 2632 2633 for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) { 2634 switch (fsuse->v.behavior) { 2635 case SECURITY_FS_USE_XATTR: behavior = "xattr"; break; 2636 case SECURITY_FS_USE_TRANS: behavior = "trans"; break; 2637 case SECURITY_FS_USE_TASK: behavior = "task"; break; 2638 default: 2639 sepol_log_err("Unknown fsuse behavior: %i", fsuse->v.behavior); 2640 rc = -1; 2641 goto exit; 2642 } 2643 2644 name = fsuse->u.name; 2645 ctx = context_to_str(pdb, &fsuse->context[0]); 2646 if (!ctx) { 2647 rc = -1; 2648 goto exit; 2649 } 2650 2651 sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx); 2652 2653 free(ctx); 2654 } 2655 2656exit: 2657 if (rc != 0) { 2658 sepol_log_err("Error writing fsuse rules to CIL\n"); 2659 } 2660 2661 return rc; 2662} 2663 2664static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb) 2665{ 2666 struct genfs *genfs; 2667 struct ocontext *ocon; 2668 struct strs *strs; 2669 char *fstype, *name, *ctx; 2670 uint32_t sclass; 2671 const char *file_type; 2672 int rc; 2673 2674 rc = strs_init(&strs, 32); 2675 if (rc != 0) { 2676 goto exit; 2677 } 2678 2679 for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { 2680 for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { 2681 fstype = genfs->fstype; 2682 name = ocon->u.name; 2683 2684 sclass = ocon->v.sclass; 2685 file_type = NULL; 2686 if (sclass) { 2687 const char *class_name = pdb->p_class_val_to_name[sclass-1]; 2688 if (strcmp(class_name, "file") == 0) { 2689 file_type = "file"; 2690 } else if (strcmp(class_name, "dir") == 0) { 2691 file_type = "dir"; 2692 } else if (strcmp(class_name, "chr_file") == 0) { 2693 file_type = "char"; 2694 } else if (strcmp(class_name, "blk_file") == 0) { 2695 file_type = "block"; 2696 } else if (strcmp(class_name, "sock_file") == 0) { 2697 file_type = "socket"; 2698 } else if (strcmp(class_name, "fifo_file") == 0) { 2699 file_type = "pipe"; 2700 } else if (strcmp(class_name, "lnk_file") == 0) { 2701 file_type = "symlink"; 2702 } else { 2703 rc = -1; 2704 goto exit; 2705 } 2706 } 2707 2708 ctx = context_to_str(pdb, &ocon->context[0]); 2709 if (!ctx) { 2710 rc = -1; 2711 goto exit; 2712 } 2713 2714 if (file_type) { 2715 rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)", 4, 2716 fstype, name, file_type, ctx); 2717 } else { 2718 rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3, 2719 fstype, name, ctx); 2720 } 2721 free(ctx); 2722 if (rc != 0) { 2723 goto exit; 2724 } 2725 } 2726 } 2727 2728 strs_sort(strs); 2729 strs_write_each(strs, out); 2730 2731exit: 2732 strs_free_all(strs); 2733 strs_destroy(&strs); 2734 2735 if (rc != 0) { 2736 sepol_log_err("Error writing genfscon rules to CIL\n"); 2737 } 2738 2739 return rc; 2740} 2741 2742static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb) 2743{ 2744 struct ocontext *portcon; 2745 const char *protocol; 2746 uint16_t low; 2747 uint16_t high; 2748 char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */ 2749 char *ctx; 2750 int rc = 0; 2751 2752 for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) { 2753 switch (portcon->u.port.protocol) { 2754 case IPPROTO_TCP: protocol = "tcp"; break; 2755 case IPPROTO_UDP: protocol = "udp"; break; 2756 case IPPROTO_DCCP: protocol = "dccp"; break; 2757 case IPPROTO_SCTP: protocol = "sctp"; break; 2758 default: 2759 sepol_log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); 2760 rc = -1; 2761 goto exit; 2762 } 2763 2764 low = portcon->u.port.low_port; 2765 high = portcon->u.port.high_port; 2766 if (low == high) { 2767 rc = snprintf(low_high_str, 44, "%u", low); 2768 } else { 2769 rc = snprintf(low_high_str, 44, "(%u %u)", low, high); 2770 } 2771 if (rc < 0 || rc >= 44) { 2772 rc = -1; 2773 goto exit; 2774 } 2775 2776 ctx = context_to_str(pdb, &portcon->context[0]); 2777 if (!ctx) { 2778 rc = -1; 2779 goto exit; 2780 } 2781 2782 sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx); 2783 2784 free(ctx); 2785 } 2786 2787 rc = 0; 2788 2789exit: 2790 if (rc != 0) { 2791 sepol_log_err("Error writing portcon rules to CIL\n"); 2792 } 2793 2794 return rc; 2795} 2796 2797static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb) 2798{ 2799 struct ocontext *netif; 2800 char *name, *ctx1, *ctx2; 2801 int rc = 0; 2802 2803 for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) { 2804 name = netif->u.name; 2805 ctx1 = context_to_str(pdb, &netif->context[0]); 2806 if (!ctx1) { 2807 rc = -1; 2808 goto exit; 2809 } 2810 ctx2 = context_to_str(pdb, &netif->context[1]); 2811 if (!ctx2) { 2812 free(ctx1); 2813 rc = -1; 2814 goto exit; 2815 } 2816 2817 sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2); 2818 2819 free(ctx1); 2820 free(ctx2); 2821 } 2822 2823exit: 2824 if (rc != 0) { 2825 sepol_log_err("Error writing netifcon rules to CIL\n"); 2826 } 2827 2828 return rc; 2829} 2830 2831static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb) 2832{ 2833 struct ocontext *node; 2834 char addr[INET_ADDRSTRLEN]; 2835 char mask[INET_ADDRSTRLEN]; 2836 char *ctx; 2837 int rc = 0; 2838 2839 for (node = pdb->ocontexts[4]; node != NULL; node = node->next) { 2840 if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { 2841 sepol_log_err("Nodecon address is invalid: %m"); 2842 rc = -1; 2843 goto exit; 2844 } 2845 2846 if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { 2847 sepol_log_err("Nodecon mask is invalid: %m"); 2848 rc = -1; 2849 goto exit; 2850 } 2851 2852 ctx = context_to_str(pdb, &node->context[0]); 2853 if (!ctx) { 2854 rc = -1; 2855 goto exit; 2856 } 2857 2858 sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx); 2859 2860 free(ctx); 2861 } 2862 2863exit: 2864 if (rc != 0) { 2865 sepol_log_err("Error writing nodecon rules to CIL\n"); 2866 } 2867 2868 return rc; 2869} 2870 2871static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb) 2872{ 2873 struct ocontext *node; 2874 char addr[INET6_ADDRSTRLEN]; 2875 char mask[INET6_ADDRSTRLEN]; 2876 char *ctx; 2877 int rc = 0; 2878 2879 for (node = pdb->ocontexts[6]; node != NULL; node = node->next) { 2880 if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { 2881 sepol_log_err("Nodecon address is invalid: %m"); 2882 rc = -1; 2883 goto exit; 2884 } 2885 2886 if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { 2887 sepol_log_err("Nodecon mask is invalid: %m"); 2888 rc = -1; 2889 goto exit; 2890 } 2891 2892 ctx = context_to_str(pdb, &node->context[0]); 2893 if (!ctx) { 2894 rc = -1; 2895 goto exit; 2896 } 2897 2898 sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx); 2899 2900 free(ctx); 2901 } 2902 2903exit: 2904 if (rc != 0) { 2905 sepol_log_err("Error writing nodecon rules to CIL\n"); 2906 } 2907 2908 return rc; 2909} 2910 2911static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb) 2912{ 2913 struct ocontext *ibpkeycon; 2914 char subnet_prefix_str[INET6_ADDRSTRLEN]; 2915 struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; 2916 uint16_t low; 2917 uint16_t high; 2918 char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */ 2919 char *ctx; 2920 int rc = 0; 2921 2922 for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL; 2923 ibpkeycon = ibpkeycon->next) { 2924 memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, 2925 sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); 2926 2927 if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, 2928 subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { 2929 sepol_log_err("ibpkeycon subnet_prefix is invalid: %m"); 2930 rc = -1; 2931 goto exit; 2932 } 2933 2934 low = ibpkeycon->u.ibpkey.low_pkey; 2935 high = ibpkeycon->u.ibpkey.high_pkey; 2936 if (low == high) { 2937 rc = snprintf(low_high_str, 44, "%u", low); 2938 } else { 2939 rc = snprintf(low_high_str, 44, "(%u %u)", low, high); 2940 } 2941 if (rc < 0 || rc >= 44) { 2942 rc = -1; 2943 goto exit; 2944 } 2945 2946 ctx = context_to_str(pdb, &ibpkeycon->context[0]); 2947 if (!ctx) { 2948 rc = -1; 2949 goto exit; 2950 } 2951 2952 sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx); 2953 2954 free(ctx); 2955 } 2956 2957 rc = 0; 2958 2959exit: 2960 if (rc != 0) { 2961 sepol_log_err("Error writing ibpkeycon rules to CIL\n"); 2962 } 2963 2964 return rc; 2965} 2966 2967static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb) 2968{ 2969 struct ocontext *ibendportcon; 2970 char port_str[4]; 2971 char *ctx; 2972 int rc = 0; 2973 2974 for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT]; 2975 ibendportcon != NULL; ibendportcon = ibendportcon->next) { 2976 rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port); 2977 if (rc < 0 || rc >= 4) { 2978 rc = -1; 2979 goto exit; 2980 } 2981 2982 ctx = context_to_str(pdb, &ibendportcon->context[0]); 2983 if (!ctx) { 2984 rc = -1; 2985 goto exit; 2986 } 2987 2988 sepol_printf(out, "(ibendportcon %s %s %s)\n", 2989 ibendportcon->u.ibendport.dev_name, port_str, ctx); 2990 2991 free(ctx); 2992 } 2993 2994 rc = 0; 2995 2996exit: 2997 if (rc != 0) { 2998 sepol_log_err("Error writing ibendportcon rules to CIL\n"); 2999 } 3000 3001 return rc; 3002} 3003 3004static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb) 3005{ 3006 return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ); 3007} 3008 3009static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb) 3010{ 3011 struct ocontext *pirq; 3012 char pirq_str[21]; /* 2^64-1 <= 20 digits */ 3013 char *ctx; 3014 int rc = 0; 3015 3016 for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) { 3017 rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq); 3018 if (rc < 0 || rc >= 21) { 3019 rc = -1; 3020 goto exit; 3021 } 3022 3023 ctx = context_to_str(pdb, &pirq->context[0]); 3024 if (!ctx) { 3025 rc = -1; 3026 goto exit; 3027 } 3028 3029 sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx); 3030 3031 free(ctx); 3032 } 3033 3034 rc = 0; 3035 3036exit: 3037 if (rc != 0) { 3038 sepol_log_err("Error writing pirqcon rules to CIL\n"); 3039 } 3040 3041 return rc; 3042} 3043 3044static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb) 3045{ 3046 struct ocontext *ioport; 3047 uint32_t low; 3048 uint32_t high; 3049 char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */ 3050 char *ctx; 3051 int rc = 0; 3052 3053 for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) { 3054 low = ioport->u.ioport.low_ioport; 3055 high = ioport->u.ioport.high_ioport; 3056 if (low == high) { 3057 rc = snprintf(low_high_str, 40, "0x%x", low); 3058 } else { 3059 rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high); 3060 } 3061 if (rc < 0 || rc >= 40) { 3062 rc = -1; 3063 goto exit; 3064 } 3065 3066 ctx = context_to_str(pdb, &ioport->context[0]); 3067 if (!ctx) { 3068 rc = -1; 3069 goto exit; 3070 } 3071 3072 sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx); 3073 3074 free(ctx); 3075 } 3076 3077 rc = 0; 3078 3079exit: 3080 if (rc != 0) { 3081 sepol_log_err("Error writing ioportcon rules to CIL\n"); 3082 } 3083 3084 return rc; 3085} 3086 3087static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb) 3088{ 3089 struct ocontext *iomem; 3090 uint64_t low; 3091 uint64_t high; 3092 char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */ 3093 char *ctx; 3094 int rc = 0; 3095 3096 for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) { 3097 low = iomem->u.iomem.low_iomem; 3098 high = iomem->u.iomem.high_iomem; 3099 if (low == high) { 3100 rc = snprintf(low_high_str, 40, "0x%"PRIx64, low); 3101 } else { 3102 rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high); 3103 } 3104 if (rc < 0 || rc >= 40) { 3105 rc = -1; 3106 goto exit; 3107 } 3108 3109 ctx = context_to_str(pdb, &iomem->context[0]); 3110 if (!ctx) { 3111 rc = -1; 3112 goto exit; 3113 } 3114 3115 sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx); 3116 3117 free(ctx); 3118 } 3119 3120 rc = 0; 3121 3122exit: 3123 if (rc != 0) { 3124 sepol_log_err("Error writing iomemcon rules to CIL\n"); 3125 } 3126 3127 return rc; 3128} 3129 3130static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb) 3131{ 3132 struct ocontext *pcid; 3133 char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */ 3134 char *ctx; 3135 int rc = 0; 3136 3137 for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) { 3138 rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device); 3139 if (rc < 0 || rc >= 20) { 3140 rc = -1; 3141 goto exit; 3142 } 3143 3144 ctx = context_to_str(pdb, &pcid->context[0]); 3145 if (!ctx) { 3146 rc = -1; 3147 goto exit; 3148 } 3149 3150 sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx); 3151 3152 free(ctx); 3153 } 3154 3155 rc = 0; 3156 3157exit: 3158 if (rc != 0) { 3159 sepol_log_err("Error writing pcidevicecon rules to CIL\n"); 3160 } 3161 3162 return rc; 3163} 3164 3165static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb) 3166{ 3167 struct ocontext *dtree; 3168 char *name, *ctx; 3169 int rc = 0; 3170 3171 for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) { 3172 name = dtree->u.name; 3173 ctx = context_to_str(pdb, &dtree->context[0]); 3174 if (!ctx) { 3175 rc = -1; 3176 goto exit; 3177 } 3178 3179 sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx); 3180 3181 free(ctx); 3182 } 3183 3184exit: 3185 if (rc != 0) { 3186 sepol_log_err("Error writing devicetreecon rules to CIL\n"); 3187 } 3188 3189 return rc; 3190} 3191 3192int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb) 3193{ 3194 struct strs *mls_constraints = NULL; 3195 struct strs *non_mls_constraints = NULL; 3196 struct strs *mls_validatetrans = NULL; 3197 struct strs *non_mls_validatetrans = NULL; 3198 int rc = 0; 3199 3200 rc = strs_init(&mls_constraints, 32); 3201 if (rc != 0) { 3202 goto exit; 3203 } 3204 3205 rc = strs_init(&non_mls_constraints, 32); 3206 if (rc != 0) { 3207 goto exit; 3208 } 3209 3210 rc = strs_init(&mls_validatetrans, 32); 3211 if (rc != 0) { 3212 goto exit; 3213 } 3214 3215 rc = strs_init(&non_mls_validatetrans, 32); 3216 if (rc != 0) { 3217 goto exit; 3218 } 3219 3220 if (pdb == NULL) { 3221 sepol_log_err("No policy"); 3222 rc = -1; 3223 goto exit; 3224 } 3225 3226 if (pdb->policy_type != SEPOL_POLICY_KERN) { 3227 sepol_log_err("Policy is not a kernel policy"); 3228 rc = -1; 3229 goto exit; 3230 } 3231 3232 if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) { 3233 /* 3234 * For policy versions between 20 and 23, attributes exist in the policy, 3235 * but only in the type_attr_map. This means that there are gaps in both 3236 * the type_val_to_struct and p_type_val_to_name arrays and policy rules 3237 * can refer to those gaps. 3238 */ 3239 sepol_log_err("Writing policy versions between 20 and 23 as CIL is not supported"); 3240 rc = -1; 3241 goto exit; 3242 } 3243 3244 rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints); 3245 if (rc != 0) { 3246 goto exit; 3247 } 3248 3249 rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans); 3250 if (rc != 0) { 3251 goto exit; 3252 } 3253 3254 rc = write_handle_unknown_to_cil(out, pdb); 3255 if (rc != 0) { 3256 goto exit; 3257 } 3258 3259 rc = write_class_decl_rules_to_cil(out, pdb); 3260 if (rc != 0) { 3261 goto exit; 3262 } 3263 3264 rc = write_sid_decl_rules_to_cil(out, pdb); 3265 if (rc != 0) { 3266 goto exit; 3267 } 3268 3269 rc = write_default_rules_to_cil(out, pdb); 3270 if (rc != 0) { 3271 goto exit; 3272 } 3273 3274 rc = write_mls_rules_to_cil(out, pdb); 3275 if (rc != 0) { 3276 goto exit; 3277 } 3278 3279 strs_write_each(mls_constraints, out); 3280 strs_write_each(mls_validatetrans, out); 3281 3282 rc = write_polcap_rules_to_cil(out, pdb); 3283 if (rc != 0) { 3284 goto exit; 3285 } 3286 3287 rc = write_type_attributes_to_cil(out, pdb); 3288 if (rc != 0) { 3289 goto exit; 3290 } 3291 3292 rc = write_role_attributes_to_cil(out, pdb); 3293 if (rc != 0) { 3294 goto exit; 3295 } 3296 3297 rc = write_boolean_decl_rules_to_cil(out, pdb); 3298 if (rc != 0) { 3299 goto exit; 3300 } 3301 3302 rc = write_type_decl_rules_to_cil(out, pdb); 3303 if (rc != 0) { 3304 goto exit; 3305 } 3306 3307 rc = write_type_alias_rules_to_cil(out, pdb); 3308 if (rc != 0) { 3309 goto exit; 3310 } 3311 3312 rc = write_type_bounds_rules_to_cil(out, pdb); 3313 if (rc != 0) { 3314 goto exit; 3315 } 3316 3317 rc = write_type_attribute_sets_to_cil(out, pdb); 3318 if (rc != 0) { 3319 goto exit; 3320 } 3321 3322 rc = write_type_permissive_rules_to_cil(out, pdb); 3323 if (rc != 0) { 3324 goto exit; 3325 } 3326 3327 rc = write_avtab_to_cil(out, pdb, 0); 3328 if (rc != 0) { 3329 goto exit; 3330 } 3331 3332 rc = write_filename_trans_rules_to_cil(out, pdb); 3333 if (rc != 0) { 3334 goto exit; 3335 } 3336 3337 if (pdb->mls) { 3338 rc = write_range_trans_rules_to_cil(out, pdb); 3339 if (rc != 0) { 3340 goto exit; 3341 } 3342 } 3343 3344 rc = write_cond_nodes_to_cil(out, pdb); 3345 if (rc != 0) { 3346 goto exit; 3347 } 3348 3349 rc = write_role_decl_rules_to_cil(out, pdb); 3350 if (rc != 0) { 3351 goto exit; 3352 } 3353 3354 rc = write_role_transition_rules_to_cil(out, pdb); 3355 if (rc != 0) { 3356 goto exit; 3357 } 3358 3359 rc = write_role_allow_rules_to_cil(out, pdb); 3360 if (rc != 0) { 3361 goto exit; 3362 } 3363 3364 rc = write_user_decl_rules_to_cil(out, pdb); 3365 if (rc != 0) { 3366 goto exit; 3367 } 3368 3369 strs_write_each(non_mls_constraints, out); 3370 strs_write_each(non_mls_validatetrans, out); 3371 3372 rc = sort_ocontexts(pdb); 3373 if (rc != 0) { 3374 goto exit; 3375 } 3376 3377 if (pdb->target_platform == SEPOL_TARGET_SELINUX) { 3378 rc = write_selinux_isid_rules_to_cil(out, pdb); 3379 if (rc != 0) { 3380 goto exit; 3381 } 3382 3383 rc = write_selinux_fsuse_rules_to_cil(out, pdb); 3384 if (rc != 0) { 3385 goto exit; 3386 } 3387 3388 rc = write_genfscon_rules_to_cil(out, pdb); 3389 if (rc != 0) { 3390 goto exit; 3391 } 3392 3393 rc = write_selinux_port_rules_to_cil(out, pdb); 3394 if (rc != 0) { 3395 goto exit; 3396 } 3397 3398 rc = write_selinux_netif_rules_to_cil(out, pdb); 3399 if (rc != 0) { 3400 goto exit; 3401 } 3402 3403 rc = write_selinux_node_rules_to_cil(out, pdb); 3404 if (rc != 0) { 3405 goto exit; 3406 } 3407 3408 rc = write_selinux_node6_rules_to_cil(out, pdb); 3409 if (rc != 0) { 3410 goto exit; 3411 } 3412 3413 rc = write_selinux_ibpkey_rules_to_cil(out, pdb); 3414 if (rc != 0) { 3415 goto exit; 3416 } 3417 3418 rc = write_selinux_ibendport_rules_to_cil(out, pdb); 3419 if (rc != 0) { 3420 goto exit; 3421 } 3422 } else if (pdb->target_platform == SEPOL_TARGET_XEN) { 3423 rc = write_xen_isid_rules_to_cil(out, pdb); 3424 if (rc != 0) { 3425 goto exit; 3426 } 3427 3428 rc = write_xen_pirq_rules_to_cil(out, pdb); 3429 if (rc != 0) { 3430 goto exit; 3431 } 3432 3433 rc = write_xen_ioport_rules_to_cil(out, pdb); 3434 if (rc != 0) { 3435 goto exit; 3436 } 3437 3438 rc = write_xen_iomem_rules_to_cil(out, pdb); 3439 if (rc != 0) { 3440 goto exit; 3441 } 3442 3443 rc = write_xen_pcidevice_rules_to_cil(out, pdb); 3444 if (rc != 0) { 3445 goto exit; 3446 } 3447 3448 rc = write_xen_devicetree_rules_to_cil(out, pdb); 3449 if (rc != 0) { 3450 goto exit; 3451 } 3452 } 3453 3454exit: 3455 strs_free_all(mls_constraints); 3456 strs_destroy(&mls_constraints); 3457 strs_free_all(non_mls_constraints); 3458 strs_destroy(&non_mls_constraints); 3459 strs_free_all(mls_validatetrans); 3460 strs_destroy(&mls_validatetrans); 3461 strs_free_all(non_mls_validatetrans); 3462 strs_destroy(&non_mls_validatetrans); 3463 3464 return rc; 3465} 3466