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