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