1 /* 2 * Copyright 2011 Tresys Technology, LLC. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS 15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * The views and conclusions contained in the software and documentation are those 26 * of the authors and should not be interpreted as representing official policies, 27 * either expressed or implied, of Tresys Technology, LLC. 28 */ 29 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <stdint.h> 34 #include <unistd.h> 35 #include <inttypes.h> 36 37 #include <sepol/policydb/conditional.h> 38 #include <sepol/errcodes.h> 39 40 #include "cil_internal.h" 41 #include "cil_flavor.h" 42 #include "cil_find.h" 43 #include "cil_mem.h" 44 #include "cil_tree.h" 45 #include "cil_list.h" 46 #include "cil_symtab.h" 47 48 49 enum cil_statement_list { 50 CIL_LIST_COMMON = 1, 51 CIL_LIST_DEFAULT_USER, 52 CIL_LIST_DEFAULT_ROLE, 53 CIL_LIST_DEFAULT_TYPE, 54 CIL_LIST_DEFAULT_RANGE, 55 CIL_LIST_SENSALIAS, 56 CIL_LIST_CATALIAS, 57 CIL_LIST_MLSCONSTRAIN, 58 CIL_LIST_MLSVALIDATETRANS, 59 CIL_LIST_POLICYCAP, 60 CIL_LIST_TYPEATTRIBUTE, 61 CIL_LIST_ROLEATTRIBUTE, 62 CIL_LIST_BOOL, 63 CIL_LIST_TYPE, 64 CIL_LIST_TYPEALIAS, 65 CIL_LIST_ROLE, 66 CIL_LIST_ROLEALLOW, 67 CIL_LIST_ROLETRANSITION, 68 CIL_LIST_USER, 69 CIL_LIST_CONSTRAINT, 70 CIL_LIST_VALIDATETRANS, 71 CIL_LIST_NUM_LISTS 72 }; 73 74 static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 75 { 76 struct cil_list **lists; 77 int kind = 0; 78 79 lists = (struct cil_list **)extra_args; 80 81 switch (node->flavor) { 82 case CIL_BLOCK: { 83 struct cil_block *blk = node->data; 84 if (blk->is_abstract == CIL_TRUE) { 85 *finished = CIL_TREE_SKIP_HEAD; 86 } 87 break; 88 } 89 case CIL_MACRO: 90 *finished = CIL_TREE_SKIP_HEAD; 91 break; 92 case CIL_BOOLEANIF: 93 *finished = CIL_TREE_SKIP_HEAD; 94 break; 95 case CIL_COMMON: 96 kind = CIL_LIST_COMMON; 97 break; 98 case CIL_DEFAULTUSER: 99 kind = CIL_LIST_DEFAULT_USER; 100 break; 101 case CIL_DEFAULTROLE: 102 kind = CIL_LIST_DEFAULT_ROLE; 103 break; 104 case CIL_DEFAULTTYPE: 105 kind = CIL_LIST_DEFAULT_TYPE; 106 break; 107 case CIL_DEFAULTRANGE: 108 kind = CIL_LIST_DEFAULT_RANGE; 109 break; 110 case CIL_SENSALIAS: 111 kind = CIL_LIST_SENSALIAS; 112 break; 113 case CIL_CATALIAS: 114 kind = CIL_LIST_CATALIAS; 115 break; 116 case CIL_MLSCONSTRAIN: 117 kind = CIL_LIST_MLSCONSTRAIN; 118 break; 119 case CIL_MLSVALIDATETRANS: 120 kind = CIL_LIST_MLSVALIDATETRANS; 121 break; 122 case CIL_POLICYCAP: 123 kind = CIL_LIST_POLICYCAP; 124 break; 125 case CIL_TYPEATTRIBUTE: { 126 struct cil_typeattribute *attr = node->data; 127 if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) { 128 kind = CIL_LIST_TYPEATTRIBUTE; 129 } 130 break; 131 } 132 case CIL_ROLEATTRIBUTE: { 133 struct cil_roleattribute *attr = node->data; 134 if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) { 135 kind = CIL_LIST_ROLEATTRIBUTE; 136 } 137 break; 138 } 139 case CIL_BOOL: 140 kind = CIL_LIST_BOOL; 141 break; 142 case CIL_TYPE: 143 kind = CIL_LIST_TYPE; 144 break; 145 case CIL_TYPEALIAS: 146 kind = CIL_LIST_TYPEALIAS; 147 break; 148 case CIL_ROLE: { 149 struct cil_role *role = node->data; 150 if (strcmp(role->datum.fqn, "object_r") != 0) { 151 kind = CIL_LIST_ROLE; 152 } 153 break; 154 } 155 case CIL_ROLEALLOW: 156 kind = CIL_LIST_ROLEALLOW; 157 break; 158 case CIL_ROLETRANSITION: 159 kind = CIL_LIST_ROLETRANSITION; 160 break; 161 case CIL_USER: 162 kind = CIL_LIST_USER; 163 break; 164 case CIL_CONSTRAIN: 165 kind = CIL_LIST_CONSTRAINT; 166 break; 167 case CIL_VALIDATETRANS: 168 kind = CIL_LIST_VALIDATETRANS; 169 break; 170 default: 171 break; 172 } 173 174 if (kind > 0) { 175 cil_list_append(lists[kind], node->flavor, node->data); 176 } 177 178 return SEPOL_OK; 179 } 180 181 static void cil_gather_statements(struct cil_tree_node *start, struct cil_list *lists[]) 182 { 183 cil_tree_walk(start, __cil_gather_statements_helper, NULL, NULL, lists); 184 } 185 186 static void cil_simple_rules_to_policy(FILE *out, struct cil_list *rules, const char *kind) 187 { 188 struct cil_list_item *i1; 189 190 cil_list_for_each(i1, rules) { 191 fprintf(out, "%s %s;\n", kind, DATUM(i1->data)->fqn); 192 } 193 } 194 195 static void cil_cats_to_policy(FILE *out, struct cil_cats *cats) 196 { 197 const char *lead = ""; 198 struct cil_cat *first = NULL, *last = NULL, *cat; 199 struct cil_list_item *i1; 200 201 cil_list_for_each(i1, cats->datum_expr) { 202 cat = i1->data; 203 if (first == NULL) { 204 first = cat; 205 } else if (last == NULL) { 206 if (cat->value == first->value + 1) { 207 last = cat; 208 } else { 209 fprintf(out, "%s%s", lead, DATUM(first)->fqn); 210 lead = ","; 211 first = cat; 212 } 213 } else if (cat->value == last->value + 1) { 214 last = cat; 215 } else { 216 fprintf(out, "%s%s", lead, DATUM(first)->fqn); 217 lead = ","; 218 if (last->value >= first->value + 1) { 219 fprintf(out, "."); 220 } else { 221 fprintf(out, ","); 222 } 223 fprintf(out, "%s", DATUM(last)->fqn); 224 first = cat; 225 last = NULL; 226 } 227 } 228 if (first) { 229 fprintf(out, "%s%s", lead, DATUM(first)->fqn); 230 if (last != NULL) { 231 if (last->value >= first->value + 1) { 232 fprintf(out, "."); 233 } else { 234 fprintf(out, ","); 235 } 236 fprintf(out, "%s", DATUM(last)->fqn); 237 } 238 } 239 } 240 241 static void cil_level_to_policy(FILE *out, struct cil_level *level) 242 { 243 fprintf(out, "%s", DATUM(level->sens)->fqn); 244 if (level->cats != NULL) { 245 fprintf(out, ":"); 246 cil_cats_to_policy(out, level->cats); 247 } 248 } 249 250 static int cil_levels_simple_and_equal(struct cil_level *l1, struct cil_level *l2) 251 { 252 /* Mostly just want to detect s0 - s0 ranges */ 253 if (l1 == l2) 254 return CIL_TRUE; 255 256 if (l1->sens == l2->sens && (l1->cats == NULL && l2->cats == NULL)) 257 return CIL_TRUE; 258 259 return CIL_FALSE; 260 } 261 262 static void cil_levelrange_to_policy(FILE *out, struct cil_levelrange *lvlrange) 263 { 264 cil_level_to_policy(out, lvlrange->low); 265 if (cil_levels_simple_and_equal(lvlrange->low, lvlrange->high) == CIL_FALSE) { 266 fprintf(out, " - "); 267 cil_level_to_policy(out, lvlrange->high); 268 } 269 } 270 271 static void cil_context_to_policy(FILE *out, struct cil_context *context, int mls) 272 { 273 fprintf(out, "%s:", DATUM(context->user)->fqn); 274 fprintf(out, "%s:", DATUM(context->role)->fqn); 275 fprintf(out, "%s", DATUM(context->type)->fqn); 276 if (mls) { 277 fprintf(out, ":"); 278 cil_levelrange_to_policy(out, context->range); 279 } 280 } 281 282 static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first) 283 { 284 struct cil_list_item *i1 = expr->head; 285 286 if (i1->flavor == CIL_OP) { 287 enum cil_flavor op = (enum cil_flavor)i1->data; 288 fprintf(out, "("); 289 switch (op) { 290 case CIL_NOT: 291 fprintf(out, "! "); 292 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); 293 break; 294 case CIL_OR: 295 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); 296 fprintf(out, " || "); 297 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); 298 break; 299 case CIL_AND: 300 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); 301 fprintf(out, " && "); 302 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); 303 break; 304 case CIL_XOR: 305 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); 306 fprintf(out, " ^ "); 307 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); 308 break; 309 case CIL_EQ: 310 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); 311 fprintf(out, " == "); 312 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); 313 break; 314 case CIL_NEQ: 315 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); 316 fprintf(out, " != "); 317 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); 318 break; 319 default: 320 fprintf(out, "???"); 321 break; 322 } 323 fprintf(out, ")"); 324 } else if (i1->flavor == CIL_DATUM) { 325 if (first == CIL_TRUE) { 326 fprintf(out, "("); 327 } 328 fprintf(out, "%s", DATUM(i1->data)->fqn); 329 if (first == CIL_TRUE) { 330 fprintf(out, ")"); 331 } 332 } else if (i1->flavor == CIL_LIST) { 333 cil_cond_expr_to_policy(out, i1->data, CIL_FALSE); 334 } else { 335 fprintf(out, "???"); 336 } 337 } 338 339 static size_t __cil_userattribute_len(struct cil_db *db, struct cil_userattribute *attr) 340 { 341 ebitmap_node_t *unode; 342 unsigned int i; 343 size_t len = 0; 344 345 ebitmap_for_each_bit(attr->users, unode, i) { 346 if (!ebitmap_get_bit(attr->users, i)) 347 continue; 348 len += strlen(DATUM(db->val_to_user[i])->fqn); 349 len++; 350 } 351 352 return len; 353 } 354 355 static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand) 356 { 357 struct cil_list_item *i1; 358 enum cil_flavor flavor = operand->flavor; 359 size_t len = 0; 360 361 if (flavor == CIL_CONS_OPERAND) { 362 len = 2; 363 } else if (flavor == CIL_DATUM) { 364 struct cil_tree_node *node = NODE(operand->data); 365 if (node->flavor == CIL_USERATTRIBUTE) { 366 len = __cil_userattribute_len(db, operand->data); 367 len++; /* "{" */ 368 } else { 369 len = strlen(DATUM(operand->data)->fqn); 370 } 371 } else if (flavor == CIL_LIST) { 372 len = 1; /* "{" */ 373 cil_list_for_each(i1, (struct cil_list *)operand->data) { 374 struct cil_tree_node *node = NODE(operand->data); 375 if (node->flavor == CIL_USERATTRIBUTE) { 376 len = __cil_userattribute_len(db, operand->data); 377 } else { 378 len += strlen(DATUM(operand->data)->fqn); 379 len++; /* " " or "}" */ 380 } 381 } 382 } 383 384 return len; 385 } 386 387 static size_t __cil_cons_leaf_op_len(struct cil_list_item *op) 388 { 389 enum cil_flavor flavor = (enum cil_flavor)op->data; 390 size_t len; 391 392 switch (flavor) { 393 case CIL_EQ: 394 len = 4; /* " == " */ 395 break; 396 case CIL_NEQ: 397 len = 4; /* " != " */ 398 break; 399 case CIL_CONS_DOM: 400 len = 5; /* " dom " */ 401 break; 402 case CIL_CONS_DOMBY: 403 len = 7; /* " domby " */ 404 break; 405 case CIL_CONS_INCOMP: 406 len = 8; /* " incomp " */ 407 break; 408 default: 409 /* Should be impossible to be here */ 410 len = 5; /* " ??? " */ 411 } 412 413 return len; 414 } 415 416 static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr) 417 { 418 struct cil_list_item *i1; 419 enum cil_flavor op; 420 size_t len; 421 422 i1 = cons_expr->head; 423 424 op = (enum cil_flavor)i1->data; 425 switch (op) { 426 case CIL_NOT: 427 len = 6; /* "(not )" */ 428 len += cil_cons_expr_len(db, i1->next->data); 429 break; 430 case CIL_AND: 431 len = 7; /* "( and )" */ 432 len += cil_cons_expr_len(db, i1->next->data); 433 len += cil_cons_expr_len(db, i1->next->next->data); 434 break; 435 case CIL_OR: 436 len = 6; /* "( or )" */ 437 len += cil_cons_expr_len(db, i1->next->data); 438 len += cil_cons_expr_len(db, i1->next->next->data); 439 break; 440 default: 441 len = 2; /* "()" */ 442 len += __cil_cons_leaf_operand_len(db, i1->next); 443 len += __cil_cons_leaf_op_len(i1); 444 len += __cil_cons_leaf_operand_len(db, i1->next->next); 445 } 446 447 return len; 448 } 449 450 static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new) 451 { 452 ebitmap_node_t *unode; 453 unsigned int i; 454 char *str; 455 size_t len; 456 457 ebitmap_for_each_bit(attr->users, unode, i) { 458 if (!ebitmap_get_bit(attr->users, i)) 459 continue; 460 str = DATUM(db->val_to_user[i])->fqn; 461 len = strlen(str); 462 memcpy(new, str, len); 463 new += len; 464 *new++ = ' '; 465 } 466 467 return new; 468 } 469 470 static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new) 471 { 472 struct cil_list_item *i1; 473 enum cil_flavor flavor = operand->flavor; 474 const char *o_str; 475 size_t o_len; 476 477 if (flavor == CIL_CONS_OPERAND) { 478 enum cil_flavor o_flavor = (enum cil_flavor)operand->data; 479 switch (o_flavor) { 480 case CIL_CONS_U1: 481 o_str = "u1"; 482 break; 483 case CIL_CONS_U2: 484 o_str = "u2"; 485 break; 486 case CIL_CONS_U3: 487 o_str = "u3"; 488 break; 489 case CIL_CONS_R1: 490 o_str = "r1"; 491 break; 492 case CIL_CONS_R2: 493 o_str = "r2"; 494 break; 495 case CIL_CONS_R3: 496 o_str = "r3"; 497 break; 498 case CIL_CONS_T1: 499 o_str = "t1"; 500 break; 501 case CIL_CONS_T2: 502 o_str = "t2"; 503 break; 504 case CIL_CONS_T3: 505 o_str = "t3"; 506 break; 507 case CIL_CONS_L1: 508 o_str = "l1"; 509 break; 510 case CIL_CONS_L2: 511 o_str = "l2"; 512 break; 513 case CIL_CONS_H1: 514 o_str = "h1"; 515 break; 516 case CIL_CONS_H2: 517 o_str = "h2"; 518 break; 519 default: 520 /* Impossible */ 521 o_str = "??"; 522 } 523 strcpy(new, o_str); 524 new += 2; 525 } else if (flavor == CIL_DATUM) { 526 struct cil_tree_node *node = NODE(operand->data); 527 if (node->flavor == CIL_USERATTRIBUTE) { 528 *new++ = '{'; 529 new = __cil_userattribute_to_string(db, operand->data, new); 530 new--; 531 *new++ = '}'; 532 } else { 533 o_str = DATUM(operand->data)->fqn; 534 o_len = strlen(o_str); 535 memcpy(new, o_str, o_len); 536 new += o_len; 537 } 538 } else if (flavor == CIL_LIST) { 539 *new++ = '{'; 540 cil_list_for_each(i1, (struct cil_list *)operand->data) { 541 struct cil_tree_node *node = NODE(operand->data); 542 if (node->flavor == CIL_USERATTRIBUTE) { 543 new = __cil_userattribute_to_string(db, operand->data, new); 544 } else { 545 o_str = DATUM(operand->data)->fqn; 546 o_len = strlen(o_str); 547 memcpy(new, o_str, o_len); 548 new += o_len; 549 *new++ = ' '; 550 } 551 } 552 new--; 553 *new++ = '}'; 554 } 555 556 return new; 557 } 558 559 static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new) 560 { 561 enum cil_flavor flavor = (enum cil_flavor)op->data; 562 const char *op_str; 563 size_t len; 564 565 switch (flavor) { 566 case CIL_EQ: 567 op_str = " == "; 568 len = 4; 569 break; 570 case CIL_NEQ: 571 op_str = " != "; 572 len = 4; 573 break; 574 case CIL_CONS_DOM: 575 op_str = " dom "; 576 len = 5; 577 break; 578 case CIL_CONS_DOMBY: 579 op_str = " domby "; 580 len = 7; 581 break; 582 case CIL_CONS_INCOMP: 583 op_str = " incomp "; 584 len = 8; 585 break; 586 default: 587 /* Should be impossible to be here */ 588 op_str = " ??? "; 589 len = 5; 590 } 591 592 strcpy(new, op_str); 593 new += len; 594 595 return new; 596 } 597 598 static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new) 599 { 600 struct cil_list_item *i1; 601 enum cil_flavor op; 602 603 i1 = cons_expr->head; 604 605 op = (enum cil_flavor)i1->data; 606 switch (op) { 607 case CIL_NOT: 608 *new++ = '('; 609 strcpy(new, "not "); 610 new += 4; 611 new = __cil_cons_expr_to_string(db, i1->next->data, new); 612 *new++ = ')'; 613 break; 614 case CIL_AND: 615 *new++ = '('; 616 new = __cil_cons_expr_to_string(db, i1->next->data, new); 617 strcpy(new, " and "); 618 new += 5; 619 new = __cil_cons_expr_to_string(db, i1->next->next->data, new); 620 *new++ = ')'; 621 break; 622 case CIL_OR: 623 *new++ = '('; 624 new = __cil_cons_expr_to_string(db, i1->next->data, new); 625 strcpy(new, " or "); 626 new += 4; 627 new = __cil_cons_expr_to_string(db, i1->next->next->data, new); 628 *new++ = ')'; 629 break; 630 default: 631 *new++ = '('; 632 new = __cil_cons_leaf_operand_to_string(db, i1->next, new); 633 new = __cil_cons_leaf_op_to_string(i1, new); 634 new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new); 635 *new++ = ')'; 636 } 637 638 return new; 639 } 640 641 static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr) 642 { 643 char *new, *tail; 644 size_t len = cil_cons_expr_len(db, cons_expr); 645 646 new = cil_malloc(len+1); 647 tail = __cil_cons_expr_to_string(db, cons_expr, new); 648 *tail = '\0'; 649 650 return new; 651 } 652 653 static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs) 654 { 655 struct cil_list_item *i1; 656 size_t len = 0; 657 char *new, *curr; 658 659 len += strlen(DATUM(classperms->class)->fqn) + 1; 660 cil_list_for_each(i1, classperms->perms) { 661 len += strlen(DATUM(i1->data)->fqn) + 1; 662 } 663 len += 4; /* for "{ " and " }" */ 664 665 new = cil_malloc(len); 666 curr = new; 667 668 curr[len-1] = '\0'; 669 670 len = strlen(DATUM(classperms->class)->fqn); 671 memcpy(curr, DATUM(classperms->class)->fqn, len); 672 curr += len; 673 *curr++ = ' '; 674 675 *curr++ = '{'; 676 *curr++ = ' '; 677 cil_list_for_each(i1, classperms->perms) { 678 len = strlen(DATUM(i1->data)->fqn); 679 memcpy(curr, DATUM(i1->data)->fqn, len); 680 curr += len; 681 *curr++ = ' '; 682 } 683 *curr++ = '}'; 684 685 cil_list_append(classperms_strs, CIL_STRING, new); 686 } 687 688 static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs) 689 { 690 struct cil_list_item *i1; 691 692 cil_list_for_each(i1, classperms) { 693 if (i1->flavor == CIL_CLASSPERMS) { 694 struct cil_classperms *cp = i1->data; 695 if (FLAVOR(cp->class) == CIL_CLASS) { 696 cil_classperms_to_string(cp, classperms_strs); 697 } else { /* MAP */ 698 struct cil_list_item *i2 = NULL; 699 cil_list_for_each(i2, cp->perms) { 700 struct cil_perm *cmp = i2->data; 701 cil_classperms_to_strings(cmp->classperms, classperms_strs); 702 } 703 } 704 } else { /* SET */ 705 struct cil_classperms_set *cp_set = i1->data; 706 struct cil_classpermission *cp = cp_set->set; 707 cil_classperms_to_strings(cp->classperms, classperms_strs); 708 } 709 } 710 } 711 712 static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder) 713 { 714 struct cil_list_item *i1; 715 716 cil_list_for_each(i1, classorder) { 717 fprintf(out, "class %s\n", DATUM(i1->data)->fqn); 718 } 719 } 720 721 static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder) 722 { 723 struct cil_list_item *i1; 724 725 cil_list_for_each(i1, sidorder) { 726 fprintf(out, "sid %s\n", DATUM(i1->data)->fqn); 727 } 728 } 729 730 static void cil_commons_to_policy(FILE *out, struct cil_list *commons) 731 { 732 struct cil_list_item *i1; 733 struct cil_class* common; 734 struct cil_tree_node *node; 735 struct cil_tree_node *perm; 736 737 cil_list_for_each(i1, commons) { 738 common = i1->data; 739 node = NODE(&common->datum); 740 perm = node->cl_head; 741 742 fprintf(out, "common %s {", common->datum.fqn); 743 while (perm != NULL) { 744 fprintf(out, "%s ", DATUM(perm->data)->fqn); 745 perm = perm->next; 746 } 747 fprintf(out, "}\n"); 748 } 749 } 750 751 static void cil_classes_to_policy(FILE *out, struct cil_list *classorder) 752 { 753 struct cil_list_item *i1; 754 struct cil_class *class; 755 struct cil_tree_node *node; 756 757 cil_list_for_each(i1, classorder) { 758 class = i1->data; 759 node = NODE(&class->datum); 760 761 fprintf(out, "class %s", class->datum.fqn); 762 if (class->common != NULL) { 763 fprintf(out, " inherits %s", class->common->datum.fqn); 764 } 765 if (node->cl_head != NULL) { 766 struct cil_tree_node *perm = node->cl_head; 767 fprintf(out, " {"); 768 while (perm != NULL) { 769 fprintf(out, " %s", DATUM(perm->data)->fqn); 770 perm = perm->next; 771 } 772 fprintf(out, " }"); 773 } 774 fprintf(out, "\n"); 775 } 776 } 777 778 static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, char *kind) 779 { 780 struct cil_list_item *i1, *i2, *i3; 781 struct cil_default *def; 782 struct cil_list *class_list; 783 784 cil_list_for_each(i1, defaults) { 785 def = i1->data; 786 fprintf(out, "%s {",kind); 787 cil_list_for_each(i2, def->class_datums) { 788 class_list = cil_expand_class(i2->data); 789 cil_list_for_each(i3, class_list) { 790 fprintf(out, " %s", DATUM(i3->data)->fqn); 791 } 792 cil_list_destroy(&class_list, CIL_FALSE); 793 } 794 fprintf(out, " }"); 795 if (def->object == CIL_DEFAULT_SOURCE) { 796 fprintf(out," %s",CIL_KEY_SOURCE); 797 } else if (def->object == CIL_DEFAULT_TARGET) { 798 fprintf(out," %s",CIL_KEY_TARGET); 799 } 800 fprintf(out,";\n"); 801 } 802 } 803 804 static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults) 805 { 806 struct cil_list_item *i1, *i2, *i3; 807 struct cil_defaultrange *def; 808 struct cil_list *class_list; 809 810 cil_list_for_each(i1, defaults) { 811 def = i1->data; 812 fprintf(out, "default_range {"); 813 cil_list_for_each(i2, def->class_datums) { 814 class_list = cil_expand_class(i2->data); 815 cil_list_for_each(i3, class_list) { 816 fprintf(out, " %s", DATUM(i3->data)->fqn); 817 } 818 cil_list_destroy(&class_list, CIL_FALSE); 819 } 820 fprintf(out, " }"); 821 822 switch (def->object_range) { 823 case CIL_DEFAULT_SOURCE_LOW: 824 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW); 825 break; 826 case CIL_DEFAULT_SOURCE_HIGH: 827 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH); 828 break; 829 case CIL_DEFAULT_SOURCE_LOW_HIGH: 830 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH); 831 break; 832 case CIL_DEFAULT_TARGET_LOW: 833 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW); 834 break; 835 case CIL_DEFAULT_TARGET_HIGH: 836 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH); 837 break; 838 case CIL_DEFAULT_TARGET_LOW_HIGH: 839 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH); 840 break; 841 default: 842 break; 843 } 844 fprintf(out,";\n"); 845 } 846 } 847 848 static void cil_sensitivities_to_policy(FILE *out, struct cil_list *sensorder, struct cil_list *all_aliases) 849 { 850 struct cil_list_item *i1, *i2; 851 struct cil_sens *sens; 852 struct cil_list *aliases = NULL; 853 struct cil_alias *alias; 854 struct cil_sens *actual; 855 int num_aliases; 856 857 cil_list_for_each(i1, sensorder) { 858 sens = i1->data; 859 num_aliases = 0; 860 cil_list_for_each(i2, all_aliases) { 861 alias = i2->data; 862 actual = alias->actual; 863 if (sens == actual) { 864 if (num_aliases == 0) { 865 cil_list_init(&aliases, CIL_LIST); 866 } 867 cil_list_append(aliases, CIL_SENSALIAS, alias); 868 num_aliases++; 869 } 870 } 871 fprintf(out, "sensitivity %s", sens->datum.fqn); 872 if (num_aliases > 0) { 873 fprintf(out, " alias"); 874 if (num_aliases > 1) { 875 fprintf(out, " {"); 876 } 877 cil_list_for_each(i2, aliases) { 878 alias = i2->data; 879 fprintf(out, " %s", alias->datum.fqn); 880 } 881 if (num_aliases > 1) { 882 fprintf(out, " }"); 883 } 884 cil_list_destroy(&aliases, CIL_FALSE); 885 } 886 fprintf(out, ";\n"); 887 } 888 } 889 890 static void cil_dominance_to_policy(FILE *out, struct cil_list *sensorder) 891 { 892 struct cil_list_item *item; 893 struct cil_sens *sens; 894 895 fprintf(out, "dominance {"); 896 cil_list_for_each(item, sensorder) { 897 sens = item->data; 898 fprintf(out, " %s", sens->datum.fqn); 899 } 900 fprintf(out, " }\n"); 901 } 902 903 static void cil_categories_to_policy(FILE *out, struct cil_list *catorder, struct cil_list *all_aliases) 904 { 905 struct cil_list_item *i1, *i2; 906 struct cil_sens *cat; 907 struct cil_list *aliases = NULL; 908 struct cil_alias *alias; 909 struct cil_sens *actual; 910 int num_aliases; 911 912 cil_list_for_each(i1, catorder) { 913 cat = i1->data; 914 num_aliases = 0; 915 cil_list_for_each(i2, all_aliases) { 916 alias = i2->data; 917 actual = alias->actual; 918 if (cat == actual) { 919 if (num_aliases == 0) { 920 cil_list_init(&aliases, CIL_LIST); 921 } 922 cil_list_append(aliases, CIL_CATALIAS, alias); 923 num_aliases++; 924 } 925 } 926 fprintf(out, "category %s",cat->datum.fqn); 927 if (num_aliases > 0) { 928 fprintf(out, " alias"); 929 if (num_aliases > 1) { 930 fprintf(out, " { "); 931 } 932 cil_list_for_each(i2, aliases) { 933 alias = i2->data; 934 fprintf(out, " %s", alias->datum.fqn); 935 } 936 if (num_aliases > 1) { 937 fprintf(out, " }"); 938 } 939 cil_list_destroy(&aliases, CIL_FALSE); 940 } 941 fprintf(out, ";\n"); 942 } 943 } 944 945 static void cil_levels_to_policy(FILE *out, struct cil_list *sensorder) 946 { 947 struct cil_list_item *i1, *i2; 948 struct cil_sens *sens; 949 950 cil_list_for_each(i1, sensorder) { 951 sens = i1->data; 952 if (sens->cats_list) { 953 cil_list_for_each(i2, sens->cats_list) { 954 fprintf(out, "level %s:",sens->datum.fqn); 955 cil_cats_to_policy(out, i2->data); 956 fprintf(out,";\n"); 957 } 958 } else { 959 fprintf(out, "level %s;\n",sens->datum.fqn); 960 } 961 } 962 } 963 964 static void cil_mlsconstrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *mlsconstrains) 965 { 966 struct cil_list_item *i1, *i2; 967 struct cil_constrain *cons; 968 struct cil_list *classperms_strs; 969 char *cp_str; 970 char *expr_str; 971 972 cil_list_for_each(i1, mlsconstrains) { 973 cons = i1->data; 974 cil_list_init(&classperms_strs, CIL_LIST); 975 cil_classperms_to_strings(cons->classperms, classperms_strs); 976 expr_str = cil_cons_expr_to_string(db, cons->datum_expr); 977 cil_list_for_each(i2, classperms_strs) { 978 cp_str = i2->data; 979 fprintf(out, "mlsconstrain %s %s;\n", cp_str, expr_str); 980 free(cp_str); 981 } 982 free(expr_str); 983 cil_list_destroy(&classperms_strs, CIL_FALSE); 984 } 985 } 986 987 static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil_list *validatetrans, char *kind) 988 { 989 struct cil_list_item *i1, *i2; 990 struct cil_validatetrans *trans; 991 struct cil_list *class_list; 992 struct cil_class *class; 993 char *expr_str; 994 995 cil_list_for_each(i1, validatetrans) { 996 trans = i1->data; 997 class_list = cil_expand_class(trans->class); 998 expr_str = cil_cons_expr_to_string(db, trans->datum_expr); 999 cil_list_for_each(i2, class_list) { 1000 class = i2->data; 1001 fprintf(out, "%s %s %s;\n", kind, class->datum.fqn, expr_str); 1002 } 1003 free(expr_str); 1004 cil_list_destroy(&class_list, CIL_FALSE); 1005 } 1006 } 1007 1008 static void cil_bools_to_policy(FILE *out, struct cil_list *bools) 1009 { 1010 struct cil_list_item *i1; 1011 struct cil_bool *bool; 1012 const char *value; 1013 1014 cil_list_for_each(i1, bools) { 1015 bool = i1->data; 1016 value = bool->value ? "true" : "false"; 1017 fprintf(out, "bool %s %s;\n", bool->datum.fqn, value); 1018 } 1019 } 1020 1021 static void cil_typealiases_to_policy(FILE *out, struct cil_list *types, struct cil_list *all_aliases) 1022 { 1023 struct cil_list_item *i1, *i2; 1024 struct cil_type *type; 1025 struct cil_list *aliases = NULL; 1026 struct cil_alias *alias; 1027 struct cil_type *actual; 1028 int num_aliases; 1029 1030 cil_list_for_each(i1, types) { 1031 type = i1->data; 1032 num_aliases = 0; 1033 cil_list_for_each(i2, all_aliases) { 1034 alias = i2->data; 1035 actual = alias->actual; 1036 if (type == actual) { 1037 if (num_aliases == 0) { 1038 cil_list_init(&aliases, CIL_LIST); 1039 } 1040 cil_list_append(aliases, CIL_TYPEALIAS, alias); 1041 num_aliases++; 1042 } 1043 } 1044 if (num_aliases > 0) { 1045 fprintf(out, "typealias %s alias", type->datum.fqn); 1046 if (num_aliases > 1) { 1047 fprintf(out, " {"); 1048 } 1049 cil_list_for_each(i2, aliases) { 1050 alias = i2->data; 1051 fprintf(out, " %s", alias->datum.fqn); 1052 } 1053 if (num_aliases > 1) { 1054 fprintf(out, " }"); 1055 } 1056 fprintf(out, ";\n"); 1057 cil_list_destroy(&aliases, CIL_FALSE); 1058 } 1059 } 1060 } 1061 1062 static void cil_typebounds_to_policy(FILE *out, struct cil_list *types) 1063 { 1064 struct cil_list_item *i1; 1065 struct cil_type *child; 1066 struct cil_type *parent; 1067 1068 cil_list_for_each(i1, types) { 1069 child = i1->data; 1070 if (child->bounds != NULL) { 1071 parent = child->bounds; 1072 fprintf(out, "typebounds %s %s\n", parent->datum.fqn, child->datum.fqn); 1073 } 1074 } 1075 } 1076 1077 static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, struct cil_list *attributes) 1078 { 1079 struct cil_list_item *i1, *i2; 1080 struct cil_type *type; 1081 struct cil_typeattribute *attribute; 1082 int first = CIL_TRUE; 1083 1084 cil_list_for_each(i1, types) { 1085 type = i1->data; 1086 cil_list_for_each(i2, attributes) { 1087 attribute = i2->data; 1088 if (!attribute->used) 1089 continue; 1090 if (ebitmap_get_bit(attribute->types, type->value)) { 1091 if (first) { 1092 fprintf(out, "typeattribute %s %s", type->datum.fqn, attribute->datum.fqn); 1093 first = CIL_FALSE; 1094 } else { 1095 fprintf(out, ", %s", attribute->datum.fqn); 1096 } 1097 } 1098 } 1099 if (!first) { 1100 fprintf(out, ";\n"); 1101 first = CIL_TRUE; 1102 } 1103 } 1104 } 1105 1106 static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx) 1107 { 1108 ebitmap_node_t *node; 1109 unsigned int i, first = 0, last = 0; 1110 int need_first = CIL_TRUE, need_last = CIL_TRUE; 1111 const char *kind; 1112 1113 if (permx->kind == CIL_PERMX_KIND_IOCTL) { 1114 kind = "ioctl"; 1115 } else { 1116 kind = "???"; 1117 } 1118 1119 fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind); 1120 1121 ebitmap_for_each_bit(permx->perms, node, i) { 1122 if (!ebitmap_get_bit(permx->perms, i)) 1123 continue; 1124 if (need_first == CIL_TRUE) { 1125 first = i; 1126 need_first = CIL_FALSE; 1127 } else if (need_last == CIL_TRUE) { 1128 if (i == first+1) { 1129 last = i; 1130 need_last = CIL_FALSE; 1131 } else { 1132 fprintf(out, " 0x%x", first); 1133 first = i; 1134 } 1135 } else if (i == last+1) { 1136 last = i; 1137 } else { 1138 if (last > first+1) { 1139 fprintf(out, " 0x%x-0x%x", first, last); 1140 } else { 1141 fprintf(out, " 0x%x 0x%x", first, last); 1142 } 1143 first = i; 1144 need_last = CIL_TRUE; 1145 } 1146 } 1147 if (need_first == CIL_FALSE) { 1148 if (need_last == CIL_FALSE) { 1149 fprintf(out, " 0x%x-0x%x", first, last); 1150 } else { 1151 fprintf(out, " 0x%x", first); 1152 } 1153 } 1154 fprintf(out," }"); 1155 } 1156 1157 static void cil_av_rulex_to_policy(FILE *out, struct cil_avrule *rule) 1158 { 1159 const char *kind; 1160 struct cil_symtab_datum *src, *tgt; 1161 1162 src = rule->src; 1163 tgt = rule->tgt; 1164 1165 switch (rule->rule_kind) { 1166 case CIL_AVRULE_ALLOWED: 1167 kind = "allowxperm"; 1168 break; 1169 case CIL_AVRULE_AUDITALLOW: 1170 kind = "auditallowxperm"; 1171 break; 1172 case CIL_AVRULE_DONTAUDIT: 1173 kind = "dontauditxperm"; 1174 break; 1175 case CIL_AVRULE_NEVERALLOW: 1176 kind = "neverallowxperm"; 1177 break; 1178 default: 1179 kind = "???"; 1180 break; 1181 } 1182 1183 fprintf(out, "%s %s %s : ", kind, src->fqn, tgt->fqn); 1184 cil_xperms_to_policy(out, rule->perms.x.permx); 1185 fprintf(out, ";\n"); 1186 } 1187 1188 static void cil_av_rule_to_policy(FILE *out, struct cil_avrule *rule) 1189 { 1190 const char *kind; 1191 struct cil_symtab_datum *src, *tgt; 1192 struct cil_list *classperms_strs; 1193 struct cil_list_item *i1; 1194 1195 src = rule->src; 1196 tgt = rule->tgt; 1197 1198 switch (rule->rule_kind) { 1199 case CIL_AVRULE_ALLOWED: 1200 kind = "allow"; 1201 break; 1202 case CIL_AVRULE_AUDITALLOW: 1203 kind = "auditallow"; 1204 break; 1205 case CIL_AVRULE_DONTAUDIT: 1206 kind = "dontaudit"; 1207 break; 1208 case CIL_AVRULE_NEVERALLOW: 1209 kind = "neverallow"; 1210 break; 1211 default: 1212 kind = "???"; 1213 break; 1214 } 1215 1216 cil_list_init(&classperms_strs, CIL_LIST); 1217 cil_classperms_to_strings(rule->perms.classperms, classperms_strs); 1218 cil_list_for_each(i1, classperms_strs) { 1219 char *cp_str = i1->data; 1220 fprintf(out, "%s %s %s : %s;\n", kind, src->fqn, tgt->fqn, cp_str); 1221 free(cp_str); 1222 } 1223 cil_list_destroy(&classperms_strs, CIL_FALSE); 1224 } 1225 1226 static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule) 1227 { 1228 const char *kind; 1229 struct cil_symtab_datum *src, *tgt, *res; 1230 struct cil_list *class_list; 1231 struct cil_list_item *i1; 1232 1233 src = rule->src; 1234 tgt = rule->tgt; 1235 res = rule->result; 1236 1237 switch (rule->rule_kind) { 1238 case CIL_TYPE_TRANSITION: 1239 kind = "type_transition"; 1240 break; 1241 case CIL_TYPE_MEMBER: 1242 kind = "type_member"; 1243 break; 1244 case CIL_TYPE_CHANGE: 1245 kind = "type_change"; 1246 break; 1247 default: 1248 kind = "???"; 1249 break; 1250 } 1251 1252 class_list = cil_expand_class(rule->obj); 1253 cil_list_for_each(i1, class_list) { 1254 fprintf(out, "%s %s %s : %s %s;\n", kind, src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn); 1255 } 1256 cil_list_destroy(&class_list, CIL_FALSE); 1257 } 1258 1259 static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans) 1260 { 1261 struct cil_symtab_datum *src, *tgt, *res; 1262 struct cil_name *name; 1263 struct cil_list *class_list; 1264 struct cil_list_item *i1; 1265 1266 src = trans->src; 1267 tgt = trans->tgt; 1268 name = trans->name; 1269 res = trans->result; 1270 1271 class_list = cil_expand_class(trans->obj); 1272 cil_list_for_each(i1, class_list) { 1273 fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->datum.fqn); 1274 } 1275 cil_list_destroy(&class_list, CIL_FALSE); 1276 } 1277 1278 static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans) 1279 { 1280 struct cil_symtab_datum *src, *exec; 1281 struct cil_list *class_list; 1282 struct cil_list_item *i1; 1283 1284 src = trans->src; 1285 exec = trans->exec; 1286 1287 class_list = cil_expand_class(trans->obj); 1288 cil_list_for_each(i1, class_list) { 1289 fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn); 1290 cil_levelrange_to_policy(out, trans->range); 1291 fprintf(out, ";\n"); 1292 } 1293 cil_list_destroy(&class_list, CIL_FALSE); 1294 } 1295 1296 static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule) 1297 { 1298 fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn); 1299 } 1300 1301 struct block_te_rules_extra { 1302 FILE *out; 1303 enum cil_flavor flavor; 1304 uint32_t rule_kind; 1305 }; 1306 1307 static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 1308 { 1309 struct block_te_rules_extra *args = extra_args; 1310 1311 switch (node->flavor) { 1312 case CIL_BLOCK: { 1313 struct cil_block *blk = node->data; 1314 if (blk->is_abstract == CIL_TRUE) { 1315 *finished = CIL_TREE_SKIP_HEAD; 1316 } 1317 break; 1318 } 1319 case CIL_MACRO: 1320 *finished = CIL_TREE_SKIP_HEAD; 1321 break; 1322 case CIL_BOOLEANIF: 1323 *finished = CIL_TREE_SKIP_HEAD; 1324 break; 1325 case CIL_AVRULE: 1326 case CIL_AVRULEX: 1327 if (args->flavor == node->flavor) { 1328 struct cil_avrule *rule = node->data; 1329 if (args->rule_kind == rule->rule_kind) { 1330 if (rule->is_extended) { 1331 cil_av_rulex_to_policy(args->out, rule); 1332 } else { 1333 cil_av_rule_to_policy(args->out, rule); 1334 } 1335 } 1336 } 1337 break; 1338 case CIL_TYPE_RULE: 1339 if (args->flavor == node->flavor) { 1340 struct cil_type_rule *rule = node->data; 1341 if (args->rule_kind == rule->rule_kind) { 1342 cil_type_rule_to_policy(args->out, rule); 1343 } 1344 } 1345 1346 break; 1347 case CIL_NAMETYPETRANSITION: 1348 if (args->flavor == node->flavor) { 1349 cil_nametypetransition_to_policy(args->out, node->data); 1350 } 1351 break; 1352 case CIL_RANGETRANSITION: 1353 if (args->flavor == node->flavor) { 1354 cil_rangetransition_to_policy(args->out, node->data); 1355 } 1356 1357 break; 1358 case CIL_TYPEPERMISSIVE: 1359 if (args->flavor == node->flavor) { 1360 cil_typepermissive_to_policy(args->out, node->data); 1361 } 1362 break; 1363 default: 1364 break; 1365 } 1366 1367 return SEPOL_OK; 1368 } 1369 1370 static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls) 1371 { 1372 struct block_te_rules_extra args; 1373 1374 args.out = out; 1375 1376 args.flavor = CIL_TYPEPERMISSIVE; 1377 args.rule_kind = 0; 1378 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1379 1380 args.flavor = CIL_AVRULE; 1381 args.rule_kind = CIL_AVRULE_ALLOWED; 1382 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1383 args.rule_kind = CIL_AVRULE_AUDITALLOW; 1384 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1385 args.rule_kind = CIL_AVRULE_DONTAUDIT; 1386 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1387 args.rule_kind = CIL_AVRULE_NEVERALLOW; 1388 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1389 1390 args.flavor = CIL_AVRULEX; 1391 args.rule_kind = CIL_AVRULE_ALLOWED; 1392 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1393 args.rule_kind = CIL_AVRULE_AUDITALLOW; 1394 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1395 args.rule_kind = CIL_AVRULE_DONTAUDIT; 1396 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1397 args.rule_kind = CIL_AVRULE_NEVERALLOW; 1398 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1399 1400 args.flavor = CIL_TYPE_RULE; 1401 args.rule_kind = CIL_TYPE_TRANSITION; 1402 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1403 args.rule_kind = CIL_TYPE_MEMBER; 1404 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1405 args.rule_kind = CIL_TYPE_CHANGE; 1406 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1407 args.rule_kind = CIL_AVRULE_TYPE; 1408 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1409 1410 args.flavor = CIL_NAMETYPETRANSITION; 1411 args.rule_kind = 0; 1412 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1413 1414 if (mls == CIL_TRUE) { 1415 args.flavor = CIL_RANGETRANSITION; 1416 args.rule_kind = 0; 1417 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); 1418 } 1419 } 1420 1421 struct te_rules_extra { 1422 FILE *out; 1423 int mls; 1424 }; 1425 1426 static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 1427 { 1428 struct te_rules_extra *args = extra_args; 1429 1430 switch (node->flavor) { 1431 case CIL_BLOCK: { 1432 struct cil_block *blk = node->data; 1433 if (blk->is_abstract == CIL_TRUE) { 1434 *finished = CIL_TREE_SKIP_HEAD; 1435 } 1436 break; 1437 } 1438 case CIL_MACRO: 1439 *finished = CIL_TREE_SKIP_HEAD; 1440 break; 1441 case CIL_BOOLEANIF: { 1442 struct cil_booleanif *bool = node->data; 1443 struct cil_tree_node *n; 1444 struct cil_condblock *cb; 1445 1446 fprintf(args->out, "if "); 1447 cil_cond_expr_to_policy(args->out, bool->datum_expr, CIL_TRUE); 1448 fprintf(args->out," {\n"); 1449 n = node->cl_head; 1450 cb = n != NULL ? n->data : NULL; 1451 if (cb && cb->flavor == CIL_CONDTRUE) { 1452 cil_block_te_rules_to_policy(args->out, n, args->mls); 1453 n = n->next; 1454 cb = n != NULL ? n->data : NULL; 1455 } 1456 if (cb && cb->flavor == CIL_CONDFALSE) { 1457 fprintf(args->out,"} else {\n"); 1458 cil_block_te_rules_to_policy(args->out, n, args->mls); 1459 } 1460 fprintf(args->out,"}\n"); 1461 *finished = CIL_TREE_SKIP_HEAD; 1462 break; 1463 } 1464 default: 1465 break; 1466 } 1467 1468 return SEPOL_OK; 1469 } 1470 1471 static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls) 1472 { 1473 struct te_rules_extra args; 1474 1475 args.out = out; 1476 args.mls = mls; 1477 1478 cil_block_te_rules_to_policy(out, head, mls); 1479 cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args); 1480 } 1481 1482 static void cil_roles_to_policy(FILE *out, struct cil_list *rules) 1483 { 1484 struct cil_list_item *i1; 1485 struct cil_role *role; 1486 1487 cil_list_for_each(i1, rules) { 1488 role = i1->data; 1489 if (strcmp(role->datum.fqn,"object_r") == 0) 1490 continue; 1491 fprintf(out, "role %s;\n", role->datum.fqn); 1492 } 1493 } 1494 1495 static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types) 1496 { 1497 struct cil_list_item *i1, *i2; 1498 struct cil_role *role; 1499 struct cil_type *type; 1500 int first = CIL_TRUE; 1501 1502 cil_list_for_each(i1, roles) { 1503 role = i1->data; 1504 if (strcmp(role->datum.fqn,"object_r") == 0) 1505 continue; 1506 if (role->types) { 1507 cil_list_for_each(i2, types) { 1508 type = i2->data; 1509 if (ebitmap_get_bit(role->types, type->value)) { 1510 if (first) { 1511 fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn); 1512 first = CIL_FALSE; 1513 } else { 1514 fprintf(out, " %s", type->datum.fqn); 1515 } 1516 } 1517 } 1518 if (!first) { 1519 fprintf(out, " }"); 1520 first = CIL_TRUE; 1521 } 1522 fprintf(out, ";\n"); 1523 } 1524 } 1525 } 1526 1527 static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes) 1528 { 1529 struct cil_list_item *i1, *i2; 1530 struct cil_role *role; 1531 struct cil_roleattribute *attribute; 1532 int first = CIL_TRUE; 1533 1534 cil_list_for_each(i1, roles) { 1535 role = i1->data; 1536 if (strcmp(role->datum.fqn,"object_r") == 0) 1537 continue; 1538 cil_list_for_each(i2, attributes) { 1539 attribute = i2->data; 1540 if (ebitmap_get_bit(attribute->roles, role->value)) { 1541 if (first) { 1542 fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn); 1543 first = CIL_FALSE; 1544 } else { 1545 fprintf(out, ", %s", attribute->datum.fqn); 1546 } 1547 } 1548 } 1549 if (!first) { 1550 fprintf(out, ";\n"); 1551 first = CIL_TRUE; 1552 } 1553 } 1554 } 1555 1556 static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows) 1557 { 1558 struct cil_list_item *i1; 1559 struct cil_roleallow *allow; 1560 1561 cil_list_for_each(i1, roleallows) { 1562 allow = i1->data; 1563 fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn); 1564 } 1565 } 1566 1567 static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions) 1568 { 1569 struct cil_list_item *i1, *i2; 1570 struct cil_list *class_list; 1571 struct cil_roletransition *trans; 1572 1573 1574 cil_list_for_each(i1, roletransitions) { 1575 trans = i1->data; 1576 class_list = cil_expand_class(trans->obj); 1577 cil_list_for_each(i2, class_list) { 1578 fprintf(out, "role_transition %s %s : %s %s;\n", DATUM(trans->src)->fqn, DATUM(trans->tgt)->fqn, DATUM(i2->data)->fqn, DATUM(trans->result)->fqn); 1579 } 1580 cil_list_destroy(&class_list, CIL_FALSE); 1581 } 1582 } 1583 1584 static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles) 1585 { 1586 struct cil_list_item *i1, *i2; 1587 struct cil_user *user; 1588 struct cil_list *roles = NULL; 1589 struct cil_role *role; 1590 int num_roles; 1591 1592 cil_list_for_each(i1, users) { 1593 user = i1->data; 1594 num_roles = 0; 1595 fprintf(out, "user %s",user->datum.fqn); 1596 cil_list_for_each(i2, all_roles) { 1597 role = i2->data; 1598 if (ebitmap_get_bit(user->roles, role->value)) { 1599 if (num_roles == 0) { 1600 cil_list_init(&roles, CIL_LIST); 1601 } 1602 cil_list_append(roles, CIL_ROLE, role); 1603 num_roles++; 1604 } 1605 } 1606 if (num_roles > 0) { 1607 fprintf(out, " roles"); 1608 if (num_roles > 1) { 1609 fprintf(out, " {"); 1610 } 1611 cil_list_for_each(i2, roles) { 1612 role = i2->data; 1613 fprintf(out, " %s", role->datum.fqn); 1614 } 1615 if (num_roles > 1) { 1616 fprintf(out, " }"); 1617 } 1618 cil_list_destroy(&roles, CIL_FALSE); 1619 } 1620 1621 if (mls == CIL_TRUE && user->dftlevel != NULL) { 1622 fprintf(out, " level "); 1623 cil_level_to_policy(out, user->dftlevel); 1624 } 1625 1626 if (mls == CIL_TRUE && user->range != NULL) { 1627 fprintf(out, " range "); 1628 cil_levelrange_to_policy(out, user->range); 1629 } 1630 1631 fprintf(out,";\n"); 1632 } 1633 } 1634 1635 static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains) 1636 { 1637 struct cil_list_item *i1, *i2; 1638 struct cil_constrain *cons; 1639 struct cil_list *classperms_strs; 1640 char *cp_str; 1641 char *expr_str; 1642 1643 cil_list_for_each(i1, constrains) { 1644 cons = i1->data; 1645 cil_list_init(&classperms_strs, CIL_LIST); 1646 cil_classperms_to_strings(cons->classperms, classperms_strs); 1647 expr_str = cil_cons_expr_to_string(db, cons->datum_expr); 1648 cil_list_for_each(i2, classperms_strs) { 1649 cp_str = i2->data; 1650 fprintf(out, "constrain %s %s;\n",cp_str, expr_str); 1651 free(cp_str); 1652 } 1653 free(expr_str); 1654 cil_list_destroy(&classperms_strs, CIL_FALSE); 1655 } 1656 } 1657 1658 static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls) 1659 { 1660 struct cil_list_item *i1; 1661 struct cil_sid *sid; 1662 1663 cil_list_for_each(i1, sids) { 1664 sid = i1->data; 1665 fprintf(out, "sid %s ", sid->datum.fqn); 1666 cil_context_to_policy(out, sid->context, mls); 1667 fprintf(out,"\n"); 1668 } 1669 } 1670 1671 static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls) 1672 { 1673 unsigned i; 1674 struct cil_fsuse *fsuse; 1675 1676 for (i=0; i<fsuses->count; i++) { 1677 fsuse = fsuses->array[i]; 1678 if (fsuse->type == CIL_FSUSE_XATTR) { 1679 fprintf(out, "fs_use_xattr %s ", fsuse->fs_str); 1680 cil_context_to_policy(out, fsuse->context, mls); 1681 fprintf(out,";\n"); 1682 } 1683 } 1684 1685 for (i=0; i<fsuses->count; i++) { 1686 fsuse = fsuses->array[i]; 1687 if (fsuse->type == CIL_FSUSE_TASK) { 1688 fprintf(out, "fs_use_task %s ", fsuse->fs_str); 1689 cil_context_to_policy(out, fsuse->context, mls); 1690 fprintf(out,";\n"); 1691 } 1692 } 1693 1694 for (i=0; i<fsuses->count; i++) { 1695 fsuse = fsuses->array[i]; 1696 if (fsuse->type == CIL_FSUSE_TRANS) { 1697 fprintf(out, "fs_use_trans %s ", fsuse->fs_str); 1698 cil_context_to_policy(out, fsuse->context, mls); 1699 fprintf(out,";\n"); 1700 } 1701 } 1702 } 1703 1704 static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls) 1705 { 1706 unsigned i; 1707 struct cil_genfscon *genfscon; 1708 1709 for (i=0; i<genfscons->count; i++) { 1710 genfscon = genfscons->array[i]; 1711 fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str); 1712 cil_context_to_policy(out, genfscon->context, mls); 1713 fprintf(out, "\n"); 1714 } 1715 } 1716 1717 static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls) 1718 { 1719 unsigned i; 1720 struct cil_portcon *portcon; 1721 1722 for (i=0; i<portcons->count; i++) { 1723 portcon = portcons->array[i]; 1724 fprintf(out, "portcon "); 1725 if (portcon->proto == CIL_PROTOCOL_UDP) { 1726 fprintf(out, "udp "); 1727 } else if (portcon->proto == CIL_PROTOCOL_TCP) { 1728 fprintf(out, "tcp "); 1729 } else if (portcon->proto == CIL_PROTOCOL_DCCP) { 1730 fprintf(out, "dccp "); 1731 } 1732 if (portcon->port_low == portcon->port_high) { 1733 fprintf(out, "%d ", portcon->port_low); 1734 } else { 1735 fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high); 1736 } 1737 cil_context_to_policy(out, portcon->context, mls); 1738 fprintf(out, "\n"); 1739 } 1740 } 1741 1742 static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls) 1743 { 1744 unsigned i; 1745 struct cil_netifcon *netifcon; 1746 1747 for (i=0; i<netifcons->count; i++) { 1748 netifcon = netifcons->array[i]; 1749 fprintf(out, "netifcon %s ", netifcon->interface_str); 1750 cil_context_to_policy(out, netifcon->if_context, mls); 1751 fprintf(out, " "); 1752 cil_context_to_policy(out, netifcon->packet_context, mls); 1753 fprintf(out, ";\n"); 1754 } 1755 } 1756 1757 static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls) 1758 { 1759 unsigned i; 1760 struct cil_nodecon *nodecon; 1761 char *addr, *mask; 1762 1763 for (i=0; i<nodecons->count; i++) { 1764 nodecon = nodecons->array[i]; 1765 fprintf(out, "nodecon "); 1766 1767 if (nodecon->addr->family == AF_INET) { 1768 errno = 0; 1769 addr = cil_malloc(INET_ADDRSTRLEN); 1770 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN); 1771 if (errno == 0) { 1772 fprintf(out, "%s ",addr); 1773 } else { 1774 fprintf(out, "[INVALID] "); 1775 } 1776 free(addr); 1777 1778 errno = 0; 1779 mask = cil_malloc(INET_ADDRSTRLEN); 1780 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN); 1781 if (errno == 0) { 1782 fprintf(out, "%s ",mask); 1783 } else { 1784 fprintf(out, "[INVALID] "); 1785 } 1786 free(mask); 1787 } else { 1788 errno = 0; 1789 addr = cil_malloc(INET6_ADDRSTRLEN); 1790 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN); 1791 if (errno == 0) { 1792 fprintf(out, "%s ",addr); 1793 } else { 1794 fprintf(out, "[INVALID] "); 1795 } 1796 free(addr); 1797 1798 errno = 0; 1799 mask = cil_malloc(INET6_ADDRSTRLEN); 1800 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN); 1801 if (errno == 0) { 1802 fprintf(out, "%s ",mask); 1803 } else { 1804 fprintf(out, "[INVALID] "); 1805 } 1806 free(mask); 1807 } 1808 1809 cil_context_to_policy(out, nodecon->context, mls); 1810 fprintf(out, ";\n"); 1811 } 1812 } 1813 1814 static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls) 1815 { 1816 unsigned i; 1817 struct cil_pirqcon *pirqcon; 1818 1819 for (i = 0; i<pirqcons->count; i++) { 1820 pirqcon = pirqcons->array[i]; 1821 fprintf(out, "pirqcon %d ", pirqcon->pirq); 1822 cil_context_to_policy(out, pirqcon->context, mls); 1823 fprintf(out, ";\n"); 1824 } 1825 } 1826 1827 static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls) 1828 { 1829 unsigned i; 1830 struct cil_iomemcon *iomemcon; 1831 1832 for (i = 0; i<iomemcons->count; i++) { 1833 iomemcon = iomemcons->array[i]; 1834 if (iomemcon->iomem_low == iomemcon->iomem_high) { 1835 fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low); 1836 } else { 1837 fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high); 1838 } 1839 cil_context_to_policy(out, iomemcon->context, mls); 1840 fprintf(out, ";\n"); 1841 } 1842 } 1843 1844 static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls) 1845 { 1846 unsigned i; 1847 struct cil_ioportcon *ioportcon; 1848 1849 for (i = 0; i < ioportcons->count; i++) { 1850 ioportcon = ioportcons->array[i]; 1851 fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high); 1852 cil_context_to_policy(out, ioportcon->context, mls); 1853 fprintf(out, ";\n"); 1854 } 1855 } 1856 1857 static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls) 1858 { 1859 unsigned i; 1860 struct cil_pcidevicecon *pcidevicecon; 1861 1862 for (i = 0; i < pcidevicecons->count; i++) { 1863 pcidevicecon = pcidevicecons->array[i]; 1864 fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev); 1865 cil_context_to_policy(out, pcidevicecon->context, mls); 1866 fprintf(out, ";\n"); 1867 } 1868 } 1869 1870 static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls) 1871 { 1872 unsigned i; 1873 struct cil_devicetreecon *devicetreecon; 1874 1875 for (i = 0; i < devicetreecons->count; i++) { 1876 devicetreecon = devicetreecons->array[i]; 1877 fprintf(out, "devicetreecon %s ", devicetreecon->path); 1878 cil_context_to_policy(out, devicetreecon->context, mls); 1879 fprintf(out, ";\n"); 1880 } 1881 } 1882 1883 void cil_gen_policy(FILE *out, struct cil_db *db) 1884 { 1885 unsigned i; 1886 struct cil_tree_node *head = db->ast->root; 1887 struct cil_list *lists[CIL_LIST_NUM_LISTS]; 1888 1889 for (i=0; i<CIL_LIST_NUM_LISTS; i++) { 1890 cil_list_init(&lists[i], CIL_LIST); 1891 } 1892 1893 cil_gather_statements(head, lists); 1894 1895 cil_class_decls_to_policy(out, db->classorder); 1896 1897 cil_sid_decls_to_policy(out, db->sidorder); 1898 1899 cil_commons_to_policy(out, lists[CIL_LIST_COMMON]); 1900 cil_classes_to_policy(out, db->classorder); 1901 1902 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], CIL_KEY_DEFAULTUSER); 1903 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], CIL_KEY_DEFAULTROLE); 1904 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], CIL_KEY_DEFAULTTYPE); 1905 1906 if (db->mls == CIL_TRUE) { 1907 cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]); 1908 cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]); 1909 cil_dominance_to_policy(out, db->sensitivityorder); 1910 cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]); 1911 cil_levels_to_policy(out, db->sensitivityorder); 1912 cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]); 1913 cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS); 1914 } 1915 1916 cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP); 1917 1918 cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute"); 1919 cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role"); 1920 1921 cil_bools_to_policy(out, lists[CIL_LIST_BOOL]); 1922 1923 cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type"); 1924 cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]); 1925 cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]); 1926 cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]); 1927 cil_te_rules_to_policy(out, head, db->mls); 1928 1929 cil_roles_to_policy(out, lists[CIL_LIST_ROLE]); 1930 cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]); 1931 cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]); 1932 cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]); 1933 cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]); 1934 1935 cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]); 1936 1937 cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]); 1938 cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS); 1939 1940 cil_sid_contexts_to_policy(out, db->sidorder, db->mls); 1941 cil_fsuses_to_policy(out, db->fsuse, db->mls); 1942 cil_genfscons_to_policy(out, db->genfscon, db->mls); 1943 cil_portcons_to_policy(out, db->portcon, db->mls); 1944 cil_netifcons_to_policy(out, db->netifcon, db->mls); 1945 cil_nodecons_to_policy(out, db->nodecon, db->mls); 1946 cil_pirqcons_to_policy(out, db->pirqcon, db->mls); 1947 cil_iomemcons_to_policy(out, db->iomemcon, db->mls); 1948 cil_ioportcons_to_policy(out, db->ioportcon, db->mls); 1949 cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls); 1950 cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls); 1951 1952 for (i=0; i<CIL_LIST_NUM_LISTS; i++) { 1953 cil_list_destroy(&lists[i], CIL_FALSE); 1954 } 1955 1956 } 1957