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