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 <ctype.h> 36 37 #include <sepol/policydb/polcaps.h> 38 #include <sepol/errcodes.h> 39 40 #include "cil_internal.h" 41 #include "cil_flavor.h" 42 #include "cil_log.h" 43 #include "cil_mem.h" 44 #include "cil_tree.h" 45 #include "cil_list.h" 46 #include "cil_find.h" 47 48 #include "cil_verify.h" 49 50 int __cil_verify_name(const char *name) 51 { 52 int rc = SEPOL_ERR; 53 int len; 54 int i = 0; 55 56 if (name == NULL) { 57 cil_log(CIL_ERR, "Name is NULL\n"); 58 goto exit; 59 } 60 61 len = strlen(name); 62 if (len >= CIL_MAX_NAME_LENGTH) { 63 cil_log(CIL_ERR, "Name length greater than max name length of %d", 64 CIL_MAX_NAME_LENGTH); 65 rc = SEPOL_ERR; 66 goto exit; 67 } 68 69 if (!isalpha(name[0])) { 70 cil_log(CIL_ERR, "First character in %s is not a letter\n", name); 71 goto exit; 72 } 73 74 for (i = 1; i < len; i++) { 75 if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') { 76 cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name); 77 goto exit; 78 } 79 } 80 return SEPOL_OK; 81 82 exit: 83 cil_log(CIL_ERR, "Invalid name\n"); 84 return rc; 85 } 86 87 int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len) 88 { 89 int rc = SEPOL_ERR; 90 int num_extras = 0; 91 struct cil_tree_node *c = parse_current; 92 int i = 0; 93 while (i < len) { 94 if ((s[i] & CIL_SYN_END) && c == NULL) { 95 break; 96 } 97 98 if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) { 99 if (c == NULL) { 100 if (num_extras > 0) { 101 i++; 102 continue; 103 } else { 104 goto exit; 105 } 106 } else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) { 107 c = c->next; 108 num_extras++; 109 continue; 110 } else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) { 111 c = c->next; 112 num_extras++; 113 continue; 114 } 115 } 116 117 if (c == NULL) { 118 goto exit; 119 } 120 121 if (s[i] & CIL_SYN_STRING) { 122 if (c->data != NULL && c->cl_head == NULL) { 123 c = c->next; 124 i++; 125 continue; 126 } 127 } 128 129 if (s[i] & CIL_SYN_LIST) { 130 if (c->data == NULL && c->cl_head != NULL) { 131 c = c->next; 132 i++; 133 continue; 134 } 135 } 136 137 if (s[i] & CIL_SYN_EMPTY_LIST) { 138 if (c->data == NULL && c->cl_head == NULL) { 139 c = c->next; 140 i++; 141 continue; 142 } 143 } 144 goto exit; 145 } 146 return SEPOL_OK; 147 148 exit: 149 cil_log(CIL_ERR, "Invalid syntax\n"); 150 return rc; 151 } 152 153 int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor) 154 { 155 int rc; 156 enum cil_syntax syntax[] = { 157 CIL_SYN_STRING, 158 CIL_SYN_STRING | CIL_SYN_LIST, 159 CIL_SYN_STRING | CIL_SYN_LIST, 160 CIL_SYN_END 161 }; 162 int syntax_len = sizeof(syntax)/sizeof(*syntax); 163 164 switch (op) { 165 case CIL_NOT: 166 syntax[2] = CIL_SYN_END; 167 syntax_len = 3; 168 break; 169 case CIL_AND: 170 case CIL_OR: 171 case CIL_XOR: 172 break; 173 case CIL_EQ: 174 case CIL_NEQ: 175 if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) { 176 cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data); 177 goto exit; 178 } 179 break; 180 case CIL_ALL: 181 if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) { 182 cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data); 183 goto exit; 184 } 185 syntax[1] = CIL_SYN_END; 186 syntax_len = 2; 187 break; 188 case CIL_RANGE: 189 if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) { 190 cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data); 191 goto exit; 192 } 193 syntax[1] = CIL_SYN_STRING; 194 syntax[2] = CIL_SYN_STRING; 195 break; 196 case CIL_NONE: /* String or List */ 197 syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS; 198 syntax[1] = CIL_SYN_END; 199 syntax_len = 2; 200 break; 201 default: 202 cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data); 203 goto exit; 204 } 205 206 rc = __cil_verify_syntax(current, syntax, syntax_len); 207 if (rc != SEPOL_OK) { 208 goto exit; 209 } 210 211 return SEPOL_OK; 212 213 exit: 214 return SEPOL_ERR; 215 } 216 217 int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor) 218 { 219 if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) { 220 if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) { 221 cil_log(CIL_ERR, "l1, l2, h1, and h2 cannot be used on the left side with a string or list on the right side\n"); 222 goto exit; 223 } else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) { 224 if (expr_flavor != CIL_MLSVALIDATETRANS) { 225 cil_log(CIL_ERR, "u3, r3, and t3 can only be used with mlsvalidatetrans rules\n"); 226 goto exit; 227 } 228 } 229 } else { 230 if (r_flavor == CIL_CONS_U2) { 231 if (op != CIL_EQ && op != CIL_NEQ) { 232 cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n"); 233 goto exit; 234 } else if (l_flavor != CIL_CONS_U1) { 235 cil_log(CIL_ERR, "u2 on the right side must be used with u1 on the left\n"); 236 goto exit; 237 } 238 } else if (r_flavor == CIL_CONS_R2) { 239 if (l_flavor != CIL_CONS_R1) { 240 cil_log(CIL_ERR, "r2 on the right side must be used with r1 on the left\n"); 241 goto exit; 242 } 243 } else if (r_flavor == CIL_CONS_T2) { 244 if (op != CIL_EQ && op != CIL_NEQ) { 245 cil_log(CIL_ERR, "t2 on the right side must be used with eq or neq as the operator\n"); 246 goto exit; 247 } else if (l_flavor != CIL_CONS_T1) { 248 cil_log(CIL_ERR, "t2 on the right side must be used with t1 on the left\n"); 249 goto exit; 250 } 251 } else if (r_flavor == CIL_CONS_L2) { 252 if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_H1) { 253 cil_log(CIL_ERR, "l2 on the right side must be used with l1 or h1 on the left\n"); 254 goto exit; 255 } 256 } else if (r_flavor == CIL_CONS_H2) { 257 if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_L2 && l_flavor != CIL_CONS_H1 ) { 258 cil_log(CIL_ERR, "h2 on the right side must be used with l1, l2, or h1 on the left\n"); 259 goto exit; 260 } 261 } else if (r_flavor == CIL_CONS_H1) { 262 if (l_flavor != CIL_CONS_L1) { 263 cil_log(CIL_ERR, "h1 on the right side must be used with l1 on the left\n"); 264 goto exit; 265 } 266 } 267 } 268 269 return SEPOL_OK; 270 271 exit: 272 return SEPOL_ERR; 273 } 274 275 int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op) 276 { 277 int rc; 278 enum cil_syntax syntax[] = { 279 CIL_SYN_STRING, 280 CIL_SYN_END, 281 CIL_SYN_END, 282 CIL_SYN_END 283 }; 284 int syntax_len = sizeof(syntax)/sizeof(*syntax); 285 286 switch (op) { 287 case CIL_NOT: 288 syntax[1] = CIL_SYN_LIST; 289 syntax_len--; 290 break; 291 case CIL_AND: 292 case CIL_OR: 293 syntax[1] = CIL_SYN_LIST; 294 syntax[2] = CIL_SYN_LIST; 295 break; 296 case CIL_EQ: 297 case CIL_NEQ: 298 syntax[1] = CIL_SYN_STRING; 299 syntax[2] = CIL_SYN_STRING | CIL_SYN_LIST; 300 break; 301 case CIL_CONS_DOM: 302 case CIL_CONS_DOMBY: 303 case CIL_CONS_INCOMP: 304 syntax[1] = CIL_SYN_STRING; 305 syntax[2] = CIL_SYN_STRING; 306 break; 307 default: 308 cil_log(CIL_ERR, "Invalid operator (%s) for constraint expression\n", (char*)current->data); 309 goto exit; 310 } 311 312 rc = __cil_verify_syntax(current, syntax, syntax_len); 313 if (rc != SEPOL_OK) { 314 cil_log(CIL_ERR, "Invalid constraint syntax\n"); 315 goto exit; 316 } 317 318 return SEPOL_OK; 319 320 exit: 321 return SEPOL_ERR; 322 } 323 324 int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list) 325 { 326 struct cil_list_item *i; 327 328 cil_list_for_each(i, datum_list) { 329 if (i->flavor == CIL_DATUM) { 330 struct cil_symtab_datum *d = i->data; 331 if (d == datum) { 332 cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name); 333 return SEPOL_ERR; 334 } 335 } else if (i->flavor == CIL_LIST) { 336 int rc = cil_verify_no_self_reference(datum, i->data); 337 if (rc != SEPOL_OK) { 338 return SEPOL_ERR; 339 } 340 } 341 } 342 343 return SEPOL_OK; 344 } 345 346 int __cil_verify_ranges(struct cil_list *list) 347 { 348 int rc = SEPOL_ERR; 349 struct cil_list_item *curr; 350 struct cil_list_item *range = NULL; 351 352 if (list == NULL || list->head == NULL) { 353 goto exit; 354 } 355 356 cil_list_for_each(curr, list) { 357 /* range */ 358 if (curr->flavor == CIL_LIST) { 359 range = ((struct cil_list*)curr->data)->head; 360 if (range == NULL || range->next == NULL || range->next->next != NULL) { 361 goto exit; 362 } 363 } 364 } 365 366 return SEPOL_OK; 367 368 exit: 369 cil_log(CIL_ERR,"Invalid Range syntax\n"); 370 return rc; 371 } 372 373 struct cil_args_verify_order { 374 uint32_t *flavor; 375 }; 376 377 int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args) 378 { 379 struct cil_args_verify_order *args = extra_args; 380 uint32_t *flavor = args->flavor; 381 382 if (node->flavor == *flavor) { 383 if (node->flavor == CIL_SID) { 384 struct cil_sid *sid = node->data; 385 if (sid->ordered == CIL_FALSE) { 386 cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name); 387 return SEPOL_ERR; 388 } 389 } else if (node->flavor == CIL_CLASS) { 390 struct cil_class *class = node->data; 391 if (class->ordered == CIL_FALSE) { 392 cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name); 393 return SEPOL_ERR; 394 } 395 } else if (node->flavor == CIL_CAT) { 396 struct cil_cat *cat = node->data; 397 if (cat->ordered == CIL_FALSE) { 398 cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name); 399 return SEPOL_ERR; 400 } 401 } else if (node->flavor == CIL_SENS) { 402 struct cil_sens *sens = node->data; 403 if (sens->ordered == CIL_FALSE) { 404 cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name); 405 return SEPOL_ERR; 406 } 407 } 408 } 409 410 return SEPOL_OK; 411 } 412 413 int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor) 414 { 415 struct cil_args_verify_order extra_args; 416 int rc = SEPOL_ERR; 417 418 extra_args.flavor = &flavor; 419 420 rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args); 421 422 return rc; 423 } 424 425 int __cil_verify_initsids(struct cil_list *sids) 426 { 427 int rc = SEPOL_OK; 428 struct cil_list_item *i; 429 430 if (sids->head == NULL) { 431 cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n"); 432 return SEPOL_ERR; 433 } 434 435 cil_list_for_each(i, sids) { 436 struct cil_sid *sid = i->data; 437 if (sid->context == NULL) { 438 struct cil_tree_node *node = sid->datum.nodes->head->data; 439 cil_tree_log(node, CIL_ERR, "No context assigned to SID %s declared",sid->datum.name); 440 rc = SEPOL_ERR; 441 } 442 } 443 444 return rc; 445 } 446 447 int __cil_is_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats) 448 { 449 struct cil_list_item *i; 450 451 cil_list_for_each(i, cats->datum_expr) { 452 struct cil_cat *c = i->data; 453 if (c == cat) { 454 return CIL_TRUE; 455 } 456 } 457 458 return CIL_FALSE; 459 } 460 461 462 int __cil_verify_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats) 463 { 464 if (__cil_is_cat_in_cats(cat, cats) != CIL_TRUE) { 465 cil_log(CIL_ERR, "Failed to find category %s in category list\n", cat->datum.name); 466 return SEPOL_ERR; 467 } 468 469 return SEPOL_OK; 470 } 471 472 int __cil_verify_cats_associated_with_sens(struct cil_sens *sens, struct cil_cats *cats) 473 { 474 int rc = SEPOL_OK; 475 struct cil_list_item *i, *j; 476 477 if (!cats) { 478 return SEPOL_OK; 479 } 480 481 if (!sens->cats_list) { 482 cil_log(CIL_ERR, "No categories can be used with sensitivity %s\n", sens->datum.name); 483 return SEPOL_ERR; 484 } 485 486 cil_list_for_each(i, cats->datum_expr) { 487 struct cil_cat *cat = i->data; 488 int ok = CIL_FALSE; 489 cil_list_for_each(j, sens->cats_list) { 490 if (__cil_is_cat_in_cats(cat, j->data) == CIL_TRUE) { 491 ok = CIL_TRUE; 492 break; 493 } 494 } 495 496 if (ok != CIL_TRUE) { 497 cil_log(CIL_ERR, "Category %s cannot be used with sensitivity %s\n", 498 cat->datum.name, sens->datum.name); 499 rc = SEPOL_ERR; 500 } 501 } 502 503 return rc; 504 } 505 506 int __cil_verify_levelrange_sensitivity(struct cil_db *db, struct cil_sens *low, struct cil_sens *high) 507 { 508 struct cil_list_item *curr; 509 int found = CIL_FALSE; 510 int rc = SEPOL_ERR; 511 512 cil_list_for_each(curr, db->sensitivityorder) { 513 if (curr->data == low) { 514 found = CIL_TRUE; 515 } 516 517 if ((found == CIL_TRUE) && (curr->data == high)) { 518 break; 519 } 520 } 521 522 if (found != CIL_TRUE || curr == NULL) { 523 goto exit; 524 } 525 526 return SEPOL_OK; 527 528 exit: 529 cil_log(CIL_ERR, "Sensitivity %s does not dominate %s\n", 530 high->datum.name, low->datum.name); 531 return rc; 532 533 } 534 535 int __cil_verify_levelrange_cats(struct cil_cats *low, struct cil_cats *high) 536 { 537 int rc = SEPOL_ERR; 538 struct cil_list_item *item; 539 540 if (low == NULL || (low == NULL && high == NULL)) { 541 return SEPOL_OK; 542 } 543 544 if (high == NULL) { 545 rc = SEPOL_ERR; 546 goto exit; 547 } 548 549 cil_list_for_each(item, low->datum_expr) { 550 rc = __cil_verify_cat_in_cats(item->data, high); 551 if (rc != SEPOL_OK) { 552 goto exit; 553 } 554 } 555 556 return SEPOL_OK; 557 558 exit: 559 cil_log(CIL_ERR, "Low level category set must be a subset of the high level category set\n"); 560 return rc; 561 } 562 563 int __cil_verify_levelrange(struct cil_db *db, struct cil_levelrange *lr) 564 { 565 int rc = SEPOL_ERR; 566 567 rc = __cil_verify_levelrange_sensitivity(db, lr->low->sens, lr->high->sens); 568 if (rc != SEPOL_OK) { 569 goto exit; 570 } 571 572 rc = __cil_verify_levelrange_cats(lr->low->cats, lr->high->cats); 573 if (rc != SEPOL_OK) { 574 goto exit; 575 } 576 577 rc = __cil_verify_cats_associated_with_sens(lr->low->sens, lr->low->cats); 578 if (rc != SEPOL_OK) { 579 cil_log(CIL_ERR, "Low level sensitivity and categories are not associated\n"); 580 goto exit; 581 } 582 583 rc = __cil_verify_cats_associated_with_sens(lr->high->sens, lr->high->cats); 584 if (rc != SEPOL_OK) { 585 cil_log(CIL_ERR, "High level sensitivity and categories are not associated\n"); 586 goto exit; 587 } 588 589 return SEPOL_OK; 590 591 exit: 592 return rc; 593 } 594 595 int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node) 596 { 597 int rc = SEPOL_ERR; 598 struct cil_levelrange *lr = node->data; 599 600 rc = __cil_verify_levelrange(db, lr); 601 if (rc != SEPOL_OK) { 602 goto exit; 603 } 604 605 return SEPOL_OK; 606 exit: 607 cil_tree_log(node, CIL_ERR, "Invalid named range"); 608 return rc; 609 } 610 611 static int __cil_verify_user_pre_eval(struct cil_tree_node *node) 612 { 613 int rc = SEPOL_ERR; 614 struct cil_user *user = node->data; 615 616 if (user->dftlevel == NULL) { 617 cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name); 618 goto exit; 619 } else if (user->range == NULL) { 620 cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name); 621 goto exit; 622 } else if (user->bounds != NULL) { 623 int steps = 0; 624 int limit = 2; 625 struct cil_user *u1 = user; 626 struct cil_user *u2 = user->bounds; 627 628 while (u2 != NULL) { 629 if (u1 == u2) { 630 cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name); 631 goto exit; 632 } 633 634 if (steps == limit) { 635 steps = 0; 636 limit *= 2; 637 u1 = u2; 638 } 639 640 u2 = u2->bounds; 641 steps++; 642 } 643 } 644 645 return SEPOL_OK; 646 exit: 647 cil_tree_log(node, CIL_ERR, "Invalid user"); 648 return rc; 649 } 650 651 static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node) 652 { 653 int rc = SEPOL_ERR; 654 struct cil_user *user = node->data; 655 656 /* Verify user range only if anonymous */ 657 if (user->range->datum.name == NULL) { 658 rc = __cil_verify_levelrange(db, user->range); 659 if (rc != SEPOL_OK) { 660 goto exit; 661 } 662 } 663 664 return SEPOL_OK; 665 exit: 666 cil_tree_log(node, CIL_ERR, "Invalid user"); 667 return rc; 668 } 669 670 int __cil_verify_role(struct cil_tree_node *node) 671 { 672 int rc = SEPOL_ERR; 673 struct cil_role *role = node->data; 674 int steps = 0; 675 int limit = 2; 676 struct cil_role *r1 = role; 677 struct cil_role *r2 = role->bounds; 678 679 while (r2 != NULL) { 680 if (r1 == r2) { 681 cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name); 682 goto exit; 683 } 684 685 if (steps == limit) { 686 steps = 0; 687 limit *= 2; 688 r1 = r2; 689 } 690 691 r2 = r2->bounds; 692 steps++; 693 } 694 695 return SEPOL_OK; 696 exit: 697 cil_tree_log(node, CIL_ERR, "Invalid role"); 698 return rc; 699 } 700 701 int __cil_verify_type(struct cil_tree_node *node) 702 { 703 int rc = SEPOL_ERR; 704 struct cil_type *type = node->data; 705 int steps = 0; 706 int limit = 2; 707 struct cil_type *t1 = type; 708 struct cil_type *t2 = type->bounds; 709 710 while (t2 != NULL) { 711 if (t1 == t2) { 712 cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name); 713 goto exit; 714 } 715 716 if (steps == limit) { 717 steps = 0; 718 limit *= 2; 719 t1 = t2; 720 } 721 722 t2 = t2->bounds; 723 steps++; 724 } 725 726 return SEPOL_OK; 727 exit: 728 cil_tree_log(node, CIL_ERR, "Invalid type"); 729 return rc; 730 } 731 732 int __cil_verify_context(struct cil_db *db, struct cil_context *ctx) 733 { 734 int rc = SEPOL_ERR; 735 struct cil_user *user = ctx->user; 736 struct cil_role *role = ctx->role; 737 struct cil_type *type = ctx->type; 738 struct cil_level *user_low = user->range->low; 739 struct cil_level *user_high = user->range->high; 740 struct cil_level *ctx_low = ctx->range->low; 741 struct cil_level *ctx_high = ctx->range->high; 742 struct cil_list *sensitivityorder = db->sensitivityorder; 743 struct cil_list_item *curr; 744 int found = CIL_FALSE; 745 746 if (user->roles != NULL) { 747 if (!ebitmap_get_bit(user->roles, role->value)) { 748 cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str); 749 rc = SEPOL_ERR; 750 goto exit; 751 } 752 } else { 753 cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str); 754 rc = SEPOL_ERR; 755 goto exit; 756 } 757 758 if (role->types != NULL) { 759 if (!ebitmap_get_bit(role->types, type->value)) { 760 cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str); 761 rc = SEPOL_ERR; 762 goto exit; 763 } 764 } else { 765 cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str); 766 rc = SEPOL_ERR; 767 goto exit; 768 } 769 770 /* Verify range only when anonymous */ 771 if (ctx->range->datum.name == NULL) { 772 rc = __cil_verify_levelrange(db, ctx->range); 773 if (rc != SEPOL_OK) { 774 goto exit; 775 } 776 } 777 778 for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) { 779 struct cil_sens *sens = curr->data; 780 781 if (found == CIL_FALSE) { 782 if (sens == user_low->sens) { 783 found = CIL_TRUE; 784 } else if (sens == ctx_low->sens) { 785 cil_log(CIL_ERR, "Range %s is invalid for user %s\n", 786 ctx->range_str, ctx->user_str); 787 rc = SEPOL_ERR; 788 goto exit; 789 } 790 } 791 792 if (found == CIL_TRUE) { 793 if (sens == ctx_high->sens) { 794 break; 795 } else if (sens == user_high->sens) { 796 cil_log(CIL_ERR, "Range %s is invalid for user %s\n", 797 ctx->range_str, ctx->user_str); 798 rc = SEPOL_ERR; 799 goto exit; 800 } 801 } 802 } 803 804 return SEPOL_OK; 805 exit: 806 cil_log(CIL_ERR, "Invalid context\n"); 807 return rc; 808 } 809 810 int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node) 811 { 812 int rc = SEPOL_ERR; 813 struct cil_context *ctx = node->data; 814 815 rc = __cil_verify_context(db, ctx); 816 if (rc != SEPOL_OK) { 817 goto exit; 818 } 819 820 return SEPOL_OK; 821 exit: 822 cil_tree_log(node, CIL_ERR, "Invalid named context"); 823 return rc; 824 } 825 826 int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab) 827 { 828 829 int rc = SEPOL_ERR; 830 struct cil_type_rule *typerule = NULL; 831 struct cil_roletransition *roletrans = NULL; 832 struct cil_complex_symtab_key ckey; 833 834 switch (node->flavor) { 835 case CIL_ROLETRANSITION: { 836 roletrans = node->data; 837 ckey.key1 = (intptr_t)roletrans->src; 838 ckey.key2 = (intptr_t)roletrans->tgt; 839 ckey.key3 = (intptr_t)roletrans->obj; 840 ckey.key4 = CIL_ROLETRANSITION; 841 break; 842 } 843 case CIL_TYPE_RULE: { 844 typerule = node->data; 845 ckey.key1 = (intptr_t)typerule->src; 846 ckey.key2 = (intptr_t)typerule->tgt; 847 ckey.key3 = (intptr_t)typerule->obj; 848 ckey.key4 = (intptr_t)typerule->rule_kind; 849 break; 850 } 851 default: 852 break; 853 } 854 855 856 rc = cil_complex_symtab_insert(symtab, &ckey, NULL); 857 if (rc == SEPOL_EEXIST) { 858 struct cil_complex_symtab_datum *datum = NULL; 859 cil_complex_symtab_search(symtab, &ckey, &datum); 860 if (datum == NULL) { 861 cil_tree_log(node, CIL_ERR, "Duplicate rule defined"); 862 rc = SEPOL_ERR; 863 goto exit; 864 } 865 } 866 867 return SEPOL_OK; 868 exit: 869 cil_tree_log(node, CIL_ERR, "Invalid rule"); 870 return rc; 871 } 872 873 int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args) 874 { 875 int rc = SEPOL_ERR; 876 struct cil_tree_node *rule_node = node; 877 struct cil_booleanif *bif = node->parent->parent->data; 878 879 switch (rule_node->flavor) { 880 case CIL_AVRULE: { 881 struct cil_avrule *avrule = NULL; 882 avrule = rule_node->data; 883 if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) { 884 if (bif->preserved_tunable) { 885 cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)"); 886 } else { 887 cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block"); 888 } 889 rc = SEPOL_ERR; 890 goto exit; 891 } 892 break; 893 } 894 case CIL_TYPE_RULE: /* 895 struct cil_type_rule *typerule = NULL; 896 struct cil_tree_node *temp_node = NULL; 897 struct cil_complex_symtab *symtab = extra_args; 898 struct cil_complex_symtab_key ckey; 899 struct cil_complex_symtab_datum datum; 900 typerule = rule_node->data; 901 902 ckey.key1 = (intptr_t)typerule->src; 903 ckey.key2 = (intptr_t)typerule->tgt; 904 ckey.key3 = (intptr_t)typerule->obj; 905 ckey.key4 = (intptr_t)typerule->rule_kind; 906 907 datum.data = node; 908 909 rc = cil_complex_symtab_insert(symtab, &ckey, &datum); 910 if (rc != SEPOL_OK) { 911 goto exit; 912 } 913 914 for (temp_node = rule_node->next; 915 temp_node != NULL; 916 temp_node = temp_node->next) { 917 918 if (temp_node->flavor == CIL_TYPE_RULE) { 919 typerule = temp_node->data; 920 if ((intptr_t)typerule->src == ckey.key1 && 921 (intptr_t)typerule->tgt == ckey.key2 && 922 (intptr_t)typerule->obj == ckey.key3 && 923 (intptr_t)typerule->rule_kind == ckey.key4) { 924 cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line); 925 rc = SEPOL_ERR; 926 goto exit; 927 } 928 } 929 } 930 break;*/ 931 932 //TODO Fix duplicate type_rule detection 933 break; 934 case CIL_CALL: 935 //Fall through to check content of call 936 break; 937 case CIL_TUNABLEIF: 938 //Fall through 939 break; 940 case CIL_NAMETYPETRANSITION: 941 /* While type transitions with file component are not allowed in 942 booleanif statements if they don't have "*" as the file. We 943 can't check that here. Or at least we won't right now. */ 944 break; 945 default: { 946 const char * flavor = cil_node_to_string(node); 947 if (bif->preserved_tunable) { 948 cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor); 949 } else { 950 cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor); 951 } 952 goto exit; 953 } 954 } 955 956 rc = SEPOL_OK; 957 exit: 958 return rc; 959 } 960 961 int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab) 962 { 963 int rc = SEPOL_ERR; 964 struct cil_booleanif *bif = (struct cil_booleanif*)node->data; 965 struct cil_tree_node *cond_block = node->cl_head; 966 967 while (cond_block != NULL) { 968 rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab); 969 if (rc != SEPOL_OK) { 970 goto exit; 971 } 972 cond_block = cond_block->next; 973 } 974 975 return SEPOL_OK; 976 exit: 977 if (bif->preserved_tunable) { 978 cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)"); 979 } else { 980 cil_tree_log(node, CIL_ERR, "Invalid booleanif"); 981 } 982 return rc; 983 } 984 985 int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node) 986 { 987 int rc = SEPOL_ERR; 988 struct cil_netifcon *netif = node->data; 989 struct cil_context *if_ctx = netif->if_context; 990 struct cil_context *pkt_ctx = netif->packet_context; 991 992 /* Verify only when anonymous */ 993 if (if_ctx->datum.name == NULL) { 994 rc = __cil_verify_context(db, if_ctx); 995 if (rc != SEPOL_OK) { 996 goto exit; 997 } 998 } 999 1000 /* Verify only when anonymous */ 1001 if (pkt_ctx->datum.name == NULL) { 1002 rc = __cil_verify_context(db, pkt_ctx); 1003 if (rc != SEPOL_OK) { 1004 goto exit; 1005 } 1006 } 1007 1008 return SEPOL_OK; 1009 1010 exit: 1011 cil_tree_log(node, CIL_ERR, "Invalid netifcon"); 1012 return rc; 1013 } 1014 1015 int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node) 1016 { 1017 int rc = SEPOL_ERR; 1018 struct cil_ibendportcon *ib_end_port = node->data; 1019 struct cil_context *ctx = ib_end_port->context; 1020 1021 /* Verify only when anonymous */ 1022 if (!ctx->datum.name) { 1023 rc = __cil_verify_context(db, ctx); 1024 if (rc != SEPOL_OK) 1025 goto exit; 1026 } 1027 1028 return SEPOL_OK; 1029 1030 exit: 1031 cil_tree_log(node, CIL_ERR, "Invalid ibendportcon"); 1032 return rc; 1033 } 1034 1035 int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node) 1036 { 1037 int rc = SEPOL_ERR; 1038 struct cil_genfscon *genfs = node->data; 1039 struct cil_context *ctx = genfs->context; 1040 1041 /* Verify only when anonymous */ 1042 if (ctx->datum.name == NULL) { 1043 rc = __cil_verify_context(db, ctx); 1044 if (rc != SEPOL_OK) { 1045 goto exit; 1046 } 1047 } 1048 1049 return SEPOL_OK; 1050 1051 exit: 1052 cil_tree_log(node, CIL_ERR, "Invalid genfscon"); 1053 return rc; 1054 } 1055 1056 int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node) 1057 { 1058 int rc = SEPOL_ERR; 1059 struct cil_filecon *file = node->data; 1060 struct cil_context *ctx = file->context; 1061 1062 if (ctx == NULL) { 1063 rc = SEPOL_OK; 1064 goto exit; 1065 } 1066 1067 /* Verify only when anonymous */ 1068 if (ctx->datum.name == NULL) { 1069 rc = __cil_verify_context(db, ctx); 1070 if (rc != SEPOL_OK) { 1071 cil_tree_log(node, CIL_ERR, "Invalid filecon"); 1072 goto exit; 1073 } 1074 } 1075 1076 return SEPOL_OK; 1077 1078 exit: 1079 return rc; 1080 } 1081 1082 int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node) 1083 { 1084 int rc = SEPOL_ERR; 1085 struct cil_nodecon *nodecon = node->data; 1086 struct cil_context *ctx = nodecon->context; 1087 1088 /* Verify only when anonymous */ 1089 if (ctx->datum.name == NULL) { 1090 rc = __cil_verify_context(db, ctx); 1091 if (rc != SEPOL_OK) { 1092 goto exit; 1093 } 1094 } 1095 1096 return SEPOL_OK; 1097 1098 exit: 1099 cil_tree_log(node, CIL_ERR, "Invalid nodecon"); 1100 return rc; 1101 } 1102 1103 int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node) 1104 { 1105 int rc = SEPOL_ERR; 1106 struct cil_ibpkeycon *pkey = node->data; 1107 struct cil_context *ctx = pkey->context; 1108 1109 /* Verify only when anonymous */ 1110 if (!ctx->datum.name) { 1111 rc = __cil_verify_context(db, ctx); 1112 if (rc != SEPOL_OK) 1113 goto exit; 1114 } 1115 1116 return SEPOL_OK; 1117 1118 exit: 1119 cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon"); 1120 return rc; 1121 } 1122 1123 int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node) 1124 { 1125 int rc = SEPOL_ERR; 1126 struct cil_portcon *port = node->data; 1127 struct cil_context *ctx = port->context; 1128 1129 /* Verify only when anonymous */ 1130 if (ctx->datum.name == NULL) { 1131 rc = __cil_verify_context(db, ctx); 1132 if (rc != SEPOL_OK) { 1133 goto exit; 1134 } 1135 } 1136 1137 return SEPOL_OK; 1138 1139 exit: 1140 cil_tree_log(node, CIL_ERR, "Invalid portcon"); 1141 return rc; 1142 } 1143 1144 int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node) 1145 { 1146 int rc = SEPOL_ERR; 1147 struct cil_pirqcon *pirq = node->data; 1148 struct cil_context *ctx = pirq->context; 1149 1150 /* Verify only when anonymous */ 1151 if (ctx->datum.name == NULL) { 1152 rc = __cil_verify_context(db, ctx); 1153 if (rc != SEPOL_OK) { 1154 goto exit; 1155 } 1156 } 1157 1158 return SEPOL_OK; 1159 1160 exit: 1161 cil_tree_log(node, CIL_ERR, "Invalid pirqcon"); 1162 return rc; 1163 } 1164 1165 int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node) 1166 { 1167 int rc = SEPOL_ERR; 1168 struct cil_iomemcon *iomem = node->data; 1169 struct cil_context *ctx = iomem->context; 1170 1171 /* Verify only when anonymous */ 1172 if (ctx->datum.name == NULL) { 1173 rc = __cil_verify_context(db, ctx); 1174 if (rc != SEPOL_OK) { 1175 goto exit; 1176 } 1177 } 1178 1179 return SEPOL_OK; 1180 1181 exit: 1182 cil_tree_log(node, CIL_ERR, "Invalid iomemcon"); 1183 return rc; 1184 } 1185 1186 int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node) 1187 { 1188 int rc = SEPOL_ERR; 1189 struct cil_ioportcon *ioport = node->data; 1190 struct cil_context *ctx = ioport->context; 1191 1192 /* Verify only when anonymous */ 1193 if (ctx->datum.name == NULL) { 1194 rc = __cil_verify_context(db, ctx); 1195 if (rc != SEPOL_OK) { 1196 goto exit; 1197 } 1198 } 1199 1200 return SEPOL_OK; 1201 1202 exit: 1203 cil_tree_log(node, CIL_ERR, "Invalid ioportcon"); 1204 return rc; 1205 } 1206 1207 int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node) 1208 { 1209 int rc = SEPOL_ERR; 1210 struct cil_pcidevicecon *pcidev = node->data; 1211 struct cil_context *ctx = pcidev->context; 1212 1213 /* Verify only when anonymous */ 1214 if (ctx->datum.name == NULL) { 1215 rc = __cil_verify_context(db, ctx); 1216 if (rc != SEPOL_OK) { 1217 goto exit; 1218 } 1219 } 1220 1221 return SEPOL_OK; 1222 1223 exit: 1224 cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon"); 1225 return rc; 1226 } 1227 1228 int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node) 1229 { 1230 int rc = SEPOL_ERR; 1231 struct cil_devicetreecon *dt = node->data; 1232 struct cil_context *ctx = dt->context; 1233 1234 /* Verify only when anonymous */ 1235 if (ctx->datum.name == NULL) { 1236 rc = __cil_verify_context(db, ctx); 1237 if (rc != SEPOL_OK) { 1238 goto exit; 1239 } 1240 } 1241 1242 return SEPOL_OK; 1243 1244 exit: 1245 cil_tree_log(node, CIL_ERR, "Invalid devicetreecon"); 1246 return rc; 1247 } 1248 1249 int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node) 1250 { 1251 int rc = SEPOL_ERR; 1252 struct cil_fsuse *fsuse = node->data; 1253 struct cil_context *ctx = fsuse->context; 1254 1255 /* Verify only when anonymous */ 1256 if (ctx->datum.name == NULL) { 1257 rc = __cil_verify_context(db, ctx); 1258 if (rc != SEPOL_OK) { 1259 goto exit; 1260 } 1261 } 1262 1263 return SEPOL_OK; 1264 1265 exit: 1266 cil_tree_log(node, CIL_ERR, "Invalid fsuse"); 1267 return rc; 1268 } 1269 1270 int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node *node) 1271 { 1272 int rc; 1273 struct cil_list *classes = NULL; 1274 struct cil_list_item *item; 1275 struct cil_class *class; 1276 struct cil_symtab_datum *perm_datum; 1277 char *kind_str; 1278 1279 switch (permx->kind) { 1280 case CIL_PERMX_KIND_IOCTL: 1281 kind_str = CIL_KEY_IOCTL; 1282 break; 1283 default: 1284 cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind); 1285 rc = SEPOL_ERR; 1286 goto exit; 1287 } 1288 1289 classes = cil_expand_class(permx->obj); 1290 1291 cil_list_for_each(item, classes) { 1292 class = item->data; 1293 rc = cil_symtab_get_datum(&class->perms, kind_str, &perm_datum); 1294 if (rc == SEPOL_ENOENT) { 1295 if (class->common != NULL) { 1296 rc = cil_symtab_get_datum(&class->common->perms, kind_str, &perm_datum); 1297 } 1298 1299 if (rc == SEPOL_ENOENT) { 1300 cil_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", kind_str, class->datum.name); 1301 rc = SEPOL_ERR; 1302 goto exit; 1303 } 1304 } 1305 } 1306 1307 rc = SEPOL_OK; 1308 1309 exit: 1310 if (classes != NULL) { 1311 cil_list_destroy(&classes, CIL_FALSE); 1312 } 1313 1314 return rc; 1315 } 1316 1317 int __cil_verify_avrulex(struct cil_tree_node *node) 1318 { 1319 struct cil_avrule *avrulex = node->data; 1320 return __cil_verify_permissionx(avrulex->perms.x.permx, node); 1321 } 1322 1323 int __cil_verify_class(struct cil_tree_node *node) 1324 { 1325 int rc = SEPOL_ERR; 1326 struct cil_class *class = node->data; 1327 1328 if (class->common != NULL) { 1329 struct cil_class *common = class->common; 1330 struct cil_tree_node *common_node = common->datum.nodes->head->data; 1331 struct cil_tree_node *curr_com_perm = NULL; 1332 1333 for (curr_com_perm = common_node->cl_head; 1334 curr_com_perm != NULL; 1335 curr_com_perm = curr_com_perm->next) { 1336 struct cil_perm *com_perm = curr_com_perm->data; 1337 struct cil_tree_node *curr_class_perm = NULL; 1338 1339 for (curr_class_perm = node->cl_head; 1340 curr_class_perm != NULL; 1341 curr_class_perm = curr_class_perm->next) { 1342 struct cil_perm *class_perm = curr_class_perm->data; 1343 1344 if (com_perm->datum.name == class_perm->datum.name) { 1345 cil_log(CIL_ERR, "Duplicate permissions between %s common and class declarations\n", class_perm->datum.name); 1346 goto exit; 1347 } 1348 } 1349 } 1350 } 1351 1352 return SEPOL_OK; 1353 1354 exit: 1355 cil_tree_log(node, CIL_ERR, "Invalid class"); 1356 return rc; 1357 } 1358 1359 int __cil_verify_policycap(struct cil_tree_node *node) 1360 { 1361 int rc; 1362 struct cil_policycap *polcap = node->data; 1363 1364 rc = sepol_polcap_getnum((const char*)polcap->datum.name); 1365 if (rc == SEPOL_ERR) { 1366 goto exit; 1367 } 1368 1369 return SEPOL_OK; 1370 1371 exit: 1372 cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name); 1373 return rc; 1374 } 1375 1376 int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 1377 { 1378 int rc = SEPOL_ERR; 1379 int *avrule_cnt = 0; 1380 int *handleunknown; 1381 int *mls; 1382 int *nseuserdflt = 0; 1383 int *pass = 0; 1384 struct cil_args_verify *args = extra_args; 1385 struct cil_complex_symtab *csymtab = NULL; 1386 struct cil_db *db = NULL; 1387 1388 if (node == NULL || extra_args == NULL) { 1389 goto exit; 1390 } 1391 1392 db = args->db; 1393 avrule_cnt = args->avrule_cnt; 1394 handleunknown = args->handleunknown; 1395 mls = args->mls; 1396 nseuserdflt = args->nseuserdflt; 1397 csymtab = args->csymtab; 1398 pass = args->pass; 1399 1400 if (node->flavor == CIL_MACRO) { 1401 *finished = CIL_TREE_SKIP_HEAD; 1402 rc = SEPOL_OK; 1403 goto exit; 1404 } else if (node->flavor == CIL_BLOCK) { 1405 struct cil_block *blk = node->data; 1406 if (blk->is_abstract == CIL_TRUE) { 1407 *finished = CIL_TREE_SKIP_HEAD; 1408 } 1409 rc = SEPOL_OK; 1410 goto exit; 1411 } 1412 1413 switch (*pass) { 1414 case 0: { 1415 switch (node->flavor) { 1416 case CIL_USER: 1417 rc = __cil_verify_user_post_eval(db, node); 1418 break; 1419 case CIL_SELINUXUSERDEFAULT: 1420 (*nseuserdflt)++; 1421 rc = SEPOL_OK; 1422 break; 1423 case CIL_ROLE: 1424 rc = __cil_verify_role(node); 1425 break; 1426 case CIL_TYPE: 1427 rc = __cil_verify_type(node); 1428 break; 1429 case CIL_AVRULE: 1430 (*avrule_cnt)++; 1431 rc = SEPOL_OK; 1432 break; 1433 case CIL_HANDLEUNKNOWN: 1434 if (*handleunknown != -1) { 1435 cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n"); 1436 rc = SEPOL_ERR; 1437 } else { 1438 *handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown; 1439 rc = SEPOL_OK; 1440 } 1441 break; 1442 case CIL_MLS: 1443 if (*mls != -1) { 1444 cil_log(CIL_ERR, "Policy can not have more than one mls\n"); 1445 rc = SEPOL_ERR; 1446 } else { 1447 *mls = ((struct cil_mls*)node->data)->value; 1448 rc = SEPOL_OK; 1449 } 1450 break; 1451 case CIL_ROLETRANSITION: 1452 rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right 1453 //rc = __cil_verify_rule(node, csymtab); 1454 break; 1455 case CIL_TYPE_RULE: 1456 rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right 1457 //rc = __cil_verify_rule(node, csymtab); 1458 break; 1459 case CIL_BOOLEANIF: 1460 rc = __cil_verify_booleanif(node, csymtab); 1461 *finished = CIL_TREE_SKIP_HEAD; 1462 break; 1463 case CIL_LEVELRANGE: 1464 rc = __cil_verify_named_levelrange(db, node); 1465 break; 1466 case CIL_CLASS: 1467 rc = __cil_verify_class(node); 1468 break; 1469 case CIL_POLICYCAP: 1470 rc = __cil_verify_policycap(node); 1471 break; 1472 default: 1473 rc = SEPOL_OK; 1474 break; 1475 } 1476 break; 1477 } 1478 case 1: { 1479 switch (node->flavor) { 1480 case CIL_CONTEXT: 1481 rc = __cil_verify_named_context(db, node); 1482 break; 1483 case CIL_NETIFCON: 1484 rc = __cil_verify_netifcon(db, node); 1485 break; 1486 case CIL_GENFSCON: 1487 rc = __cil_verify_genfscon(db, node); 1488 break; 1489 case CIL_FILECON: 1490 rc = __cil_verify_filecon(db, node); 1491 break; 1492 case CIL_NODECON: 1493 rc = __cil_verify_nodecon(db, node); 1494 break; 1495 case CIL_IBPKEYCON: 1496 rc = __cil_verify_ibpkeycon(db, node); 1497 break; 1498 case CIL_IBENDPORTCON: 1499 rc = __cil_verify_ibendportcon(db, node); 1500 break; 1501 case CIL_PORTCON: 1502 rc = __cil_verify_portcon(db, node); 1503 break; 1504 case CIL_PIRQCON: 1505 rc = __cil_verify_pirqcon(db, node); 1506 break; 1507 case CIL_IOMEMCON: 1508 rc = __cil_verify_iomemcon(db, node); 1509 break; 1510 case CIL_IOPORTCON: 1511 rc = __cil_verify_ioportcon(db, node); 1512 break; 1513 case CIL_PCIDEVICECON: 1514 rc = __cil_verify_pcidevicecon(db, node); 1515 break; 1516 case CIL_DEVICETREECON: 1517 rc = __cil_verify_devicetreecon(db, node); 1518 break; 1519 case CIL_FSUSE: 1520 rc = __cil_verify_fsuse(db, node); 1521 break; 1522 case CIL_AVRULEX: 1523 rc = __cil_verify_avrulex(node); 1524 break; 1525 case CIL_PERMISSIONX: 1526 rc = __cil_verify_permissionx(node->data, node); 1527 break; 1528 case CIL_RANGETRANSITION: 1529 rc = SEPOL_OK; 1530 break; 1531 default: 1532 rc = SEPOL_OK; 1533 break; 1534 } 1535 break; 1536 } 1537 default: 1538 rc = SEPOL_ERR; 1539 } 1540 1541 exit: 1542 return rc; 1543 } 1544 1545 static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig) 1546 { 1547 int rc = SEPOL_ERR; 1548 struct cil_list_item *curr; 1549 1550 cil_list_for_each(curr, classperms) { 1551 if (curr->flavor == CIL_CLASSPERMS) { 1552 struct cil_classperms *cp = curr->data; 1553 if (FLAVOR(cp->class) == CIL_CLASS) { 1554 return SEPOL_OK; 1555 } else { /* MAP */ 1556 struct cil_list_item *i = NULL; 1557 cil_list_for_each(i, cp->perms) { 1558 struct cil_perm *cmp = i->data; 1559 if (&cmp->datum == orig) { 1560 rc = SEPOL_ERR; 1561 goto exit; 1562 } 1563 rc = __cil_verify_classperms(cmp->classperms, orig); 1564 if (rc != SEPOL_OK) { 1565 goto exit; 1566 } 1567 } 1568 } 1569 } else { /* SET */ 1570 struct cil_classperms_set *cp_set = curr->data; 1571 struct cil_classpermission *cp = cp_set->set; 1572 if (&cp->datum == orig) { 1573 rc = SEPOL_ERR; 1574 goto exit; 1575 } 1576 rc = __cil_verify_classperms(cp->classperms, orig); 1577 if (rc != SEPOL_OK) { 1578 goto exit; 1579 } 1580 } 1581 } 1582 1583 return SEPOL_OK; 1584 1585 exit: 1586 return rc; 1587 } 1588 1589 static int __cil_verify_classpermission(struct cil_tree_node *node) 1590 { 1591 int rc = SEPOL_ERR; 1592 struct cil_classpermission *cp = node->data; 1593 1594 if (cp->classperms == NULL) { 1595 cil_tree_log(node, CIL_ERR, "Classpermission %s does not have a classpermissionset", cp->datum.name); 1596 rc = SEPOL_ERR; 1597 goto exit; 1598 } 1599 1600 rc = __cil_verify_classperms(cp->classperms, &cp->datum); 1601 if (rc != SEPOL_OK) { 1602 cil_tree_log(node, CIL_ERR, "Found circular class permissions involving the set %s",cp->datum.name); 1603 goto exit; 1604 } 1605 1606 rc = SEPOL_OK; 1607 1608 exit: 1609 return rc; 1610 } 1611 1612 struct cil_verify_map_args { 1613 struct cil_class *class; 1614 struct cil_tree_node *node; 1615 int rc; 1616 }; 1617 1618 static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) 1619 { 1620 int rc = SEPOL_ERR; 1621 struct cil_verify_map_args *map_args = args; 1622 struct cil_perm *cmp = (struct cil_perm *)d; 1623 1624 if (cmp->classperms == NULL) { 1625 cil_tree_log(map_args->node, CIL_ERR, "Map class %s does not have a classmapping for %s", map_args->class->datum.name, cmp->datum.name); 1626 map_args->rc = SEPOL_ERR; 1627 goto exit; 1628 } 1629 1630 rc = __cil_verify_classperms(cmp->classperms, &cmp->datum); 1631 if (rc != SEPOL_OK) { 1632 cil_tree_log(map_args->node, CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", map_args->class->datum.name, cmp->datum.name); 1633 map_args->rc = SEPOL_ERR; 1634 goto exit; 1635 } 1636 1637 exit: 1638 return SEPOL_OK; 1639 } 1640 1641 static int __cil_verify_map_class(struct cil_tree_node *node) 1642 { 1643 struct cil_class *mc = node->data; 1644 struct cil_verify_map_args map_args; 1645 1646 map_args.class = mc; 1647 map_args.node = node; 1648 map_args.rc = SEPOL_OK; 1649 1650 cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args); 1651 1652 if (map_args.rc != SEPOL_OK) { 1653 return SEPOL_ERR; 1654 } 1655 1656 return SEPOL_OK; 1657 } 1658 1659 int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args) 1660 { 1661 int rc = SEPOL_ERR; 1662 1663 if (node->flavor == CIL_MACRO) { 1664 *finished = CIL_TREE_SKIP_HEAD; 1665 rc = SEPOL_OK; 1666 goto exit; 1667 } else if (node->flavor == CIL_BLOCK) { 1668 struct cil_block *blk = node->data; 1669 if (blk->is_abstract == CIL_TRUE) { 1670 *finished = CIL_TREE_SKIP_HEAD; 1671 } 1672 rc = SEPOL_OK; 1673 goto exit; 1674 } 1675 1676 switch (node->flavor) { 1677 case CIL_USER: 1678 rc = __cil_verify_user_pre_eval(node); 1679 if (rc != SEPOL_OK) { 1680 goto exit; 1681 } 1682 break; 1683 case CIL_MAP_CLASS: 1684 rc = __cil_verify_map_class(node); 1685 break; 1686 case CIL_CLASSPERMISSION: 1687 rc = __cil_verify_classpermission(node); 1688 break; 1689 default: 1690 rc = SEPOL_OK; 1691 break; 1692 } 1693 1694 exit: 1695 return rc; 1696 } 1697