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