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