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 <ctype.h> 34 35 #include <sepol/policydb/conditional.h> 36 37 #include "cil_internal.h" 38 #include "cil_flavor.h" 39 #include "cil_log.h" 40 #include "cil_mem.h" 41 #include "cil_tree.h" 42 #include "cil_list.h" 43 #include "cil_parser.h" 44 #include "cil_build_ast.h" 45 #include "cil_copy_ast.h" 46 #include "cil_verify.h" 47 #include "cil_strpool.h" 48 49 struct cil_args_build { 50 struct cil_tree_node *ast; 51 struct cil_db *db; 52 struct cil_tree_node *macro; 53 struct cil_tree_node *boolif; 54 struct cil_tree_node *tunif; 55 struct cil_tree_node *in; 56 }; 57 58 int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list) 59 { 60 int rc = SEPOL_ERR; 61 struct cil_tree_node *curr; 62 enum cil_syntax syntax[] = { 63 CIL_SYN_N_STRINGS, 64 CIL_SYN_END 65 }; 66 int syntax_len = sizeof(syntax)/sizeof(*syntax); 67 68 rc = __cil_verify_syntax(current, syntax, syntax_len); 69 if (rc != SEPOL_OK) { 70 goto exit; 71 } 72 73 cil_list_init(list, flavor); 74 75 for (curr = current; curr != NULL; curr = curr->next) { 76 cil_list_append(*list, CIL_STRING, curr->data); 77 } 78 79 return SEPOL_OK; 80 81 exit: 82 return rc; 83 } 84 85 int cil_gen_node(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor) 86 { 87 int rc = SEPOL_ERR; 88 symtab_t *symtab = NULL; 89 90 rc = __cil_verify_name((const char*)key); 91 if (rc != SEPOL_OK) { 92 goto exit; 93 } 94 95 rc = cil_get_symtab(ast_node->parent, &symtab, sflavor); 96 if (rc != SEPOL_OK) { 97 goto exit; 98 } 99 100 ast_node->data = datum; 101 ast_node->flavor = nflavor; 102 103 if (symtab != NULL) { 104 rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node); 105 if (rc == SEPOL_EEXIST) { 106 cil_log(CIL_ERR, "Re-declaration of %s %s\n", 107 cil_node_to_string(ast_node), key); 108 if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) { 109 if (sflavor == CIL_SYM_BLOCKS) { 110 struct cil_tree_node *node = datum->nodes->head->data; 111 cil_tree_log(node, CIL_ERR, "Previous declaration"); 112 } 113 } 114 goto exit; 115 } 116 } 117 118 if (ast_node->flavor >= CIL_MIN_DECLARATIVE && ast_node->parent->flavor == CIL_MACRO) { 119 struct cil_list_item *item; 120 struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params; 121 if (param_list != NULL) { 122 cil_list_for_each(item, param_list) { 123 struct cil_param *param = item->data; 124 if (param->flavor == ast_node->flavor) { 125 if (param->str == key) { 126 cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key); 127 rc = SEPOL_ERR; 128 goto exit; 129 } 130 } 131 } 132 } 133 } 134 135 return SEPOL_OK; 136 137 exit: 138 cil_log(CIL_ERR, "Failed to create node\n"); 139 return rc; 140 } 141 142 void cil_clear_node(struct cil_tree_node *ast_node) 143 { 144 if (ast_node == NULL) { 145 return; 146 } 147 148 ast_node->data = NULL; 149 ast_node->flavor = CIL_NONE; 150 } 151 152 int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract) 153 { 154 enum cil_syntax syntax[] = { 155 CIL_SYN_STRING, 156 CIL_SYN_STRING, 157 CIL_SYN_N_LISTS | CIL_SYN_END, 158 CIL_SYN_END 159 }; 160 int syntax_len = sizeof(syntax)/sizeof(*syntax); 161 char *key = NULL; 162 struct cil_block *block = NULL; 163 int rc = SEPOL_ERR; 164 165 if (db == NULL || parse_current == NULL || ast_node == NULL) { 166 goto exit; 167 } 168 169 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 170 if (rc != SEPOL_OK) { 171 goto exit; 172 } 173 174 cil_block_init(&block); 175 176 block->is_abstract = is_abstract; 177 178 key = parse_current->next->data; 179 180 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)block, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK); 181 if (rc != SEPOL_OK) { 182 goto exit; 183 } 184 185 return SEPOL_OK; 186 187 exit: 188 cil_tree_log(parse_current, CIL_ERR, "Bad block declaration"); 189 cil_destroy_block(block); 190 cil_clear_node(ast_node); 191 return rc; 192 } 193 194 void cil_destroy_block(struct cil_block *block) 195 { 196 if (block == NULL) { 197 return; 198 } 199 200 cil_symtab_datum_destroy(&block->datum); 201 cil_symtab_array_destroy(block->symtab); 202 cil_list_destroy(&block->bi_nodes, CIL_FALSE); 203 204 free(block); 205 } 206 207 int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 208 { 209 enum cil_syntax syntax[] = { 210 CIL_SYN_STRING, 211 CIL_SYN_STRING, 212 CIL_SYN_END 213 }; 214 int syntax_len = sizeof(syntax)/sizeof(*syntax); 215 struct cil_blockinherit *inherit = NULL; 216 int rc = SEPOL_ERR; 217 218 if (db == NULL || parse_current == NULL || ast_node == NULL) { 219 goto exit; 220 } 221 222 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 223 if (rc != SEPOL_OK) { 224 goto exit; 225 } 226 227 cil_blockinherit_init(&inherit); 228 229 inherit->block_str = parse_current->next->data; 230 231 ast_node->data = inherit; 232 ast_node->flavor = CIL_BLOCKINHERIT; 233 234 return SEPOL_OK; 235 236 exit: 237 cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration"); 238 cil_destroy_blockinherit(inherit); 239 return rc; 240 } 241 242 void cil_destroy_blockinherit(struct cil_blockinherit *inherit) 243 { 244 if (inherit == NULL) { 245 return; 246 } 247 248 free(inherit); 249 } 250 251 int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 252 { 253 enum cil_syntax syntax[] = { 254 CIL_SYN_STRING, 255 CIL_SYN_STRING, 256 CIL_SYN_END 257 }; 258 int syntax_len = sizeof(syntax)/sizeof(*syntax); 259 struct cil_blockabstract *abstract = NULL; 260 int rc = SEPOL_ERR; 261 262 if (db == NULL || parse_current == NULL || ast_node == NULL) { 263 goto exit; 264 } 265 266 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 267 if (rc != SEPOL_OK) { 268 goto exit; 269 } 270 271 cil_blockabstract_init(&abstract); 272 273 abstract->block_str = parse_current->next->data; 274 275 ast_node->data = abstract; 276 ast_node->flavor = CIL_BLOCKABSTRACT; 277 278 return SEPOL_OK; 279 280 exit: 281 cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration"); 282 cil_destroy_blockabstract(abstract); 283 return rc; 284 } 285 286 void cil_destroy_blockabstract(struct cil_blockabstract *abstract) 287 { 288 if (abstract == NULL) { 289 return; 290 } 291 292 free(abstract); 293 } 294 295 int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 296 { 297 enum cil_syntax syntax[] = { 298 CIL_SYN_STRING, 299 CIL_SYN_STRING, 300 CIL_SYN_N_LISTS, 301 CIL_SYN_END 302 }; 303 int syntax_len = sizeof(syntax)/sizeof(*syntax); 304 int rc = SEPOL_ERR; 305 struct cil_in *in = NULL; 306 307 if (db == NULL || parse_current == NULL || ast_node == NULL) { 308 goto exit; 309 } 310 311 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 312 if (rc != SEPOL_OK) { 313 goto exit; 314 } 315 316 cil_in_init(&in); 317 318 in->block_str = parse_current->next->data; 319 320 ast_node->data = in; 321 ast_node->flavor = CIL_IN; 322 323 return SEPOL_OK; 324 exit: 325 cil_tree_log(parse_current, CIL_ERR, "Bad in statement"); 326 cil_destroy_in(in); 327 return rc; 328 } 329 330 void cil_destroy_in(struct cil_in *in) 331 { 332 if (in == NULL) { 333 return; 334 } 335 336 cil_symtab_array_destroy(in->symtab); 337 338 free(in); 339 } 340 341 int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 342 { 343 enum cil_syntax syntax[] = { 344 CIL_SYN_STRING, 345 CIL_SYN_STRING, 346 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, 347 CIL_SYN_END 348 }; 349 int syntax_len = sizeof(syntax)/sizeof(*syntax); 350 char *key = NULL; 351 struct cil_class *class = NULL; 352 struct cil_tree_node *perms = NULL; 353 int rc = SEPOL_ERR; 354 355 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 356 if (rc != SEPOL_OK) { 357 goto exit; 358 } 359 360 cil_class_init(&class); 361 362 key = parse_current->next->data; 363 if (key == CIL_KEY_UNORDERED) { 364 cil_log(CIL_ERR, "'unordered' keyword is reserved and not a valid class name.\n"); 365 rc = SEPOL_ERR; 366 goto exit; 367 } 368 369 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)class, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS); 370 if (rc != SEPOL_OK) { 371 goto exit; 372 } 373 374 if (parse_current->next->next != NULL) { 375 perms = parse_current->next->next->cl_head; 376 rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM, &class->num_perms); 377 if (rc != SEPOL_OK) { 378 goto exit; 379 } 380 if (class->num_perms > CIL_PERMS_PER_CLASS) { 381 cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name); 382 goto exit; 383 } 384 385 } 386 387 return SEPOL_OK; 388 389 exit: 390 cil_tree_log(parse_current, CIL_ERR, "Bad class declaration"); 391 cil_destroy_class(class); 392 cil_clear_node(ast_node); 393 return rc; 394 } 395 396 void cil_destroy_class(struct cil_class *class) 397 { 398 if (class == NULL) { 399 return; 400 } 401 402 cil_symtab_datum_destroy(&class->datum); 403 cil_symtab_destroy(&class->perms); 404 405 free(class); 406 } 407 408 int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 409 { 410 enum cil_syntax syntax[] = { 411 CIL_SYN_STRING, 412 CIL_SYN_LIST, 413 CIL_SYN_END 414 }; 415 int syntax_len = sizeof(syntax)/sizeof(*syntax); 416 struct cil_classorder *classorder = NULL; 417 struct cil_list_item *curr = NULL; 418 struct cil_list_item *head = NULL; 419 int rc = SEPOL_ERR; 420 421 if (db == NULL || parse_current == NULL || ast_node == NULL) { 422 goto exit; 423 } 424 425 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 426 if (rc != SEPOL_OK) { 427 goto exit; 428 } 429 430 cil_classorder_init(&classorder); 431 432 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASSORDER, &classorder->class_list_str); 433 if (rc != SEPOL_OK) { 434 goto exit; 435 } 436 437 head = classorder->class_list_str->head; 438 cil_list_for_each(curr, classorder->class_list_str) { 439 if (curr->data == CIL_KEY_UNORDERED) { 440 if (curr == head && curr->next == NULL) { 441 cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n"); 442 rc = SEPOL_ERR; 443 goto exit; 444 } else if (curr != head) { 445 cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n"); 446 rc = SEPOL_ERR; 447 goto exit; 448 } 449 } 450 } 451 452 ast_node->data = classorder; 453 ast_node->flavor = CIL_CLASSORDER; 454 455 return SEPOL_OK; 456 457 exit: 458 cil_tree_log(parse_current, CIL_ERR, "Bad classorder declaration"); 459 cil_destroy_classorder(classorder); 460 return rc; 461 } 462 463 void cil_destroy_classorder(struct cil_classorder *classorder) 464 { 465 if (classorder == NULL) { 466 return; 467 } 468 469 if (classorder->class_list_str != NULL) { 470 cil_list_destroy(&classorder->class_list_str, 1); 471 } 472 473 free(classorder); 474 } 475 476 int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms) 477 { 478 char *key = NULL; 479 struct cil_perm *perm = NULL; 480 int rc = SEPOL_ERR; 481 482 cil_perm_init(&perm); 483 484 key = parse_current->data; 485 if (key == NULL) { 486 cil_log(CIL_ERR, "Bad permission\n"); 487 goto exit; 488 } 489 490 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)perm, (hashtab_key_t)key, CIL_SYM_PERMS, flavor); 491 if (rc != SEPOL_OK) { 492 goto exit; 493 } 494 495 perm->value = *num_perms; 496 (*num_perms)++; 497 498 return SEPOL_OK; 499 500 exit: 501 cil_destroy_perm(perm); 502 cil_clear_node(ast_node); 503 return rc; 504 } 505 506 void cil_destroy_perm(struct cil_perm *perm) 507 { 508 if (perm == NULL) { 509 return; 510 } 511 512 cil_symtab_datum_destroy(&perm->datum); 513 cil_list_destroy(&perm->classperms, CIL_FALSE); 514 515 free(perm); 516 } 517 518 int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms) 519 { 520 int rc = SEPOL_ERR; 521 struct cil_tree_node *new_ast = NULL; 522 523 while(current_perm != NULL) { 524 if (current_perm->cl_head != NULL) { 525 526 rc = SEPOL_ERR; 527 goto exit; 528 } 529 cil_tree_node_init(&new_ast); 530 new_ast->parent = ast_node; 531 new_ast->line = current_perm->line; 532 new_ast->hll_line = current_perm->hll_line; 533 534 rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms); 535 if (rc != SEPOL_OK) { 536 cil_tree_node_destroy(&new_ast); 537 goto exit; 538 } 539 540 if (ast_node->cl_head == NULL) { 541 ast_node->cl_head = new_ast; 542 } else { 543 ast_node->cl_tail->next = new_ast; 544 } 545 ast_node->cl_tail = new_ast; 546 547 current_perm = current_perm->next; 548 } 549 550 return SEPOL_OK; 551 552 exit: 553 cil_log(CIL_ERR, "Bad permissions\n"); 554 cil_tree_children_destroy(ast_node); 555 cil_clear_node(ast_node); 556 return rc; 557 } 558 559 int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms) 560 { 561 int rc = SEPOL_ERR; 562 enum cil_syntax syntax[] = { 563 CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS, 564 CIL_SYN_END 565 }; 566 int syntax_len = sizeof(syntax)/sizeof(*syntax); 567 568 rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len); 569 if (rc != SEPOL_OK) { 570 goto exit; 571 } 572 573 rc = cil_gen_expr(start_perm, CIL_PERM, perms); 574 if (rc != SEPOL_OK) { 575 goto exit; 576 } 577 578 return SEPOL_OK; 579 580 exit: 581 cil_log(CIL_ERR, "Bad permission list or expression\n"); 582 return rc; 583 } 584 585 int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classperms **cp) 586 { 587 int rc = SEPOL_ERR; 588 enum cil_syntax syntax[] = { 589 CIL_SYN_STRING, 590 CIL_SYN_LIST, 591 CIL_SYN_END 592 }; 593 int syntax_len = sizeof(syntax)/sizeof(*syntax); 594 595 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 596 if (rc != SEPOL_OK) { 597 goto exit; 598 } 599 600 cil_classperms_init(cp); 601 602 (*cp)->class_str = parse_current->data; 603 604 rc = cil_fill_perms(parse_current->next, &(*cp)->perm_strs); 605 if (rc != SEPOL_OK) { 606 cil_destroy_classperms(*cp); 607 goto exit; 608 } 609 610 return SEPOL_OK; 611 612 exit: 613 cil_log(CIL_ERR, "Bad class-permissions\n"); 614 *cp = NULL; 615 return rc; 616 } 617 618 void cil_destroy_classperms(struct cil_classperms *cp) 619 { 620 if (cp == NULL) { 621 return; 622 } 623 624 cil_list_destroy(&cp->perm_strs, CIL_TRUE); 625 cil_list_destroy(&cp->perms, CIL_FALSE); 626 627 free(cp); 628 } 629 630 void cil_fill_classperms_set(struct cil_tree_node *parse_current, struct cil_classperms_set **cp_set) 631 { 632 cil_classperms_set_init(cp_set); 633 (*cp_set)->set_str = parse_current->data; 634 } 635 636 void cil_destroy_classperms_set(struct cil_classperms_set *cp_set) 637 { 638 if (cp_set == NULL) { 639 return; 640 } 641 642 free(cp_set); 643 } 644 645 int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_list **cp_list) 646 { 647 int rc = SEPOL_ERR; 648 struct cil_tree_node *curr; 649 enum cil_syntax syntax[] = { 650 CIL_SYN_STRING | CIL_SYN_LIST, 651 }; 652 int syntax_len = sizeof(syntax)/sizeof(*syntax); 653 654 if (parse_current == NULL || cp_list == NULL) { 655 goto exit; 656 } 657 658 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 659 if (rc != SEPOL_OK) { 660 goto exit; 661 } 662 663 cil_list_init(cp_list, CIL_CLASSPERMS); 664 665 curr = parse_current->cl_head; 666 667 if (curr == NULL) { 668 /* Class-perms form: SET1 */ 669 struct cil_classperms_set *new_cp_set; 670 cil_fill_classperms_set(parse_current, &new_cp_set); 671 cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set); 672 } else if (curr->cl_head == NULL) { 673 /* Class-perms form: (CLASS1 (PERM1 ...)) */ 674 struct cil_classperms *new_cp; 675 rc = cil_fill_classperms(curr, &new_cp); 676 if (rc != SEPOL_OK) { 677 goto exit; 678 } 679 cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp); 680 } else { 681 cil_log(CIL_ERR, "Bad class-permissions list syntax\n"); 682 rc = SEPOL_ERR; 683 goto exit; 684 } 685 686 return SEPOL_OK; 687 688 exit: 689 cil_log(CIL_ERR, "Problem filling class-permissions list\n"); 690 cil_list_destroy(cp_list, CIL_TRUE); 691 return rc; 692 } 693 694 void cil_destroy_classperms_list(struct cil_list **cp_list) 695 { 696 struct cil_list_item *curr; 697 698 if (cp_list == NULL || *cp_list == NULL) { 699 return; 700 } 701 702 cil_list_for_each(curr, *cp_list) { 703 if (curr->flavor == CIL_CLASSPERMS) { 704 cil_destroy_classperms(curr->data); 705 } else { 706 cil_destroy_classperms_set(curr->data); 707 } 708 } 709 710 cil_list_destroy(cp_list, CIL_FALSE); 711 } 712 713 int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 714 { 715 int rc = SEPOL_ERR; 716 char *key = NULL; 717 struct cil_classpermission *cp = NULL; 718 enum cil_syntax syntax[] = { 719 CIL_SYN_STRING, 720 CIL_SYN_STRING, 721 CIL_SYN_END 722 }; 723 int syntax_len = sizeof(syntax)/sizeof(*syntax); 724 725 if (db == NULL || parse_current == NULL || ast_node == NULL) { 726 goto exit; 727 } 728 729 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 730 if (rc != SEPOL_OK) { 731 goto exit; 732 } 733 734 cil_classpermission_init(&cp); 735 736 key = parse_current->next->data; 737 738 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cp, (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS, CIL_CLASSPERMISSION); 739 if (rc != SEPOL_OK) { 740 goto exit; 741 } 742 743 return SEPOL_OK; 744 745 exit: 746 cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration"); 747 cil_destroy_classpermission(cp); 748 cil_clear_node(ast_node); 749 return rc; 750 } 751 752 void cil_destroy_classpermission(struct cil_classpermission *cp) 753 { 754 if (cp == NULL) { 755 return; 756 } 757 758 if (cp->datum.name != NULL) { 759 cil_list_destroy(&cp->classperms, CIL_FALSE); 760 } else { 761 /* anonymous classpermission from call */ 762 cil_destroy_classperms_list(&cp->classperms); 763 } 764 765 cil_symtab_datum_destroy(&cp->datum); 766 767 768 free(cp); 769 } 770 771 int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 772 { 773 int rc = SEPOL_ERR; 774 struct cil_classpermissionset *cps = NULL; 775 enum cil_syntax syntax[] = { 776 CIL_SYN_STRING, 777 CIL_SYN_STRING, 778 CIL_SYN_STRING | CIL_SYN_LIST, 779 CIL_SYN_END 780 }; 781 int syntax_len = sizeof(syntax)/sizeof(*syntax); 782 783 if (db == NULL || parse_current == NULL || ast_node == NULL) { 784 goto exit; 785 } 786 787 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 788 if (rc != SEPOL_OK) { 789 goto exit; 790 } 791 792 cil_classpermissionset_init(&cps); 793 794 cps->set_str = parse_current->next->data; 795 796 rc = cil_fill_classperms_list(parse_current->next->next, &cps->classperms); 797 if (rc != SEPOL_OK) { 798 goto exit; 799 } 800 801 ast_node->data = cps; 802 ast_node->flavor = CIL_CLASSPERMISSIONSET; 803 804 return SEPOL_OK; 805 806 exit: 807 cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset"); 808 cil_destroy_classpermissionset(cps); 809 return rc; 810 } 811 812 void cil_destroy_classpermissionset(struct cil_classpermissionset *cps) 813 { 814 if (cps == NULL) { 815 return; 816 } 817 818 cil_destroy_classperms_list(&cps->classperms); 819 820 free(cps); 821 } 822 823 int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 824 { 825 enum cil_syntax syntax[] = { 826 CIL_SYN_STRING, 827 CIL_SYN_STRING, 828 CIL_SYN_LIST, 829 CIL_SYN_END 830 }; 831 int syntax_len = sizeof(syntax)/sizeof(*syntax); 832 char *key = NULL; 833 struct cil_class *map = NULL; 834 int rc = SEPOL_ERR; 835 836 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 837 if (rc != SEPOL_OK) { 838 goto exit; 839 } 840 841 cil_class_init(&map); 842 843 key = parse_current->next->data; 844 845 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)map, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS); 846 if (rc != SEPOL_OK) { 847 goto exit; 848 } 849 850 rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_MAP_PERM, &map->num_perms); 851 if (rc != SEPOL_OK) { 852 goto exit; 853 } 854 855 return SEPOL_OK; 856 857 exit: 858 cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration"); 859 cil_destroy_class(map); 860 cil_clear_node(ast_node); 861 return rc; 862 } 863 864 int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 865 { 866 int rc = SEPOL_ERR; 867 struct cil_classmapping *mapping = NULL; 868 enum cil_syntax syntax[] = { 869 CIL_SYN_STRING, 870 CIL_SYN_STRING, 871 CIL_SYN_STRING, 872 CIL_SYN_STRING | CIL_SYN_LIST, 873 CIL_SYN_END 874 }; 875 int syntax_len = sizeof(syntax)/sizeof(*syntax); 876 877 if (db == NULL || parse_current == NULL || ast_node == NULL) { 878 goto exit; 879 } 880 881 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 882 if (rc != SEPOL_OK) { 883 goto exit; 884 } 885 886 cil_classmapping_init(&mapping); 887 888 mapping->map_class_str = parse_current->next->data; 889 mapping->map_perm_str = parse_current->next->next->data; 890 891 rc = cil_fill_classperms_list(parse_current->next->next->next, &mapping->classperms); 892 if (rc != SEPOL_OK) { 893 goto exit; 894 } 895 896 ast_node->data = mapping; 897 ast_node->flavor = CIL_CLASSMAPPING; 898 899 return SEPOL_OK; 900 901 exit: 902 cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration"); 903 cil_destroy_classmapping(mapping); 904 return rc; 905 } 906 907 void cil_destroy_classmapping(struct cil_classmapping *mapping) 908 { 909 if (mapping == NULL) { 910 return; 911 } 912 913 cil_destroy_classperms_list(&mapping->classperms); 914 915 free(mapping); 916 } 917 918 // TODO try to merge some of this with cil_gen_class (helper function for both) 919 int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 920 { 921 enum cil_syntax syntax[] = { 922 CIL_SYN_STRING, 923 CIL_SYN_STRING, 924 CIL_SYN_LIST, 925 CIL_SYN_END 926 }; 927 int syntax_len = sizeof(syntax)/sizeof(*syntax); 928 char *key = NULL; 929 struct cil_class *common = NULL; 930 int rc = SEPOL_ERR; 931 932 if (db == NULL || parse_current == NULL || ast_node == NULL) { 933 goto exit; 934 } 935 936 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 937 if (rc != SEPOL_OK) { 938 goto exit; 939 } 940 941 cil_class_init(&common); 942 943 key = parse_current->next->data; 944 945 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)common, (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON); 946 if (rc != SEPOL_OK) { 947 goto exit; 948 } 949 950 rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_PERM, &common->num_perms); 951 if (rc != SEPOL_OK) { 952 goto exit; 953 } 954 if (common->num_perms > CIL_PERMS_PER_CLASS) { 955 cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name); 956 goto exit; 957 } 958 959 return SEPOL_OK; 960 961 exit: 962 cil_tree_log(parse_current, CIL_ERR, "Bad common declaration"); 963 cil_destroy_class(common); 964 cil_clear_node(ast_node); 965 return rc; 966 967 } 968 969 int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 970 { 971 enum cil_syntax syntax[] = { 972 CIL_SYN_STRING, 973 CIL_SYN_STRING, 974 CIL_SYN_STRING, 975 CIL_SYN_END 976 }; 977 int syntax_len = sizeof(syntax)/sizeof(*syntax); 978 struct cil_classcommon *clscom = NULL; 979 int rc = SEPOL_ERR; 980 981 if (db == NULL || parse_current == NULL || ast_node == NULL) { 982 goto exit; 983 } 984 985 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 986 if (rc != SEPOL_OK) { 987 goto exit; 988 } 989 990 cil_classcommon_init(&clscom); 991 992 clscom->class_str = parse_current->next->data; 993 clscom->common_str = parse_current->next->next->data; 994 995 ast_node->data = clscom; 996 ast_node->flavor = CIL_CLASSCOMMON; 997 998 return SEPOL_OK; 999 1000 exit: 1001 cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration"); 1002 cil_destroy_classcommon(clscom); 1003 return rc; 1004 1005 } 1006 1007 void cil_destroy_classcommon(struct cil_classcommon *clscom) 1008 { 1009 if (clscom == NULL) { 1010 return; 1011 } 1012 1013 free(clscom); 1014 } 1015 1016 int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1017 { 1018 enum cil_syntax syntax[] = { 1019 CIL_SYN_STRING, 1020 CIL_SYN_STRING, 1021 CIL_SYN_END 1022 }; 1023 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1024 char *key = NULL; 1025 struct cil_sid *sid = NULL; 1026 int rc = SEPOL_ERR; 1027 1028 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1029 goto exit; 1030 } 1031 1032 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1033 if (rc != SEPOL_OK) { 1034 goto exit; 1035 } 1036 1037 cil_sid_init(&sid); 1038 1039 key = parse_current->next->data; 1040 1041 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sid, (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID); 1042 if (rc != SEPOL_OK) { 1043 goto exit; 1044 } 1045 1046 return SEPOL_OK; 1047 1048 exit: 1049 cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration"); 1050 cil_destroy_sid(sid); 1051 cil_clear_node(ast_node); 1052 return rc; 1053 } 1054 1055 void cil_destroy_sid(struct cil_sid *sid) 1056 { 1057 if (sid == NULL) { 1058 return; 1059 } 1060 1061 cil_symtab_datum_destroy(&sid->datum); 1062 free(sid); 1063 } 1064 1065 int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1066 { 1067 enum cil_syntax syntax[] = { 1068 CIL_SYN_STRING, 1069 CIL_SYN_STRING, 1070 CIL_SYN_STRING | CIL_SYN_LIST, 1071 CIL_SYN_END 1072 }; 1073 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1074 struct cil_sidcontext *sidcon = NULL; 1075 int rc = SEPOL_ERR; 1076 1077 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1078 goto exit; 1079 } 1080 1081 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1082 if (rc != SEPOL_OK) { 1083 goto exit; 1084 } 1085 1086 cil_sidcontext_init(&sidcon); 1087 1088 sidcon->sid_str = parse_current->next->data; 1089 1090 if (parse_current->next->next->cl_head == NULL) { 1091 sidcon->context_str = parse_current->next->next->data; 1092 } else { 1093 cil_context_init(&sidcon->context); 1094 1095 rc = cil_fill_context(parse_current->next->next->cl_head, sidcon->context); 1096 if (rc != SEPOL_OK) { 1097 goto exit; 1098 } 1099 } 1100 1101 ast_node->data = sidcon; 1102 ast_node->flavor = CIL_SIDCONTEXT; 1103 1104 return SEPOL_OK; 1105 1106 exit: 1107 cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration"); 1108 cil_destroy_sidcontext(sidcon); 1109 return rc; 1110 } 1111 1112 void cil_destroy_sidcontext(struct cil_sidcontext *sidcon) 1113 { 1114 if (sidcon == NULL) { 1115 return; 1116 } 1117 1118 if (sidcon->context_str == NULL && sidcon->context != NULL) { 1119 cil_destroy_context(sidcon->context); 1120 } 1121 1122 free(sidcon); 1123 } 1124 1125 int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1126 { 1127 enum cil_syntax syntax[] = { 1128 CIL_SYN_STRING, 1129 CIL_SYN_LIST, 1130 CIL_SYN_END 1131 }; 1132 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1133 struct cil_sidorder *sidorder = NULL; 1134 struct cil_list_item *curr = NULL; 1135 int rc = SEPOL_ERR; 1136 1137 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1138 goto exit; 1139 } 1140 1141 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1142 if (rc != SEPOL_OK) { 1143 goto exit; 1144 } 1145 1146 cil_sidorder_init(&sidorder); 1147 1148 rc = cil_fill_list(parse_current->next->cl_head, CIL_SIDORDER, &sidorder->sid_list_str); 1149 if (rc != SEPOL_OK) { 1150 goto exit; 1151 } 1152 1153 cil_list_for_each(curr, sidorder->sid_list_str) { 1154 if (curr->data == CIL_KEY_UNORDERED) { 1155 cil_log(CIL_ERR, "Sidorder cannot be unordered.\n"); 1156 rc = SEPOL_ERR; 1157 goto exit; 1158 } 1159 } 1160 1161 ast_node->data = sidorder; 1162 ast_node->flavor = CIL_SIDORDER; 1163 1164 return SEPOL_OK; 1165 1166 exit: 1167 cil_tree_log(parse_current, CIL_ERR, "Bad sidorder declaration"); 1168 cil_destroy_sidorder(sidorder); 1169 return rc; 1170 } 1171 1172 void cil_destroy_sidorder(struct cil_sidorder *sidorder) 1173 { 1174 if (sidorder == NULL) { 1175 return; 1176 } 1177 1178 if (sidorder->sid_list_str != NULL) { 1179 cil_list_destroy(&sidorder->sid_list_str, 1); 1180 } 1181 1182 free(sidorder); 1183 } 1184 1185 int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1186 { 1187 enum cil_syntax syntax[] = { 1188 CIL_SYN_STRING, 1189 CIL_SYN_STRING, 1190 CIL_SYN_END 1191 }; 1192 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1193 char *key = NULL; 1194 struct cil_user *user = NULL; 1195 int rc = SEPOL_ERR; 1196 1197 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1198 goto exit; 1199 } 1200 1201 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1202 if (rc != SEPOL_OK) { 1203 goto exit; 1204 } 1205 1206 cil_user_init(&user); 1207 1208 key = parse_current->next->data; 1209 1210 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)user, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER); 1211 if (rc != SEPOL_OK) { 1212 goto exit; 1213 } 1214 1215 return SEPOL_OK; 1216 1217 exit: 1218 cil_tree_log(parse_current, CIL_ERR, "Bad user declaration"); 1219 cil_destroy_user(user); 1220 cil_clear_node(ast_node); 1221 return rc; 1222 } 1223 1224 void cil_destroy_user(struct cil_user *user) 1225 { 1226 if (user == NULL) { 1227 return; 1228 } 1229 1230 cil_symtab_datum_destroy(&user->datum); 1231 ebitmap_destroy(user->roles); 1232 free(user->roles); 1233 free(user); 1234 } 1235 1236 int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1237 { 1238 enum cil_syntax syntax[] = { 1239 CIL_SYN_STRING, 1240 CIL_SYN_STRING, 1241 CIL_SYN_END 1242 }; 1243 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1244 char *key = NULL; 1245 struct cil_userattribute *attr = NULL; 1246 int rc = SEPOL_ERR; 1247 1248 if (parse_current == NULL || ast_node == NULL) { 1249 goto exit; 1250 } 1251 1252 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1253 if (rc != SEPOL_OK) { 1254 goto exit; 1255 } 1256 1257 cil_userattribute_init(&attr); 1258 1259 key = parse_current->next->data; 1260 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE); 1261 if (rc != SEPOL_OK) { 1262 goto exit; 1263 } 1264 1265 return SEPOL_OK; 1266 exit: 1267 cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration"); 1268 cil_destroy_userattribute(attr); 1269 cil_clear_node(ast_node); 1270 return rc; 1271 } 1272 1273 void cil_destroy_userattribute(struct cil_userattribute *attr) 1274 { 1275 struct cil_list_item *expr = NULL; 1276 struct cil_list_item *next = NULL; 1277 1278 if (attr == NULL) { 1279 return; 1280 } 1281 1282 if (attr->expr_list != NULL) { 1283 /* we don't want to destroy the expression stacks (cil_list) inside 1284 * this list cil_list_destroy destroys sublists, so we need to do it 1285 * manually */ 1286 expr = attr->expr_list->head; 1287 while (expr != NULL) { 1288 next = expr->next; 1289 cil_list_item_destroy(&expr, CIL_FALSE); 1290 expr = next; 1291 } 1292 free(attr->expr_list); 1293 attr->expr_list = NULL; 1294 } 1295 1296 cil_symtab_datum_destroy(&attr->datum); 1297 ebitmap_destroy(attr->users); 1298 free(attr->users); 1299 free(attr); 1300 } 1301 1302 int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1303 { 1304 enum cil_syntax syntax[] = { 1305 CIL_SYN_STRING, 1306 CIL_SYN_STRING, 1307 CIL_SYN_STRING | CIL_SYN_LIST, 1308 CIL_SYN_END 1309 }; 1310 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1311 struct cil_userattributeset *attrset = NULL; 1312 int rc = SEPOL_ERR; 1313 1314 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1315 goto exit; 1316 } 1317 1318 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1319 if (rc != SEPOL_OK) { 1320 goto exit; 1321 } 1322 1323 cil_userattributeset_init(&attrset); 1324 1325 attrset->attr_str = parse_current->next->data; 1326 1327 rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr); 1328 if (rc != SEPOL_OK) { 1329 goto exit; 1330 } 1331 ast_node->data = attrset; 1332 ast_node->flavor = CIL_USERATTRIBUTESET; 1333 1334 return SEPOL_OK; 1335 1336 exit: 1337 cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration"); 1338 cil_destroy_userattributeset(attrset); 1339 1340 return rc; 1341 } 1342 1343 void cil_destroy_userattributeset(struct cil_userattributeset *attrset) 1344 { 1345 if (attrset == NULL) { 1346 return; 1347 } 1348 1349 cil_list_destroy(&attrset->str_expr, CIL_TRUE); 1350 cil_list_destroy(&attrset->datum_expr, CIL_FALSE); 1351 1352 free(attrset); 1353 } 1354 1355 int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1356 { 1357 enum cil_syntax syntax[] = { 1358 CIL_SYN_STRING, 1359 CIL_SYN_STRING, 1360 CIL_SYN_STRING | CIL_SYN_LIST, 1361 CIL_SYN_END 1362 }; 1363 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1364 struct cil_userlevel *usrlvl = NULL; 1365 int rc = SEPOL_ERR; 1366 1367 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1368 goto exit; 1369 } 1370 1371 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1372 if (rc != SEPOL_OK) { 1373 goto exit; 1374 } 1375 1376 cil_userlevel_init(&usrlvl); 1377 1378 usrlvl->user_str = parse_current->next->data; 1379 1380 if (parse_current->next->next->cl_head == NULL) { 1381 usrlvl->level_str = parse_current->next->next->data; 1382 } else { 1383 cil_level_init(&usrlvl->level); 1384 1385 rc = cil_fill_level(parse_current->next->next->cl_head, usrlvl->level); 1386 if (rc != SEPOL_OK) { 1387 goto exit; 1388 } 1389 } 1390 1391 ast_node->data = usrlvl; 1392 ast_node->flavor = CIL_USERLEVEL; 1393 1394 return SEPOL_OK; 1395 1396 exit: 1397 cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration"); 1398 cil_destroy_userlevel(usrlvl); 1399 return rc; 1400 } 1401 1402 void cil_destroy_userlevel(struct cil_userlevel *usrlvl) 1403 { 1404 if (usrlvl == NULL) { 1405 return; 1406 } 1407 1408 if (usrlvl->level_str == NULL && usrlvl->level != NULL) { 1409 cil_destroy_level(usrlvl->level); 1410 } 1411 1412 free(usrlvl); 1413 } 1414 1415 int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1416 { 1417 enum cil_syntax syntax[] = { 1418 CIL_SYN_STRING, 1419 CIL_SYN_STRING, 1420 CIL_SYN_STRING | CIL_SYN_LIST, 1421 CIL_SYN_END 1422 }; 1423 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1424 struct cil_userrange *userrange = NULL; 1425 int rc = SEPOL_ERR; 1426 1427 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1428 goto exit; 1429 } 1430 1431 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1432 if (rc != SEPOL_OK) { 1433 goto exit; 1434 } 1435 1436 cil_userrange_init(&userrange); 1437 1438 userrange->user_str = parse_current->next->data; 1439 1440 if (parse_current->next->next->cl_head == NULL) { 1441 userrange->range_str = parse_current->next->next->data; 1442 } else { 1443 cil_levelrange_init(&userrange->range); 1444 1445 rc = cil_fill_levelrange(parse_current->next->next->cl_head, userrange->range); 1446 if (rc != SEPOL_OK) { 1447 goto exit; 1448 } 1449 } 1450 1451 ast_node->data = userrange; 1452 ast_node->flavor = CIL_USERRANGE; 1453 1454 return SEPOL_OK; 1455 1456 exit: 1457 cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration"); 1458 cil_destroy_userrange(userrange); 1459 return rc; 1460 } 1461 1462 void cil_destroy_userrange(struct cil_userrange *userrange) 1463 { 1464 if (userrange == NULL) { 1465 return; 1466 } 1467 1468 if (userrange->range_str == NULL && userrange->range != NULL) { 1469 cil_destroy_levelrange(userrange->range); 1470 } 1471 1472 free(userrange); 1473 } 1474 1475 int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1476 { 1477 enum cil_syntax syntax[] = { 1478 CIL_SYN_STRING, 1479 CIL_SYN_STRING, 1480 CIL_SYN_STRING, 1481 CIL_SYN_END 1482 }; 1483 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1484 struct cil_userprefix *userprefix = NULL; 1485 int rc = SEPOL_ERR; 1486 1487 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1488 goto exit; 1489 } 1490 1491 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1492 if (rc != SEPOL_OK) { 1493 goto exit; 1494 } 1495 1496 cil_userprefix_init(&userprefix); 1497 1498 userprefix->user_str = parse_current->next->data; 1499 userprefix->prefix_str = parse_current->next->next->data; 1500 1501 ast_node->data = userprefix; 1502 ast_node->flavor = CIL_USERPREFIX; 1503 1504 return SEPOL_OK; 1505 exit: 1506 cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration"); 1507 cil_destroy_userprefix(userprefix); 1508 return rc; 1509 } 1510 1511 void cil_destroy_userprefix(struct cil_userprefix *userprefix) 1512 { 1513 if (userprefix == NULL) { 1514 return; 1515 } 1516 1517 free(userprefix); 1518 } 1519 1520 int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1521 { 1522 enum cil_syntax syntax[] = { 1523 CIL_SYN_STRING, 1524 CIL_SYN_STRING, 1525 CIL_SYN_STRING, 1526 CIL_SYN_STRING | CIL_SYN_LIST, 1527 CIL_SYN_END 1528 }; 1529 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1530 struct cil_selinuxuser *selinuxuser = NULL; 1531 int rc = SEPOL_ERR; 1532 1533 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1534 goto exit; 1535 } 1536 1537 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1538 if (rc != SEPOL_OK) { 1539 goto exit; 1540 } 1541 1542 cil_selinuxuser_init(&selinuxuser); 1543 1544 selinuxuser->name_str = parse_current->next->data; 1545 selinuxuser->user_str = parse_current->next->next->data; 1546 1547 if (parse_current->next->next->next->cl_head == NULL) { 1548 selinuxuser->range_str = parse_current->next->next->next->data; 1549 } else { 1550 cil_levelrange_init(&selinuxuser->range); 1551 1552 rc = cil_fill_levelrange(parse_current->next->next->next->cl_head, selinuxuser->range); 1553 if (rc != SEPOL_OK) { 1554 goto exit; 1555 } 1556 } 1557 1558 ast_node->data = selinuxuser; 1559 ast_node->flavor = CIL_SELINUXUSER; 1560 1561 return SEPOL_OK; 1562 exit: 1563 cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration"); 1564 cil_destroy_selinuxuser(selinuxuser); 1565 return rc; 1566 } 1567 1568 int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1569 { 1570 enum cil_syntax syntax[] = { 1571 CIL_SYN_STRING, 1572 CIL_SYN_STRING, 1573 CIL_SYN_STRING | CIL_SYN_LIST, 1574 CIL_SYN_END 1575 }; 1576 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1577 struct cil_selinuxuser *selinuxuser = NULL; 1578 int rc = SEPOL_ERR; 1579 1580 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1581 goto exit; 1582 } 1583 1584 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1585 if (rc != SEPOL_OK) { 1586 goto exit; 1587 } 1588 1589 cil_selinuxuser_init(&selinuxuser); 1590 1591 selinuxuser->name_str = cil_strpool_add("__default__"); 1592 selinuxuser->user_str = parse_current->next->data; 1593 1594 if (parse_current->next->next->cl_head == NULL) { 1595 selinuxuser->range_str = parse_current->next->next->data; 1596 } else { 1597 cil_levelrange_init(&selinuxuser->range); 1598 1599 rc = cil_fill_levelrange(parse_current->next->next->cl_head, selinuxuser->range); 1600 if (rc != SEPOL_OK) { 1601 goto exit; 1602 } 1603 } 1604 1605 ast_node->data = selinuxuser; 1606 ast_node->flavor = CIL_SELINUXUSERDEFAULT; 1607 1608 return SEPOL_OK; 1609 exit: 1610 cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration"); 1611 cil_destroy_selinuxuser(selinuxuser); 1612 return rc; 1613 } 1614 1615 void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser) 1616 { 1617 if (selinuxuser == NULL) { 1618 return; 1619 } 1620 1621 if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) { 1622 cil_destroy_levelrange(selinuxuser->range); 1623 } 1624 1625 free(selinuxuser); 1626 } 1627 1628 int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1629 { 1630 enum cil_syntax syntax[] = { 1631 CIL_SYN_STRING, 1632 CIL_SYN_STRING, 1633 CIL_SYN_END 1634 }; 1635 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1636 char *key = NULL; 1637 struct cil_role *role = NULL; 1638 int rc = SEPOL_ERR; 1639 1640 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1641 goto exit; 1642 } 1643 1644 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1645 if (rc != SEPOL_OK) { 1646 goto exit; 1647 } 1648 1649 cil_role_init(&role); 1650 1651 key = parse_current->next->data; 1652 1653 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)role, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE); 1654 if (rc != SEPOL_OK) { 1655 goto exit; 1656 } 1657 1658 return SEPOL_OK; 1659 1660 exit: 1661 cil_tree_log(parse_current, CIL_ERR, "Bad role declaration"); 1662 cil_destroy_role(role); 1663 cil_clear_node(ast_node); 1664 return rc; 1665 } 1666 1667 void cil_destroy_role(struct cil_role *role) 1668 { 1669 if (role == NULL) { 1670 return; 1671 } 1672 1673 cil_symtab_datum_destroy(&role->datum); 1674 ebitmap_destroy(role->types); 1675 free(role->types); 1676 free(role); 1677 } 1678 1679 int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1680 { 1681 enum cil_syntax syntax[] = { 1682 CIL_SYN_STRING, 1683 CIL_SYN_STRING, 1684 CIL_SYN_STRING, 1685 CIL_SYN_END 1686 }; 1687 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1688 struct cil_roletype *roletype = NULL; 1689 int rc = SEPOL_ERR; 1690 1691 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1692 goto exit; 1693 } 1694 1695 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1696 if (rc != SEPOL_OK) { 1697 goto exit; 1698 } 1699 1700 cil_roletype_init(&roletype); 1701 1702 roletype->role_str = parse_current->next->data; 1703 roletype->type_str = parse_current->next->next->data; 1704 1705 ast_node->data = roletype; 1706 ast_node->flavor = CIL_ROLETYPE; 1707 1708 return SEPOL_OK; 1709 1710 exit: 1711 cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration"); 1712 cil_destroy_roletype(roletype); 1713 return rc; 1714 } 1715 1716 void cil_destroy_roletype(struct cil_roletype *roletype) 1717 { 1718 if (roletype == NULL) { 1719 return; 1720 } 1721 1722 free(roletype); 1723 } 1724 1725 int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1726 { 1727 enum cil_syntax syntax[] = { 1728 CIL_SYN_STRING, 1729 CIL_SYN_STRING, 1730 CIL_SYN_STRING, 1731 CIL_SYN_END 1732 }; 1733 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1734 struct cil_userrole *userrole = NULL; 1735 int rc = SEPOL_ERR; 1736 1737 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1738 goto exit; 1739 } 1740 1741 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1742 if (rc != SEPOL_OK) { 1743 goto exit; 1744 } 1745 1746 cil_userrole_init(&userrole); 1747 1748 userrole->user_str = parse_current->next->data; 1749 userrole->role_str = parse_current->next->next->data; 1750 1751 ast_node->data = userrole; 1752 ast_node->flavor = CIL_USERROLE; 1753 1754 return SEPOL_OK; 1755 1756 exit: 1757 cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration"); 1758 cil_destroy_userrole(userrole); 1759 return rc; 1760 } 1761 1762 void cil_destroy_userrole(struct cil_userrole *userrole) 1763 { 1764 if (userrole == NULL) { 1765 return; 1766 } 1767 1768 free(userrole); 1769 } 1770 1771 int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1772 { 1773 enum cil_syntax syntax[] = { 1774 CIL_SYN_STRING, 1775 CIL_SYN_STRING, 1776 CIL_SYN_STRING, 1777 CIL_SYN_STRING, 1778 CIL_SYN_STRING, 1779 CIL_SYN_END 1780 }; 1781 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1782 struct cil_roletransition *roletrans = NULL; 1783 int rc = SEPOL_ERR; 1784 1785 if (parse_current == NULL || ast_node == NULL) { 1786 goto exit; 1787 } 1788 1789 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1790 if (rc != SEPOL_OK) { 1791 goto exit; 1792 } 1793 1794 cil_roletransition_init(&roletrans); 1795 1796 roletrans->src_str = parse_current->next->data; 1797 roletrans->tgt_str = parse_current->next->next->data; 1798 roletrans->obj_str = parse_current->next->next->next->data; 1799 roletrans->result_str = parse_current->next->next->next->next->data; 1800 1801 ast_node->data = roletrans; 1802 ast_node->flavor = CIL_ROLETRANSITION; 1803 1804 return SEPOL_OK; 1805 1806 exit: 1807 cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule"); 1808 cil_destroy_roletransition(roletrans); 1809 return rc; 1810 } 1811 1812 void cil_destroy_roletransition(struct cil_roletransition *roletrans) 1813 { 1814 if (roletrans == NULL) { 1815 return; 1816 } 1817 1818 free(roletrans); 1819 } 1820 1821 int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1822 { 1823 enum cil_syntax syntax[] = { 1824 CIL_SYN_STRING, 1825 CIL_SYN_STRING, 1826 CIL_SYN_STRING, 1827 CIL_SYN_END 1828 }; 1829 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1830 struct cil_roleallow *roleallow = NULL; 1831 int rc = SEPOL_ERR; 1832 1833 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1834 goto exit; 1835 } 1836 1837 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1838 if (rc != SEPOL_OK) { 1839 goto exit; 1840 } 1841 1842 cil_roleallow_init(&roleallow); 1843 1844 roleallow->src_str = parse_current->next->data; 1845 roleallow->tgt_str = parse_current->next->next->data; 1846 1847 ast_node->data = roleallow; 1848 ast_node->flavor = CIL_ROLEALLOW; 1849 1850 return SEPOL_OK; 1851 1852 exit: 1853 cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule"); 1854 cil_destroy_roleallow(roleallow); 1855 return rc; 1856 } 1857 1858 void cil_destroy_roleallow(struct cil_roleallow *roleallow) 1859 { 1860 if (roleallow == NULL) { 1861 return; 1862 } 1863 1864 free(roleallow); 1865 } 1866 1867 int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1868 { 1869 enum cil_syntax syntax[] = { 1870 CIL_SYN_STRING, 1871 CIL_SYN_STRING, 1872 CIL_SYN_END 1873 }; 1874 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1875 char *key = NULL; 1876 struct cil_roleattribute *attr = NULL; 1877 int rc = SEPOL_ERR; 1878 1879 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1880 goto exit; 1881 } 1882 1883 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1884 if (rc != SEPOL_OK) { 1885 goto exit; 1886 } 1887 1888 if (parse_current->next->data == CIL_KEY_SELF) { 1889 cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); 1890 rc = SEPOL_ERR; 1891 goto exit; 1892 } 1893 1894 cil_roleattribute_init(&attr); 1895 1896 key = parse_current->next->data; 1897 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE); 1898 if (rc != SEPOL_OK) { 1899 goto exit; 1900 } 1901 1902 return SEPOL_OK; 1903 exit: 1904 cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration"); 1905 cil_destroy_roleattribute(attr); 1906 cil_clear_node(ast_node); 1907 return rc; 1908 } 1909 1910 void cil_destroy_roleattribute(struct cil_roleattribute *attr) 1911 { 1912 if (attr == NULL) { 1913 return; 1914 } 1915 1916 if (attr->expr_list != NULL) { 1917 /* we don't want to destroy the expression stacks (cil_list) inside 1918 * this list cil_list_destroy destroys sublists, so we need to do it 1919 * manually */ 1920 struct cil_list_item *expr = attr->expr_list->head; 1921 while (expr != NULL) { 1922 struct cil_list_item *next = expr->next; 1923 cil_list_item_destroy(&expr, CIL_FALSE); 1924 expr = next; 1925 } 1926 free(attr->expr_list); 1927 attr->expr_list = NULL; 1928 } 1929 1930 cil_symtab_datum_destroy(&attr->datum); 1931 ebitmap_destroy(attr->roles); 1932 free(attr->roles); 1933 free(attr); 1934 } 1935 1936 int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 1937 { 1938 enum cil_syntax syntax[] = { 1939 CIL_SYN_STRING, 1940 CIL_SYN_STRING, 1941 CIL_SYN_STRING | CIL_SYN_LIST, 1942 CIL_SYN_END 1943 }; 1944 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1945 struct cil_roleattributeset *attrset = NULL; 1946 int rc = SEPOL_ERR; 1947 1948 if (db == NULL || parse_current == NULL || ast_node == NULL) { 1949 goto exit; 1950 } 1951 1952 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 1953 if (rc != SEPOL_OK) { 1954 goto exit; 1955 } 1956 1957 cil_roleattributeset_init(&attrset); 1958 1959 attrset->attr_str = parse_current->next->data; 1960 1961 rc = cil_gen_expr(parse_current->next->next, CIL_ROLE, &attrset->str_expr); 1962 if (rc != SEPOL_OK) { 1963 goto exit; 1964 } 1965 ast_node->data = attrset; 1966 ast_node->flavor = CIL_ROLEATTRIBUTESET; 1967 1968 return SEPOL_OK; 1969 1970 exit: 1971 cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration"); 1972 cil_destroy_roleattributeset(attrset); 1973 1974 return rc; 1975 } 1976 1977 void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset) 1978 { 1979 if (attrset == NULL) { 1980 return; 1981 } 1982 1983 cil_list_destroy(&attrset->str_expr, CIL_TRUE); 1984 cil_list_destroy(&attrset->datum_expr, CIL_FALSE); 1985 1986 free(attrset); 1987 } 1988 1989 int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) 1990 { 1991 enum cil_syntax syntax[] = { 1992 CIL_SYN_STRING, 1993 CIL_SYN_STRING, 1994 CIL_SYN_STRING, 1995 CIL_SYN_STRING | CIL_SYN_LIST, 1996 CIL_SYN_END 1997 }; 1998 int syntax_len = sizeof(syntax)/sizeof(*syntax); 1999 struct cil_avrule *rule = NULL; 2000 int rc = SEPOL_ERR; 2001 2002 if (parse_current == NULL || ast_node == NULL) { 2003 goto exit; 2004 } 2005 2006 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2007 if (rc != SEPOL_OK) { 2008 goto exit; 2009 } 2010 2011 cil_avrule_init(&rule); 2012 2013 rule->is_extended = 0; 2014 rule->rule_kind = rule_kind; 2015 2016 rule->src_str = parse_current->next->data; 2017 rule->tgt_str = parse_current->next->next->data; 2018 2019 rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->perms.classperms); 2020 if (rc != SEPOL_OK) { 2021 goto exit; 2022 } 2023 2024 ast_node->data = rule; 2025 ast_node->flavor = CIL_AVRULE; 2026 2027 return SEPOL_OK; 2028 2029 exit: 2030 cil_tree_log(parse_current, CIL_ERR, "Bad allow rule"); 2031 cil_destroy_avrule(rule); 2032 return rc; 2033 } 2034 2035 void cil_destroy_avrule(struct cil_avrule *rule) 2036 { 2037 if (rule == NULL) { 2038 return; 2039 } 2040 2041 if (!rule->is_extended) { 2042 cil_destroy_classperms_list(&rule->perms.classperms); 2043 } else { 2044 if (rule->perms.x.permx_str == NULL && rule->perms.x.permx != NULL) { 2045 cil_destroy_permissionx(rule->perms.x.permx); 2046 } 2047 } 2048 2049 free(rule); 2050 } 2051 2052 int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx) 2053 { 2054 enum cil_syntax syntax[] = { 2055 CIL_SYN_STRING, 2056 CIL_SYN_STRING, 2057 CIL_SYN_LIST, 2058 CIL_SYN_END 2059 }; 2060 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2061 int rc = SEPOL_ERR; 2062 2063 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2064 if (rc != SEPOL_OK) { 2065 goto exit; 2066 } 2067 2068 if (parse_current->data == CIL_KEY_IOCTL) { 2069 permx->kind = CIL_PERMX_KIND_IOCTL; 2070 } else { 2071 cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data); 2072 rc = SEPOL_ERR; 2073 goto exit; 2074 } 2075 2076 permx->obj_str = parse_current->next->data; 2077 2078 rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str); 2079 if (rc != SEPOL_OK) { 2080 goto exit; 2081 } 2082 2083 return SEPOL_OK; 2084 2085 exit: 2086 cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content"); 2087 return rc; 2088 } 2089 2090 int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 2091 { 2092 enum cil_syntax syntax[] = { 2093 CIL_SYN_STRING, 2094 CIL_SYN_STRING, 2095 CIL_SYN_LIST, 2096 CIL_SYN_END 2097 }; 2098 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2099 char *key = NULL; 2100 struct cil_permissionx *permx = NULL; 2101 int rc = SEPOL_ERR; 2102 2103 if (parse_current == NULL || ast_node == NULL) { 2104 goto exit; 2105 } 2106 2107 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2108 if (rc != SEPOL_OK) { 2109 goto exit; 2110 } 2111 2112 cil_permissionx_init(&permx); 2113 2114 key = parse_current->next->data; 2115 2116 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX); 2117 if (rc != SEPOL_OK) { 2118 goto exit; 2119 } 2120 2121 rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx); 2122 if (rc != SEPOL_OK) { 2123 goto exit; 2124 } 2125 2126 return SEPOL_OK; 2127 2128 exit: 2129 cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement"); 2130 cil_destroy_permissionx(permx); 2131 cil_clear_node(ast_node); 2132 return rc; 2133 } 2134 2135 void cil_destroy_permissionx(struct cil_permissionx *permx) 2136 { 2137 if (permx == NULL) { 2138 return; 2139 } 2140 2141 cil_symtab_datum_destroy(&permx->datum); 2142 2143 cil_list_destroy(&permx->expr_str, CIL_TRUE); 2144 ebitmap_destroy(permx->perms); 2145 free(permx->perms); 2146 free(permx); 2147 } 2148 2149 int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) 2150 { 2151 enum cil_syntax syntax[] = { 2152 CIL_SYN_STRING, 2153 CIL_SYN_STRING, 2154 CIL_SYN_STRING, 2155 CIL_SYN_STRING | CIL_SYN_LIST, 2156 CIL_SYN_END 2157 }; 2158 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2159 struct cil_avrule *rule = NULL; 2160 int rc = SEPOL_ERR; 2161 2162 if (parse_current == NULL || ast_node == NULL) { 2163 goto exit; 2164 } 2165 2166 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2167 if (rc != SEPOL_OK) { 2168 goto exit; 2169 } 2170 2171 cil_avrule_init(&rule); 2172 2173 rule->is_extended = 1; 2174 rule->rule_kind = rule_kind; 2175 rule->src_str = parse_current->next->data; 2176 rule->tgt_str = parse_current->next->next->data; 2177 2178 if (parse_current->next->next->next->cl_head == NULL) { 2179 rule->perms.x.permx_str = parse_current->next->next->next->data; 2180 } else { 2181 cil_permissionx_init(&rule->perms.x.permx); 2182 2183 rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx); 2184 if (rc != SEPOL_OK) { 2185 goto exit; 2186 } 2187 } 2188 2189 ast_node->data = rule; 2190 ast_node->flavor = CIL_AVRULEX; 2191 2192 return SEPOL_OK; 2193 2194 exit: 2195 cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule"); 2196 cil_destroy_avrule(rule); 2197 return rc; 2198 } 2199 2200 int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) 2201 { 2202 enum cil_syntax syntax[] = { 2203 CIL_SYN_STRING, 2204 CIL_SYN_STRING, 2205 CIL_SYN_STRING, 2206 CIL_SYN_STRING, 2207 CIL_SYN_STRING, 2208 CIL_SYN_END 2209 }; 2210 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2211 struct cil_type_rule *rule = NULL; 2212 int rc = SEPOL_ERR; 2213 2214 if (parse_current == NULL || ast_node == NULL) { 2215 goto exit; 2216 } 2217 2218 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2219 if (rc != SEPOL_OK) { 2220 goto exit; 2221 } 2222 2223 cil_type_rule_init(&rule); 2224 2225 rule->rule_kind = rule_kind; 2226 rule->src_str = parse_current->next->data; 2227 rule->tgt_str = parse_current->next->next->data; 2228 rule->obj_str = parse_current->next->next->next->data; 2229 rule->result_str = parse_current->next->next->next->next->data; 2230 2231 ast_node->data = rule; 2232 ast_node->flavor = CIL_TYPE_RULE; 2233 2234 return SEPOL_OK; 2235 2236 exit: 2237 cil_tree_log(parse_current, CIL_ERR, "Bad type rule"); 2238 cil_destroy_type_rule(rule); 2239 return rc; 2240 } 2241 2242 void cil_destroy_type_rule(struct cil_type_rule *rule) 2243 { 2244 if (rule == NULL) { 2245 return; 2246 } 2247 2248 free(rule); 2249 } 2250 2251 int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 2252 { 2253 enum cil_syntax syntax[] = { 2254 CIL_SYN_STRING, 2255 CIL_SYN_STRING, 2256 CIL_SYN_END 2257 }; 2258 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2259 char *key = NULL; 2260 struct cil_type *type = NULL; 2261 int rc = SEPOL_ERR; 2262 2263 if (db == NULL || parse_current == NULL || ast_node == NULL) { 2264 goto exit; 2265 } 2266 2267 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2268 if (rc != SEPOL_OK) { 2269 goto exit; 2270 } 2271 2272 if (parse_current->next->data == CIL_KEY_SELF) { 2273 cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); 2274 rc = SEPOL_ERR; 2275 goto exit; 2276 } 2277 2278 cil_type_init(&type); 2279 2280 key = parse_current->next->data; 2281 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE); 2282 if (rc != SEPOL_OK) { 2283 goto exit; 2284 } 2285 2286 return SEPOL_OK; 2287 2288 exit: 2289 cil_tree_log(parse_current, CIL_ERR, "Bad type declaration"); 2290 cil_destroy_type(type); 2291 cil_clear_node(ast_node); 2292 return rc; 2293 } 2294 2295 void cil_destroy_type(struct cil_type *type) 2296 { 2297 if (type == NULL) { 2298 return; 2299 } 2300 2301 cil_symtab_datum_destroy(&type->datum); 2302 free(type); 2303 } 2304 2305 int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 2306 { 2307 enum cil_syntax syntax[] = { 2308 CIL_SYN_STRING, 2309 CIL_SYN_STRING, 2310 CIL_SYN_END 2311 }; 2312 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2313 char *key = NULL; 2314 struct cil_typeattribute *attr = NULL; 2315 int rc = SEPOL_ERR; 2316 2317 if (db == NULL || parse_current == NULL || ast_node == NULL) { 2318 goto exit; 2319 } 2320 2321 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2322 if (rc != SEPOL_OK) { 2323 goto exit; 2324 } 2325 2326 if (parse_current->next->data == CIL_KEY_SELF) { 2327 cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); 2328 rc = SEPOL_ERR; 2329 goto exit; 2330 } 2331 2332 cil_typeattribute_init(&attr); 2333 2334 key = parse_current->next->data; 2335 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE); 2336 if (rc != SEPOL_OK) { 2337 goto exit; 2338 } 2339 2340 return SEPOL_OK; 2341 2342 exit: 2343 cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration"); 2344 cil_destroy_typeattribute(attr); 2345 cil_clear_node(ast_node); 2346 return rc; 2347 } 2348 2349 void cil_destroy_typeattribute(struct cil_typeattribute *attr) 2350 { 2351 if (attr == NULL) { 2352 return; 2353 } 2354 2355 cil_symtab_datum_destroy(&attr->datum); 2356 2357 if (attr->expr_list != NULL) { 2358 /* we don't want to destroy the expression stacks (cil_list) inside 2359 * this list cil_list_destroy destroys sublists, so we need to do it 2360 * manually */ 2361 struct cil_list_item *expr = attr->expr_list->head; 2362 while (expr != NULL) { 2363 struct cil_list_item *next = expr->next; 2364 cil_list_item_destroy(&expr, CIL_FALSE); 2365 expr = next; 2366 } 2367 free(attr->expr_list); 2368 attr->expr_list = NULL; 2369 } 2370 ebitmap_destroy(attr->types); 2371 free(attr->types); 2372 free(attr); 2373 } 2374 2375 int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) 2376 { 2377 enum cil_syntax syntax[] = { 2378 CIL_SYN_STRING, 2379 CIL_SYN_STRING, 2380 CIL_SYN_STRING, 2381 CIL_SYN_END 2382 }; 2383 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2384 char *key = NULL; 2385 struct cil_bool *boolean = NULL; 2386 int rc = SEPOL_ERR; 2387 2388 if (db == NULL || parse_current == NULL || ast_node == NULL) { 2389 goto exit; 2390 } 2391 2392 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2393 if (rc != SEPOL_OK) { 2394 goto exit; 2395 } 2396 2397 cil_bool_init(&boolean); 2398 2399 key = parse_current->next->data; 2400 2401 if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { 2402 boolean->value = CIL_TRUE; 2403 } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { 2404 boolean->value = CIL_FALSE; 2405 } else { 2406 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); 2407 rc = SEPOL_ERR; 2408 goto exit; 2409 } 2410 2411 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL); 2412 if (rc != SEPOL_OK) { 2413 goto exit; 2414 } 2415 2416 return SEPOL_OK; 2417 2418 exit: 2419 if (tunableif) { 2420 cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration"); 2421 } else { 2422 cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration"); 2423 } 2424 cil_destroy_bool(boolean); 2425 cil_clear_node(ast_node); 2426 return rc; 2427 } 2428 2429 void cil_destroy_bool(struct cil_bool *boolean) 2430 { 2431 if (boolean == NULL) { 2432 return; 2433 } 2434 2435 cil_symtab_datum_destroy(&boolean->datum); 2436 free(boolean); 2437 } 2438 2439 int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 2440 { 2441 enum cil_syntax syntax[] = { 2442 CIL_SYN_STRING, 2443 CIL_SYN_STRING, 2444 CIL_SYN_STRING, 2445 CIL_SYN_END 2446 }; 2447 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2448 char *key = NULL; 2449 struct cil_tunable *tunable = NULL; 2450 int rc = SEPOL_ERR; 2451 2452 if (db == NULL || parse_current == NULL || ast_node == NULL) { 2453 goto exit; 2454 } 2455 2456 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2457 if (rc != SEPOL_OK) { 2458 goto exit; 2459 } 2460 2461 cil_tunable_init(&tunable); 2462 2463 key = parse_current->next->data; 2464 2465 if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { 2466 tunable->value = CIL_TRUE; 2467 } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { 2468 tunable->value = CIL_FALSE; 2469 } else { 2470 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); 2471 rc = SEPOL_ERR; 2472 goto exit; 2473 } 2474 2475 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE); 2476 if (rc != SEPOL_OK) { 2477 goto exit; 2478 } 2479 2480 return SEPOL_OK; 2481 2482 exit: 2483 cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration"); 2484 cil_destroy_tunable(tunable); 2485 cil_clear_node(ast_node); 2486 return rc; 2487 } 2488 2489 void cil_destroy_tunable(struct cil_tunable *tunable) 2490 { 2491 if (tunable == NULL) { 2492 return; 2493 } 2494 2495 cil_symtab_datum_destroy(&tunable->datum); 2496 free(tunable); 2497 } 2498 2499 static enum cil_flavor __cil_get_expr_operator_flavor(const char *op) 2500 { 2501 if (op == NULL) return CIL_NONE; 2502 else if (op == CIL_KEY_AND) return CIL_AND; 2503 else if (op == CIL_KEY_OR) return CIL_OR; 2504 else if (op == CIL_KEY_NOT) return CIL_NOT; 2505 else if (op == CIL_KEY_EQ) return CIL_EQ; /* Only conditional */ 2506 else if (op == CIL_KEY_NEQ) return CIL_NEQ; /* Only conditional */ 2507 else if (op == CIL_KEY_XOR) return CIL_XOR; 2508 else if (op == CIL_KEY_ALL) return CIL_ALL; /* Only set and permissionx */ 2509 else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */ 2510 else return CIL_NONE; 2511 } 2512 2513 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth); 2514 2515 static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth) 2516 { 2517 int rc = SEPOL_ERR; 2518 enum cil_flavor op; 2519 2520 if (flavor == CIL_BOOL && *depth > COND_EXPR_MAXDEPTH) { 2521 cil_log(CIL_ERR, "Max depth of %d exceeded for boolean expression\n", COND_EXPR_MAXDEPTH); 2522 goto exit; 2523 } 2524 2525 op = __cil_get_expr_operator_flavor(current->data); 2526 2527 rc = cil_verify_expr_syntax(current, op, flavor); 2528 if (rc != SEPOL_OK) { 2529 goto exit; 2530 } 2531 2532 if (op != CIL_NONE) { 2533 cil_list_append(expr, CIL_OP, (void *)op); 2534 current = current->next; 2535 } 2536 2537 if (op == CIL_NONE || op == CIL_ALL) { 2538 (*depth)++; 2539 } 2540 2541 for (;current != NULL; current = current->next) { 2542 rc = __cil_fill_expr(current, flavor, expr, depth); 2543 if (rc != SEPOL_OK) { 2544 goto exit; 2545 } 2546 } 2547 2548 (*depth)--; 2549 2550 return SEPOL_OK; 2551 2552 exit: 2553 return rc; 2554 } 2555 2556 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth) 2557 { 2558 int rc = SEPOL_ERR; 2559 2560 if (current->cl_head == NULL) { 2561 enum cil_flavor op = __cil_get_expr_operator_flavor(current->data); 2562 if (op != CIL_NONE) { 2563 cil_log(CIL_ERR, "Operator (%s) not in an expression\n", (char*)current->data); 2564 goto exit; 2565 } 2566 cil_list_append(expr, CIL_STRING, current->data); 2567 } else { 2568 struct cil_list *sub_expr; 2569 cil_list_init(&sub_expr, flavor); 2570 rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr, depth); 2571 if (rc != SEPOL_OK) { 2572 cil_list_destroy(&sub_expr, CIL_TRUE); 2573 goto exit; 2574 } 2575 cil_list_append(expr, CIL_LIST, sub_expr); 2576 } 2577 2578 return SEPOL_OK; 2579 2580 exit: 2581 return rc; 2582 } 2583 2584 2585 int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) 2586 { 2587 int rc = SEPOL_ERR; 2588 int depth = 0; 2589 2590 cil_list_init(expr, flavor); 2591 2592 if (current->cl_head == NULL) { 2593 rc = __cil_fill_expr(current, flavor, *expr, &depth); 2594 } else { 2595 rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr, &depth); 2596 } 2597 2598 if (rc != SEPOL_OK) { 2599 cil_list_destroy(expr, CIL_TRUE); 2600 cil_log(CIL_ERR, "Bad expression\n"); 2601 } 2602 2603 return rc; 2604 } 2605 2606 static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op) 2607 { 2608 if (op == CIL_KEY_AND) return CIL_AND; 2609 else if (op == CIL_KEY_OR) return CIL_OR; 2610 else if (op == CIL_KEY_NOT) return CIL_NOT; 2611 else if (op == CIL_KEY_EQ) return CIL_EQ; 2612 else if (op == CIL_KEY_NEQ) return CIL_NEQ; 2613 else if (op == CIL_KEY_CONS_DOM) return CIL_CONS_DOM; 2614 else if (op == CIL_KEY_CONS_DOMBY) return CIL_CONS_DOMBY; 2615 else if (op == CIL_KEY_CONS_INCOMP) return CIL_CONS_INCOMP; 2616 else return CIL_NONE; 2617 } 2618 2619 static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand) 2620 { 2621 if (operand == NULL) return CIL_LIST; 2622 else if (operand == CIL_KEY_CONS_T1) return CIL_CONS_T1; 2623 else if (operand == CIL_KEY_CONS_T2) return CIL_CONS_T2; 2624 else if (operand == CIL_KEY_CONS_T3) return CIL_CONS_T3; 2625 else if (operand == CIL_KEY_CONS_R1) return CIL_CONS_R1; 2626 else if (operand == CIL_KEY_CONS_R2) return CIL_CONS_R2; 2627 else if (operand == CIL_KEY_CONS_R3) return CIL_CONS_R3; 2628 else if (operand == CIL_KEY_CONS_U1) return CIL_CONS_U1; 2629 else if (operand == CIL_KEY_CONS_U2) return CIL_CONS_U2; 2630 else if (operand == CIL_KEY_CONS_U3) return CIL_CONS_U3; 2631 else if (operand == CIL_KEY_CONS_L1) return CIL_CONS_L1; 2632 else if (operand == CIL_KEY_CONS_L2) return CIL_CONS_L2; 2633 else if (operand == CIL_KEY_CONS_H1) return CIL_CONS_H1; 2634 else if (operand == CIL_KEY_CONS_H2) return CIL_CONS_H2; 2635 else return CIL_STRING; 2636 } 2637 2638 static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum cil_flavor expr_flavor, enum cil_flavor op, struct cil_list **leaf_expr) 2639 { 2640 int rc = SEPOL_ERR; 2641 enum cil_flavor leaf_expr_flavor = CIL_NONE; 2642 enum cil_flavor l_flavor = CIL_NONE; 2643 enum cil_flavor r_flavor = CIL_NONE; 2644 2645 l_flavor = __cil_get_constraint_operand_flavor(current->next->data); 2646 r_flavor = __cil_get_constraint_operand_flavor(current->next->next->data); 2647 2648 switch (l_flavor) { 2649 case CIL_CONS_U1: 2650 case CIL_CONS_U2: 2651 case CIL_CONS_U3: 2652 leaf_expr_flavor = CIL_USER; 2653 break; 2654 case CIL_CONS_R1: 2655 case CIL_CONS_R2: 2656 case CIL_CONS_R3: 2657 leaf_expr_flavor = CIL_ROLE; 2658 break; 2659 case CIL_CONS_T1: 2660 case CIL_CONS_T2: 2661 case CIL_CONS_T3: 2662 leaf_expr_flavor = CIL_TYPE; 2663 break; 2664 case CIL_CONS_L1: 2665 case CIL_CONS_L2: 2666 case CIL_CONS_H1: 2667 case CIL_CONS_H2: 2668 leaf_expr_flavor = CIL_LEVEL; 2669 break; 2670 default: 2671 cil_log(CIL_ERR, "Invalid left operand (%s)\n", (char*)current->next->data); 2672 goto exit; 2673 } 2674 2675 rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op, expr_flavor); 2676 if (rc != SEPOL_OK) { 2677 goto exit; 2678 } 2679 2680 cil_list_init(leaf_expr, leaf_expr_flavor); 2681 2682 cil_list_append(*leaf_expr, CIL_OP, (void *)op); 2683 2684 cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor); 2685 2686 if (r_flavor == CIL_STRING) { 2687 cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data); 2688 } else if (r_flavor == CIL_LIST) { 2689 struct cil_list *sub_list; 2690 cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list); 2691 cil_list_append(*leaf_expr, CIL_LIST, &sub_list); 2692 } else { 2693 cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor); 2694 } 2695 2696 return SEPOL_OK; 2697 2698 exit: 2699 2700 return SEPOL_ERR; 2701 } 2702 2703 static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr, int *depth) 2704 { 2705 int rc = SEPOL_ERR; 2706 enum cil_flavor op; 2707 struct cil_list *lexpr; 2708 struct cil_list *rexpr; 2709 2710 if (current->data == NULL || current->cl_head != NULL) { 2711 cil_log(CIL_ERR, "Expected a string at the start of the constraint expression\n"); 2712 goto exit; 2713 } 2714 2715 if (*depth > CEXPR_MAXDEPTH) { 2716 cil_log(CIL_ERR, "Max depth of %d exceeded for constraint expression\n", CEXPR_MAXDEPTH); 2717 rc = SEPOL_ERR; 2718 goto exit; 2719 } 2720 2721 op = __cil_get_constraint_operator_flavor(current->data); 2722 2723 rc = cil_verify_constraint_expr_syntax(current, op); 2724 if (rc != SEPOL_OK) { 2725 goto exit; 2726 } 2727 2728 switch (op) { 2729 case CIL_EQ: 2730 case CIL_NEQ: 2731 case CIL_CONS_DOM: 2732 case CIL_CONS_DOMBY: 2733 case CIL_CONS_INCOMP: 2734 (*depth)++; 2735 rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr); 2736 if (rc != SEPOL_OK) { 2737 goto exit; 2738 } 2739 break; 2740 case CIL_NOT: 2741 rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth); 2742 if (rc != SEPOL_OK) { 2743 goto exit; 2744 } 2745 cil_list_init(expr, flavor); 2746 cil_list_append(*expr, CIL_OP, (void *)op); 2747 cil_list_append(*expr, CIL_LIST, lexpr); 2748 break; 2749 default: 2750 rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth); 2751 if (rc != SEPOL_OK) { 2752 goto exit; 2753 } 2754 rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr, depth); 2755 if (rc != SEPOL_OK) { 2756 cil_list_destroy(&lexpr, CIL_TRUE); 2757 goto exit; 2758 } 2759 cil_list_init(expr, flavor); 2760 cil_list_append(*expr, CIL_OP, (void *)op); 2761 cil_list_append(*expr, CIL_LIST, lexpr); 2762 cil_list_append(*expr, CIL_LIST, rexpr); 2763 break; 2764 } 2765 2766 (*depth)--; 2767 2768 return SEPOL_OK; 2769 exit: 2770 2771 return rc; 2772 } 2773 2774 int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) 2775 { 2776 int rc = SEPOL_ERR; 2777 int depth = 0; 2778 2779 if (current->cl_head == NULL) { 2780 goto exit; 2781 } 2782 2783 rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr, &depth); 2784 if (rc != SEPOL_OK) { 2785 goto exit; 2786 } 2787 2788 return SEPOL_OK; 2789 2790 exit: 2791 2792 cil_log(CIL_ERR, "Bad expression tree for constraint\n"); 2793 return rc; 2794 } 2795 2796 int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) 2797 { 2798 enum cil_syntax syntax[] = { 2799 CIL_SYN_STRING, 2800 CIL_SYN_STRING | CIL_SYN_LIST, 2801 CIL_SYN_LIST, 2802 CIL_SYN_LIST | CIL_SYN_END, 2803 CIL_SYN_END 2804 }; 2805 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2806 struct cil_booleanif *bif = NULL; 2807 struct cil_tree_node *next = NULL; 2808 struct cil_tree_node *cond = NULL; 2809 int rc = SEPOL_ERR; 2810 2811 if (db == NULL || parse_current == NULL || ast_node == NULL) { 2812 goto exit; 2813 } 2814 2815 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2816 if (rc != SEPOL_OK) { 2817 goto exit; 2818 } 2819 2820 cil_boolif_init(&bif); 2821 bif->preserved_tunable = tunableif; 2822 2823 rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr); 2824 if (rc != SEPOL_OK) { 2825 goto exit; 2826 } 2827 2828 cond = parse_current->next->next; 2829 2830 /* Destroying expr tree after stack is created*/ 2831 if (cond->cl_head->data != CIL_KEY_CONDTRUE && 2832 cond->cl_head->data != CIL_KEY_CONDFALSE) { 2833 rc = SEPOL_ERR; 2834 cil_log(CIL_ERR, "Conditional neither true nor false\n"); 2835 goto exit; 2836 } 2837 2838 if (cond->next != NULL) { 2839 cond = cond->next; 2840 if (cond->cl_head->data != CIL_KEY_CONDTRUE && 2841 cond->cl_head->data != CIL_KEY_CONDFALSE) { 2842 rc = SEPOL_ERR; 2843 cil_log(CIL_ERR, "Conditional neither true nor false\n"); 2844 goto exit; 2845 } 2846 } 2847 2848 2849 next = parse_current->next->next; 2850 cil_tree_subtree_destroy(parse_current->next); 2851 parse_current->next = next; 2852 2853 ast_node->flavor = CIL_BOOLEANIF; 2854 ast_node->data = bif; 2855 2856 return SEPOL_OK; 2857 2858 exit: 2859 if (tunableif) { 2860 cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration"); 2861 } else { 2862 cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration"); 2863 } 2864 cil_destroy_boolif(bif); 2865 return rc; 2866 } 2867 2868 void cil_destroy_boolif(struct cil_booleanif *bif) 2869 { 2870 if (bif == NULL) { 2871 return; 2872 } 2873 2874 cil_list_destroy(&bif->str_expr, CIL_TRUE); 2875 cil_list_destroy(&bif->datum_expr, CIL_FALSE); 2876 2877 free(bif); 2878 } 2879 2880 int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 2881 { 2882 enum cil_syntax syntax[] = { 2883 CIL_SYN_STRING, 2884 CIL_SYN_STRING | CIL_SYN_LIST, 2885 CIL_SYN_LIST, 2886 CIL_SYN_LIST | CIL_SYN_END, 2887 CIL_SYN_END 2888 }; 2889 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2890 struct cil_tunableif *tif = NULL; 2891 struct cil_tree_node *next = NULL; 2892 struct cil_tree_node *cond = NULL; 2893 int rc = SEPOL_ERR; 2894 2895 if (db == NULL || parse_current == NULL || ast_node == NULL) { 2896 goto exit; 2897 } 2898 2899 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2900 if (rc != SEPOL_OK) { 2901 goto exit; 2902 } 2903 2904 cil_tunif_init(&tif); 2905 2906 rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr); 2907 if (rc != SEPOL_OK) { 2908 goto exit; 2909 } 2910 2911 cond = parse_current->next->next; 2912 2913 if (cond->cl_head->data != CIL_KEY_CONDTRUE && 2914 cond->cl_head->data != CIL_KEY_CONDFALSE) { 2915 rc = SEPOL_ERR; 2916 cil_log(CIL_ERR, "Conditional neither true nor false\n"); 2917 goto exit; 2918 } 2919 2920 if (cond->next != NULL) { 2921 cond = cond->next; 2922 2923 if (cond->cl_head->data != CIL_KEY_CONDTRUE && 2924 cond->cl_head->data != CIL_KEY_CONDFALSE) { 2925 rc = SEPOL_ERR; 2926 cil_log(CIL_ERR, "Conditional neither true nor false\n"); 2927 goto exit; 2928 } 2929 } 2930 2931 /* Destroying expr tree after stack is created*/ 2932 next = parse_current->next->next; 2933 cil_tree_subtree_destroy(parse_current->next); 2934 parse_current->next = next; 2935 2936 ast_node->flavor = CIL_TUNABLEIF; 2937 ast_node->data = tif; 2938 2939 return SEPOL_OK; 2940 2941 exit: 2942 cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration"); 2943 cil_destroy_tunif(tif); 2944 return rc; 2945 } 2946 2947 void cil_destroy_tunif(struct cil_tunableif *tif) 2948 { 2949 if (tif == NULL) { 2950 return; 2951 } 2952 2953 cil_list_destroy(&tif->str_expr, CIL_TRUE); 2954 cil_list_destroy(&tif->datum_expr, CIL_FALSE); 2955 2956 free(tif); 2957 } 2958 2959 int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) 2960 { 2961 enum cil_syntax syntax[] = { 2962 CIL_SYN_STRING, 2963 CIL_SYN_N_LISTS, 2964 CIL_SYN_END 2965 }; 2966 int syntax_len = sizeof(syntax)/sizeof(*syntax); 2967 int rc = SEPOL_ERR; 2968 struct cil_condblock *cb = NULL; 2969 2970 if (db == NULL || parse_current == NULL || ast_node == NULL) { 2971 goto exit; 2972 } 2973 2974 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 2975 if (rc != SEPOL_OK) { 2976 goto exit; 2977 } 2978 2979 if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) { 2980 rc = SEPOL_ERR; 2981 cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n"); 2982 goto exit; 2983 } 2984 2985 ast_node->flavor = CIL_CONDBLOCK; 2986 2987 cil_condblock_init(&cb); 2988 cb->flavor = flavor; 2989 2990 ast_node->data = cb; 2991 2992 return SEPOL_OK; 2993 2994 exit: 2995 cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration", 2996 (char*)parse_current->data); 2997 cil_destroy_condblock(cb); 2998 return rc; 2999 } 3000 3001 void cil_destroy_condblock(struct cil_condblock *cb) 3002 { 3003 if (cb == NULL) { 3004 return; 3005 } 3006 3007 cil_symtab_array_destroy(cb->symtab); 3008 free(cb); 3009 } 3010 3011 int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) 3012 { 3013 enum cil_syntax syntax[] = { 3014 CIL_SYN_STRING, 3015 CIL_SYN_STRING, 3016 CIL_SYN_END 3017 }; 3018 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3019 char *key = NULL; 3020 struct cil_alias *alias = NULL; 3021 enum cil_sym_index sym_index; 3022 int rc = SEPOL_ERR; 3023 3024 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3025 goto exit; 3026 } 3027 3028 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3029 if (rc != SEPOL_OK) { 3030 goto exit; 3031 } 3032 3033 if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) { 3034 cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); 3035 rc = SEPOL_ERR; 3036 goto exit; 3037 } 3038 3039 cil_alias_init(&alias); 3040 3041 key = parse_current->next->data; 3042 3043 rc = cil_flavor_to_symtab_index(flavor, &sym_index); 3044 if (rc != SEPOL_OK) { 3045 goto exit; 3046 } 3047 3048 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor); 3049 if (rc != SEPOL_OK) { 3050 goto exit; 3051 } 3052 3053 return SEPOL_OK; 3054 3055 exit: 3056 cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data); 3057 cil_destroy_alias(alias); 3058 cil_clear_node(ast_node); 3059 return rc; 3060 } 3061 3062 void cil_destroy_alias(struct cil_alias *alias) 3063 { 3064 if (alias == NULL) { 3065 return; 3066 } 3067 3068 cil_symtab_datum_destroy(&alias->datum); 3069 alias->actual = NULL; 3070 3071 free(alias); 3072 } 3073 3074 int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) 3075 { 3076 int rc = SEPOL_ERR; 3077 enum cil_syntax syntax[] = { 3078 CIL_SYN_STRING, 3079 CIL_SYN_STRING, 3080 CIL_SYN_STRING, 3081 CIL_SYN_END 3082 }; 3083 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3084 struct cil_aliasactual *aliasactual = NULL; 3085 3086 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3087 goto exit; 3088 } 3089 3090 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3091 if (rc != SEPOL_OK) { 3092 goto exit; 3093 } 3094 3095 if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) { 3096 cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); 3097 rc = SEPOL_ERR; 3098 goto exit; 3099 } 3100 3101 cil_aliasactual_init(&aliasactual); 3102 3103 aliasactual->alias_str = parse_current->next->data; 3104 3105 aliasactual->actual_str = parse_current->next->next->data; 3106 3107 ast_node->data = aliasactual; 3108 ast_node->flavor = flavor; 3109 3110 return SEPOL_OK; 3111 3112 exit: 3113 cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current)); 3114 cil_clear_node(ast_node); 3115 return rc; 3116 } 3117 3118 void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual) 3119 { 3120 if (aliasactual == NULL) { 3121 return; 3122 } 3123 3124 free(aliasactual); 3125 } 3126 3127 int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3128 { 3129 enum cil_syntax syntax[] = { 3130 CIL_SYN_STRING, 3131 CIL_SYN_STRING, 3132 CIL_SYN_STRING | CIL_SYN_LIST, 3133 CIL_SYN_END 3134 }; 3135 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3136 struct cil_typeattributeset *attrset = NULL; 3137 int rc = SEPOL_ERR; 3138 3139 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3140 goto exit; 3141 } 3142 3143 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3144 if (rc != SEPOL_OK) { 3145 goto exit; 3146 } 3147 3148 cil_typeattributeset_init(&attrset); 3149 3150 attrset->attr_str = parse_current->next->data; 3151 3152 rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr); 3153 if (rc != SEPOL_OK) { 3154 goto exit; 3155 } 3156 ast_node->data = attrset; 3157 ast_node->flavor = CIL_TYPEATTRIBUTESET; 3158 3159 return SEPOL_OK; 3160 3161 exit: 3162 cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement"); 3163 cil_destroy_typeattributeset(attrset); 3164 return rc; 3165 } 3166 3167 void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset) 3168 { 3169 if (attrset == NULL) { 3170 return; 3171 } 3172 3173 cil_list_destroy(&attrset->str_expr, CIL_TRUE); 3174 cil_list_destroy(&attrset->datum_expr, CIL_FALSE); 3175 3176 free(attrset); 3177 } 3178 3179 int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3180 { 3181 enum cil_syntax syntax[] = { 3182 CIL_SYN_STRING, 3183 CIL_SYN_STRING | CIL_SYN_LIST, 3184 CIL_SYN_STRING, 3185 CIL_SYN_END 3186 }; 3187 char *expand_str; 3188 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3189 struct cil_expandtypeattribute *expandattr = NULL; 3190 int rc = SEPOL_ERR; 3191 3192 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3193 goto exit; 3194 } 3195 3196 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3197 if (rc != SEPOL_OK) { 3198 goto exit; 3199 } 3200 3201 cil_expandtypeattribute_init(&expandattr); 3202 3203 if (parse_current->next->cl_head == NULL) { 3204 cil_list_init(&expandattr->attr_strs, CIL_TYPE); 3205 cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data); 3206 } else { 3207 rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs); 3208 if (rc != SEPOL_OK) { 3209 goto exit; 3210 } 3211 } 3212 3213 expand_str = parse_current->next->next->data; 3214 3215 if (expand_str == CIL_KEY_CONDTRUE) { 3216 expandattr->expand = CIL_TRUE; 3217 } else if (expand_str == CIL_KEY_CONDFALSE) { 3218 expandattr->expand = CIL_FALSE; 3219 } else { 3220 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); 3221 goto exit; 3222 } 3223 3224 ast_node->data = expandattr; 3225 ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE; 3226 3227 return SEPOL_OK; 3228 3229 exit: 3230 cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement"); 3231 cil_destroy_expandtypeattribute(expandattr); 3232 return rc; 3233 } 3234 3235 void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr) 3236 { 3237 if (expandattr == NULL) { 3238 return; 3239 } 3240 3241 cil_list_destroy(&expandattr->attr_strs, CIL_TRUE); 3242 3243 cil_list_destroy(&expandattr->attr_datums, CIL_FALSE); 3244 3245 free(expandattr); 3246 } 3247 3248 int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3249 { 3250 enum cil_syntax syntax[] = { 3251 CIL_SYN_STRING, 3252 CIL_SYN_STRING, 3253 CIL_SYN_END 3254 }; 3255 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3256 struct cil_typepermissive *typeperm = NULL; 3257 int rc = SEPOL_ERR; 3258 3259 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3260 goto exit; 3261 } 3262 3263 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3264 if (rc != SEPOL_OK) { 3265 goto exit; 3266 } 3267 3268 cil_typepermissive_init(&typeperm); 3269 3270 typeperm->type_str = parse_current->next->data; 3271 3272 ast_node->data = typeperm; 3273 ast_node->flavor = CIL_TYPEPERMISSIVE; 3274 3275 return SEPOL_OK; 3276 3277 exit: 3278 cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration"); 3279 cil_destroy_typepermissive(typeperm); 3280 return rc; 3281 } 3282 3283 void cil_destroy_typepermissive(struct cil_typepermissive *typeperm) 3284 { 3285 if (typeperm == NULL) { 3286 return; 3287 } 3288 3289 free(typeperm); 3290 } 3291 3292 int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3293 { 3294 int rc = SEPOL_ERR; 3295 enum cil_syntax syntax[] = { 3296 CIL_SYN_STRING, 3297 CIL_SYN_STRING, 3298 CIL_SYN_STRING, 3299 CIL_SYN_STRING, 3300 CIL_SYN_STRING, 3301 CIL_SYN_STRING | CIL_SYN_END, 3302 CIL_SYN_END 3303 }; 3304 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3305 char *s1, *s2, *s3, *s4, *s5; 3306 3307 if (db == NULL || parse_current == NULL || ast_node == NULL ) { 3308 goto exit; 3309 } 3310 3311 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3312 if (rc != SEPOL_OK) { 3313 goto exit; 3314 } 3315 3316 s1 = parse_current->next->data; 3317 s2 = parse_current->next->next->data; 3318 s3 = parse_current->next->next->next->data; 3319 s4 = parse_current->next->next->next->next->data; 3320 s5 = NULL; 3321 3322 if (parse_current->next->next->next->next->next) { 3323 if (s4 == CIL_KEY_STAR) { 3324 s4 = parse_current->next->next->next->next->next->data; 3325 } else { 3326 s5 = parse_current->next->next->next->next->next->data; 3327 } 3328 } 3329 3330 if (s5) { 3331 struct cil_nametypetransition *nametypetrans = NULL; 3332 3333 cil_nametypetransition_init(&nametypetrans); 3334 3335 nametypetrans->src_str = s1; 3336 nametypetrans->tgt_str = s2; 3337 nametypetrans->obj_str = s3; 3338 nametypetrans->result_str = s5; 3339 nametypetrans->name_str = s4; 3340 3341 ast_node->data = nametypetrans; 3342 ast_node->flavor = CIL_NAMETYPETRANSITION; 3343 } else { 3344 struct cil_type_rule *rule = NULL; 3345 3346 cil_type_rule_init(&rule); 3347 3348 rule->rule_kind = CIL_TYPE_TRANSITION; 3349 rule->src_str = s1; 3350 rule->tgt_str = s2; 3351 rule->obj_str = s3; 3352 rule->result_str = s4; 3353 3354 ast_node->data = rule; 3355 ast_node->flavor = CIL_TYPE_RULE; 3356 } 3357 3358 return SEPOL_OK; 3359 3360 exit: 3361 cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration"); 3362 return rc; 3363 } 3364 3365 void cil_destroy_name(struct cil_name *name) 3366 { 3367 if (name == NULL) { 3368 return; 3369 } 3370 3371 cil_symtab_datum_destroy(&name->datum); 3372 free(name); 3373 } 3374 3375 void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans) 3376 { 3377 if (nametypetrans == NULL) { 3378 return; 3379 } 3380 3381 free(nametypetrans); 3382 } 3383 3384 int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3385 { 3386 enum cil_syntax syntax[] = { 3387 CIL_SYN_STRING, 3388 CIL_SYN_STRING, 3389 CIL_SYN_STRING, 3390 CIL_SYN_STRING, 3391 CIL_SYN_STRING | CIL_SYN_LIST, 3392 CIL_SYN_END 3393 }; 3394 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3395 struct cil_rangetransition *rangetrans = NULL; 3396 int rc = SEPOL_ERR; 3397 3398 if (db == NULL || parse_current == NULL || ast_node == NULL ) { 3399 goto exit; 3400 } 3401 3402 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3403 if (rc != SEPOL_OK) { 3404 goto exit; 3405 } 3406 3407 cil_rangetransition_init(&rangetrans); 3408 3409 rangetrans->src_str = parse_current->next->data; 3410 rangetrans->exec_str = parse_current->next->next->data; 3411 rangetrans->obj_str = parse_current->next->next->next->data; 3412 3413 rangetrans->range_str = NULL; 3414 3415 if (parse_current->next->next->next->next->cl_head == NULL) { 3416 rangetrans->range_str = parse_current->next->next->next->next->data; 3417 } else { 3418 cil_levelrange_init(&rangetrans->range); 3419 3420 rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range); 3421 if (rc != SEPOL_OK) { 3422 goto exit; 3423 } 3424 } 3425 3426 ast_node->data = rangetrans; 3427 ast_node->flavor = CIL_RANGETRANSITION; 3428 3429 return SEPOL_OK; 3430 3431 exit: 3432 cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration"); 3433 cil_destroy_rangetransition(rangetrans); 3434 return rc; 3435 } 3436 3437 void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans) 3438 { 3439 if (rangetrans == NULL) { 3440 return; 3441 } 3442 3443 if (rangetrans->range_str == NULL && rangetrans->range != NULL) { 3444 cil_destroy_levelrange(rangetrans->range); 3445 } 3446 3447 free(rangetrans); 3448 } 3449 3450 int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3451 { 3452 enum cil_syntax syntax[] = { 3453 CIL_SYN_STRING, 3454 CIL_SYN_STRING, 3455 CIL_SYN_END 3456 }; 3457 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3458 char *key = NULL; 3459 struct cil_sens *sens = NULL; 3460 int rc = SEPOL_ERR; 3461 3462 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3463 goto exit; 3464 } 3465 3466 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3467 if (rc != SEPOL_OK) { 3468 goto exit; 3469 } 3470 3471 cil_sens_init(&sens); 3472 3473 key = parse_current->next->data; 3474 3475 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS); 3476 if (rc != SEPOL_OK) { 3477 goto exit; 3478 } 3479 3480 return SEPOL_OK; 3481 3482 exit: 3483 cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration"); 3484 cil_destroy_sensitivity(sens); 3485 cil_clear_node(ast_node); 3486 return rc; 3487 } 3488 3489 void cil_destroy_sensitivity(struct cil_sens *sens) 3490 { 3491 if (sens == NULL) { 3492 return; 3493 } 3494 3495 cil_symtab_datum_destroy(&sens->datum); 3496 3497 cil_list_destroy(&sens->cats_list, CIL_FALSE); 3498 3499 free(sens); 3500 } 3501 3502 int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3503 { 3504 enum cil_syntax syntax[] = { 3505 CIL_SYN_STRING, 3506 CIL_SYN_STRING, 3507 CIL_SYN_END 3508 }; 3509 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3510 char *key = NULL; 3511 struct cil_cat *cat = NULL; 3512 int rc = SEPOL_ERR; 3513 3514 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3515 goto exit; 3516 } 3517 3518 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3519 if (rc != SEPOL_OK) { 3520 goto exit; 3521 } 3522 3523 cil_cat_init(&cat); 3524 3525 key = parse_current->next->data; 3526 3527 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT); 3528 if (rc != SEPOL_OK) { 3529 goto exit; 3530 } 3531 3532 return SEPOL_OK; 3533 3534 exit: 3535 cil_tree_log(parse_current, CIL_ERR, "Bad category declaration"); 3536 cil_destroy_category(cat); 3537 cil_clear_node(ast_node); 3538 return rc; 3539 } 3540 3541 void cil_destroy_category(struct cil_cat *cat) 3542 { 3543 if (cat == NULL) { 3544 return; 3545 } 3546 3547 cil_symtab_datum_destroy(&cat->datum); 3548 free(cat); 3549 } 3550 3551 int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3552 { 3553 enum cil_syntax syntax[] = { 3554 CIL_SYN_STRING, 3555 CIL_SYN_STRING, 3556 CIL_SYN_LIST, 3557 CIL_SYN_END 3558 }; 3559 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3560 char *key = NULL; 3561 struct cil_catset *catset = NULL; 3562 int rc = SEPOL_ERR; 3563 3564 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3565 goto exit; 3566 } 3567 3568 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3569 if (rc != SEPOL_OK) { 3570 goto exit; 3571 } 3572 3573 cil_catset_init(&catset); 3574 3575 key = parse_current->next->data; 3576 3577 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET); 3578 if (rc != SEPOL_OK) { 3579 goto exit; 3580 } 3581 3582 rc = cil_fill_cats(parse_current->next->next, &catset->cats); 3583 if (rc != SEPOL_OK) { 3584 goto exit; 3585 } 3586 3587 return SEPOL_OK; 3588 3589 exit: 3590 cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration"); 3591 cil_destroy_catset(catset); 3592 cil_clear_node(ast_node); 3593 return rc; 3594 } 3595 3596 void cil_destroy_catset(struct cil_catset *catset) 3597 { 3598 if (catset == NULL) { 3599 return; 3600 } 3601 3602 cil_symtab_datum_destroy(&catset->datum); 3603 3604 cil_destroy_cats(catset->cats); 3605 3606 free(catset); 3607 } 3608 3609 int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3610 { 3611 enum cil_syntax syntax[] = { 3612 CIL_SYN_STRING, 3613 CIL_SYN_LIST, 3614 CIL_SYN_END 3615 }; 3616 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3617 struct cil_catorder *catorder = NULL; 3618 struct cil_list_item *curr = NULL; 3619 int rc = SEPOL_ERR; 3620 3621 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3622 goto exit; 3623 } 3624 3625 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3626 if (rc != SEPOL_OK) { 3627 goto exit; 3628 } 3629 3630 cil_catorder_init(&catorder); 3631 3632 rc = cil_fill_list(parse_current->next->cl_head, CIL_CATORDER, &catorder->cat_list_str); 3633 if (rc != SEPOL_OK) { 3634 goto exit; 3635 } 3636 3637 cil_list_for_each(curr, catorder->cat_list_str) { 3638 if (curr->data == CIL_KEY_UNORDERED) { 3639 cil_log(CIL_ERR, "Category order cannot be unordered.\n"); 3640 rc = SEPOL_ERR; 3641 goto exit; 3642 } 3643 } 3644 3645 ast_node->data = catorder; 3646 ast_node->flavor = CIL_CATORDER; 3647 3648 return SEPOL_OK; 3649 3650 exit: 3651 cil_tree_log(parse_current, CIL_ERR, "Bad categoryorder declaration"); 3652 cil_destroy_catorder(catorder); 3653 return rc; 3654 } 3655 3656 void cil_destroy_catorder(struct cil_catorder *catorder) 3657 { 3658 if (catorder == NULL) { 3659 return; 3660 } 3661 3662 if (catorder->cat_list_str != NULL) { 3663 cil_list_destroy(&catorder->cat_list_str, 1); 3664 } 3665 3666 free(catorder); 3667 } 3668 3669 int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3670 { 3671 enum cil_syntax syntax[] = { 3672 CIL_SYN_STRING, 3673 CIL_SYN_LIST, 3674 CIL_SYN_END 3675 }; 3676 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3677 struct cil_sensorder *sensorder = NULL; 3678 struct cil_list_item *curr = NULL; 3679 int rc = SEPOL_ERR; 3680 3681 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3682 goto exit; 3683 } 3684 3685 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3686 if (rc != SEPOL_OK) { 3687 goto exit; 3688 } 3689 3690 cil_sensorder_init(&sensorder); 3691 3692 rc = cil_fill_list(parse_current->next->cl_head, CIL_SENSITIVITYORDER, &sensorder->sens_list_str); 3693 if (rc != SEPOL_OK) { 3694 goto exit; 3695 } 3696 3697 cil_list_for_each(curr, sensorder->sens_list_str) { 3698 if (curr->data == CIL_KEY_UNORDERED) { 3699 cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n"); 3700 rc = SEPOL_ERR; 3701 goto exit; 3702 } 3703 } 3704 3705 ast_node->data = sensorder; 3706 ast_node->flavor = CIL_SENSITIVITYORDER; 3707 3708 return SEPOL_OK; 3709 3710 exit: 3711 cil_tree_log(parse_current, CIL_ERR, "Bad sensitivityorder declaration"); 3712 cil_destroy_sensitivityorder(sensorder); 3713 return rc; 3714 } 3715 3716 void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder) 3717 { 3718 if (sensorder == NULL) { 3719 return; 3720 } 3721 3722 if (sensorder->sens_list_str != NULL) { 3723 cil_list_destroy(&sensorder->sens_list_str, CIL_TRUE); 3724 } 3725 3726 free(sensorder); 3727 } 3728 3729 int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3730 { 3731 enum cil_syntax syntax[] = { 3732 CIL_SYN_STRING, 3733 CIL_SYN_STRING, 3734 CIL_SYN_STRING | CIL_SYN_LIST, 3735 CIL_SYN_END 3736 }; 3737 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3738 struct cil_senscat *senscat = NULL; 3739 int rc = SEPOL_ERR; 3740 3741 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3742 goto exit; 3743 } 3744 3745 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3746 if (rc != SEPOL_OK) { 3747 goto exit; 3748 } 3749 3750 cil_senscat_init(&senscat); 3751 3752 senscat->sens_str = parse_current->next->data; 3753 3754 rc = cil_fill_cats(parse_current->next->next, &senscat->cats); 3755 if (rc != SEPOL_OK) { 3756 goto exit; 3757 } 3758 3759 ast_node->data = senscat; 3760 ast_node->flavor = CIL_SENSCAT; 3761 3762 return SEPOL_OK; 3763 3764 exit: 3765 cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration"); 3766 cil_destroy_senscat(senscat); 3767 return rc; 3768 } 3769 3770 void cil_destroy_senscat(struct cil_senscat *senscat) 3771 { 3772 if (senscat == NULL) { 3773 return; 3774 } 3775 3776 cil_destroy_cats(senscat->cats); 3777 3778 free(senscat); 3779 } 3780 3781 int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3782 { 3783 enum cil_syntax syntax[] = { 3784 CIL_SYN_STRING, 3785 CIL_SYN_STRING, 3786 CIL_SYN_LIST, 3787 CIL_SYN_END 3788 }; 3789 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3790 char *key = NULL; 3791 struct cil_level *level = NULL; 3792 int rc = SEPOL_ERR; 3793 3794 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3795 goto exit; 3796 } 3797 3798 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3799 if (rc != SEPOL_OK) { 3800 goto exit; 3801 } 3802 3803 cil_level_init(&level); 3804 3805 key = parse_current->next->data; 3806 3807 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL); 3808 if (rc != SEPOL_OK) { 3809 goto exit; 3810 } 3811 3812 rc = cil_fill_level(parse_current->next->next->cl_head, level); 3813 if (rc != SEPOL_OK) { 3814 goto exit; 3815 } 3816 3817 return SEPOL_OK; 3818 3819 exit: 3820 cil_tree_log(parse_current, CIL_ERR, "Bad level declaration"); 3821 cil_destroy_level(level); 3822 cil_clear_node(ast_node); 3823 return rc; 3824 } 3825 3826 void cil_destroy_level(struct cil_level *level) 3827 { 3828 if (level == NULL) { 3829 return; 3830 } 3831 3832 cil_symtab_datum_destroy(&level->datum); 3833 3834 cil_destroy_cats(level->cats); 3835 3836 free(level); 3837 } 3838 3839 /* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */ 3840 int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange) 3841 { 3842 enum cil_syntax syntax[] = { 3843 CIL_SYN_STRING | CIL_SYN_LIST, 3844 CIL_SYN_STRING | CIL_SYN_LIST, 3845 CIL_SYN_END 3846 }; 3847 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3848 int rc = SEPOL_ERR; 3849 3850 if (low == NULL || lvlrange == NULL) { 3851 goto exit; 3852 } 3853 3854 rc = __cil_verify_syntax(low, syntax, syntax_len); 3855 if (rc != SEPOL_OK) { 3856 3857 goto exit; 3858 } 3859 3860 if (low->cl_head == NULL) { 3861 lvlrange->low_str = low->data; 3862 } else { 3863 cil_level_init(&lvlrange->low); 3864 rc = cil_fill_level(low->cl_head, lvlrange->low); 3865 if (rc != SEPOL_OK) { 3866 goto exit; 3867 } 3868 } 3869 3870 if (low->next->cl_head == NULL) { 3871 lvlrange->high_str = low->next->data; 3872 } else { 3873 cil_level_init(&lvlrange->high); 3874 rc = cil_fill_level(low->next->cl_head, lvlrange->high); 3875 if (rc != SEPOL_OK) { 3876 goto exit; 3877 } 3878 } 3879 3880 return SEPOL_OK; 3881 3882 exit: 3883 cil_log(CIL_ERR, "Bad levelrange\n"); 3884 return rc; 3885 } 3886 3887 int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 3888 { 3889 enum cil_syntax syntax[] = { 3890 CIL_SYN_STRING, 3891 CIL_SYN_STRING, 3892 CIL_SYN_LIST, 3893 CIL_SYN_END 3894 }; 3895 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3896 char *key = NULL; 3897 struct cil_levelrange *lvlrange = NULL; 3898 int rc = SEPOL_ERR; 3899 3900 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3901 goto exit; 3902 } 3903 3904 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3905 if (rc != SEPOL_OK) { 3906 goto exit; 3907 } 3908 3909 cil_levelrange_init(&lvlrange); 3910 3911 key = parse_current->next->data; 3912 3913 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE); 3914 if (rc != SEPOL_OK) { 3915 goto exit; 3916 } 3917 3918 rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange); 3919 if (rc != SEPOL_OK) { 3920 goto exit; 3921 } 3922 3923 return SEPOL_OK; 3924 3925 exit: 3926 cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration"); 3927 cil_destroy_levelrange(lvlrange); 3928 cil_clear_node(ast_node); 3929 return rc; 3930 } 3931 3932 void cil_destroy_levelrange(struct cil_levelrange *lvlrange) 3933 { 3934 if (lvlrange == NULL) { 3935 return; 3936 } 3937 3938 cil_symtab_datum_destroy(&lvlrange->datum); 3939 3940 if (lvlrange->low_str == NULL) { 3941 cil_destroy_level(lvlrange->low); 3942 } 3943 3944 if (lvlrange->high_str == NULL) { 3945 cil_destroy_level(lvlrange->high); 3946 } 3947 3948 free(lvlrange); 3949 } 3950 3951 int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) 3952 { 3953 enum cil_syntax syntax[] = { 3954 CIL_SYN_STRING, 3955 CIL_SYN_STRING | CIL_SYN_LIST, 3956 CIL_SYN_LIST, 3957 CIL_SYN_END 3958 }; 3959 int syntax_len = sizeof(syntax)/sizeof(*syntax); 3960 struct cil_constrain *cons = NULL; 3961 int rc = SEPOL_ERR; 3962 3963 if (db == NULL || parse_current == NULL || ast_node == NULL) { 3964 goto exit; 3965 } 3966 3967 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 3968 if (rc != SEPOL_OK) { 3969 goto exit; 3970 } 3971 3972 cil_constrain_init(&cons); 3973 3974 rc = cil_fill_classperms_list(parse_current->next, &cons->classperms); 3975 if (rc != SEPOL_OK) { 3976 goto exit; 3977 } 3978 3979 rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr); 3980 if (rc != SEPOL_OK) { 3981 goto exit; 3982 } 3983 3984 ast_node->data = cons; 3985 ast_node->flavor = flavor; 3986 3987 return SEPOL_OK; 3988 3989 exit: 3990 cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration"); 3991 cil_destroy_constrain(cons); 3992 return rc; 3993 } 3994 3995 void cil_destroy_constrain(struct cil_constrain *cons) 3996 { 3997 if (cons == NULL) { 3998 return; 3999 } 4000 4001 cil_destroy_classperms_list(&cons->classperms); 4002 cil_list_destroy(&cons->str_expr, CIL_TRUE); 4003 cil_list_destroy(&cons->datum_expr, CIL_FALSE); 4004 4005 free(cons); 4006 } 4007 4008 int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) 4009 { 4010 enum cil_syntax syntax[] = { 4011 CIL_SYN_STRING, 4012 CIL_SYN_STRING, 4013 CIL_SYN_LIST, 4014 CIL_SYN_END 4015 }; 4016 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4017 struct cil_validatetrans *validtrans = NULL; 4018 int rc = SEPOL_ERR; 4019 4020 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4021 goto exit; 4022 } 4023 4024 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4025 if (rc != SEPOL_OK) { 4026 goto exit; 4027 } 4028 4029 cil_validatetrans_init(&validtrans); 4030 4031 validtrans->class_str = parse_current->next->data; 4032 4033 rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr); 4034 if (rc != SEPOL_OK) { 4035 goto exit; 4036 } 4037 4038 ast_node->data = validtrans; 4039 ast_node->flavor = flavor; 4040 4041 return SEPOL_OK; 4042 4043 exit: 4044 cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration"); 4045 cil_destroy_validatetrans(validtrans); 4046 return rc; 4047 4048 4049 } 4050 4051 void cil_destroy_validatetrans(struct cil_validatetrans *validtrans) 4052 { 4053 if (validtrans == NULL) { 4054 return; 4055 } 4056 4057 cil_list_destroy(&validtrans->str_expr, CIL_TRUE); 4058 cil_list_destroy(&validtrans->datum_expr, CIL_FALSE); 4059 4060 free(validtrans); 4061 } 4062 4063 /* Fills in context starting from user */ 4064 int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context) 4065 { 4066 enum cil_syntax syntax[] = { 4067 CIL_SYN_STRING, 4068 CIL_SYN_STRING, 4069 CIL_SYN_STRING, 4070 CIL_SYN_STRING | CIL_SYN_LIST, 4071 CIL_SYN_END 4072 }; 4073 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4074 int rc = SEPOL_ERR; 4075 4076 if (user_node == NULL || context == NULL) { 4077 goto exit; 4078 } 4079 4080 rc = __cil_verify_syntax(user_node, syntax, syntax_len); 4081 if (rc != SEPOL_OK) { 4082 goto exit; 4083 } 4084 4085 context->user_str = user_node->data; 4086 context->role_str = user_node->next->data; 4087 context->type_str = user_node->next->next->data; 4088 4089 context->range_str = NULL; 4090 4091 if (user_node->next->next->next->cl_head == NULL) { 4092 context->range_str = user_node->next->next->next->data; 4093 } else { 4094 cil_levelrange_init(&context->range); 4095 4096 rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range); 4097 if (rc != SEPOL_OK) { 4098 goto exit; 4099 } 4100 } 4101 4102 return SEPOL_OK; 4103 4104 exit: 4105 cil_log(CIL_ERR, "Bad context\n"); 4106 return rc; 4107 } 4108 4109 int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4110 { 4111 enum cil_syntax syntax[] = { 4112 CIL_SYN_STRING, 4113 CIL_SYN_STRING, 4114 CIL_SYN_LIST, 4115 CIL_SYN_END 4116 }; 4117 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4118 char *key = NULL; 4119 struct cil_context *context = NULL; 4120 int rc = SEPOL_ERR; 4121 4122 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4123 goto exit; 4124 } 4125 4126 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4127 if (rc != SEPOL_OK) { 4128 goto exit; 4129 } 4130 4131 cil_context_init(&context); 4132 4133 key = parse_current->next->data; 4134 4135 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT); 4136 if (rc != SEPOL_OK) { 4137 goto exit; 4138 } 4139 4140 rc = cil_fill_context(parse_current->next->next->cl_head, context); 4141 if (rc != SEPOL_OK) { 4142 goto exit; 4143 } 4144 4145 return SEPOL_OK; 4146 4147 exit: 4148 cil_tree_log(parse_current, CIL_ERR, "Bad context declaration"); 4149 cil_destroy_context(context); 4150 cil_clear_node(ast_node); 4151 return SEPOL_ERR; 4152 } 4153 4154 void cil_destroy_context(struct cil_context *context) 4155 { 4156 if (context == NULL) { 4157 return; 4158 } 4159 4160 cil_symtab_datum_destroy(&context->datum);; 4161 4162 if (context->range_str == NULL && context->range != NULL) { 4163 cil_destroy_levelrange(context->range); 4164 } 4165 4166 free(context); 4167 } 4168 4169 int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4170 { 4171 enum cil_syntax syntax[] = { 4172 CIL_SYN_STRING, 4173 CIL_SYN_STRING, 4174 CIL_SYN_STRING, 4175 CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, 4176 CIL_SYN_END 4177 }; 4178 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4179 int rc = SEPOL_ERR; 4180 struct cil_filecon *filecon = NULL; 4181 char *type = NULL; 4182 4183 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4184 goto exit; 4185 } 4186 4187 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4188 if (rc != SEPOL_OK) { 4189 goto exit; 4190 } 4191 4192 type = parse_current->next->next->data; 4193 cil_filecon_init(&filecon); 4194 4195 filecon->path_str = parse_current->next->data; 4196 4197 if (type == CIL_KEY_FILE) { 4198 filecon->type = CIL_FILECON_FILE; 4199 } else if (type == CIL_KEY_DIR) { 4200 filecon->type = CIL_FILECON_DIR; 4201 } else if (type == CIL_KEY_CHAR) { 4202 filecon->type = CIL_FILECON_CHAR; 4203 } else if (type == CIL_KEY_BLOCK) { 4204 filecon->type = CIL_FILECON_BLOCK; 4205 } else if (type == CIL_KEY_SOCKET) { 4206 filecon->type = CIL_FILECON_SOCKET; 4207 } else if (type == CIL_KEY_PIPE) { 4208 filecon->type = CIL_FILECON_PIPE; 4209 } else if (type == CIL_KEY_SYMLINK) { 4210 filecon->type = CIL_FILECON_SYMLINK; 4211 } else if (type == CIL_KEY_ANY) { 4212 filecon->type = CIL_FILECON_ANY; 4213 } else { 4214 cil_log(CIL_ERR, "Invalid file type\n"); 4215 rc = SEPOL_ERR; 4216 goto exit; 4217 } 4218 4219 if (parse_current->next->next->next->cl_head == NULL) { 4220 filecon->context_str = parse_current->next->next->next->data; 4221 } else { 4222 if (parse_current->next->next->next->cl_head->next == NULL) { 4223 filecon->context = NULL; 4224 } else { 4225 cil_context_init(&filecon->context); 4226 4227 rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context); 4228 if (rc != SEPOL_OK) { 4229 goto exit; 4230 } 4231 } 4232 } 4233 4234 ast_node->data = filecon; 4235 ast_node->flavor = CIL_FILECON; 4236 4237 return SEPOL_OK; 4238 4239 exit: 4240 cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration"); 4241 cil_destroy_filecon(filecon); 4242 return rc; 4243 } 4244 4245 //TODO: Should we be checking if the pointer is NULL when passed in? 4246 void cil_destroy_filecon(struct cil_filecon *filecon) 4247 { 4248 if (filecon == NULL) { 4249 return; 4250 } 4251 4252 if (filecon->context_str == NULL && filecon->context != NULL) { 4253 cil_destroy_context(filecon->context); 4254 } 4255 4256 free(filecon); 4257 } 4258 4259 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4260 { 4261 enum cil_syntax syntax[] = { 4262 CIL_SYN_STRING, 4263 CIL_SYN_STRING, 4264 CIL_SYN_STRING | CIL_SYN_LIST, 4265 CIL_SYN_STRING | CIL_SYN_LIST, 4266 CIL_SYN_END 4267 }; 4268 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4269 int rc = SEPOL_ERR; 4270 struct cil_portcon *portcon = NULL; 4271 char *proto; 4272 4273 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4274 goto exit; 4275 } 4276 4277 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4278 if (rc != SEPOL_OK) { 4279 goto exit; 4280 } 4281 4282 cil_portcon_init(&portcon); 4283 4284 proto = parse_current->next->data; 4285 if (proto == CIL_KEY_UDP) { 4286 portcon->proto = CIL_PROTOCOL_UDP; 4287 } else if (proto == CIL_KEY_TCP) { 4288 portcon->proto = CIL_PROTOCOL_TCP; 4289 } else if (proto == CIL_KEY_DCCP) { 4290 portcon->proto = CIL_PROTOCOL_DCCP; 4291 } else { 4292 cil_log(CIL_ERR, "Invalid protocol\n"); 4293 rc = SEPOL_ERR; 4294 goto exit; 4295 } 4296 4297 if (parse_current->next->next->cl_head != NULL) { 4298 if (parse_current->next->next->cl_head->next != NULL 4299 && parse_current->next->next->cl_head->next->next == NULL) { 4300 rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10); 4301 if (rc != SEPOL_OK) { 4302 cil_log(CIL_ERR, "Improper port specified\n"); 4303 goto exit; 4304 } 4305 rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10); 4306 if (rc != SEPOL_OK) { 4307 cil_log(CIL_ERR, "Improper port specified\n"); 4308 goto exit; 4309 } 4310 } else { 4311 cil_log(CIL_ERR, "Improper port range specified\n"); 4312 rc = SEPOL_ERR; 4313 goto exit; 4314 } 4315 } else { 4316 rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10); 4317 if (rc != SEPOL_OK) { 4318 cil_log(CIL_ERR, "Improper port specified\n"); 4319 goto exit; 4320 } 4321 portcon->port_high = portcon->port_low; 4322 } 4323 4324 if (parse_current->next->next->next->cl_head == NULL ) { 4325 portcon->context_str = parse_current->next->next->next->data; 4326 } else { 4327 cil_context_init(&portcon->context); 4328 4329 rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context); 4330 if (rc != SEPOL_OK) { 4331 goto exit; 4332 } 4333 } 4334 4335 ast_node->data = portcon; 4336 ast_node->flavor = CIL_PORTCON; 4337 4338 return SEPOL_OK; 4339 4340 exit: 4341 cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration"); 4342 cil_destroy_portcon(portcon); 4343 return rc; 4344 } 4345 4346 void cil_destroy_portcon(struct cil_portcon *portcon) 4347 { 4348 if (portcon == NULL) { 4349 return; 4350 } 4351 4352 if (portcon->context_str == NULL && portcon->context != NULL) { 4353 cil_destroy_context(portcon->context); 4354 } 4355 4356 free(portcon); 4357 } 4358 4359 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4360 { 4361 enum cil_syntax syntax[] = { 4362 CIL_SYN_STRING, 4363 CIL_SYN_STRING | CIL_SYN_LIST, 4364 CIL_SYN_STRING | CIL_SYN_LIST, 4365 CIL_SYN_STRING | CIL_SYN_LIST, 4366 CIL_SYN_END 4367 }; 4368 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4369 int rc = SEPOL_ERR; 4370 struct cil_nodecon *nodecon = NULL; 4371 4372 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4373 goto exit; 4374 } 4375 4376 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4377 if (rc != SEPOL_OK) { 4378 goto exit; 4379 } 4380 4381 cil_nodecon_init(&nodecon); 4382 4383 if (parse_current->next->cl_head == NULL ) { 4384 nodecon->addr_str = parse_current->next->data; 4385 } else { 4386 cil_ipaddr_init(&nodecon->addr); 4387 4388 rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr); 4389 if (rc != SEPOL_OK) { 4390 goto exit; 4391 } 4392 } 4393 4394 if (parse_current->next->next->cl_head == NULL ) { 4395 nodecon->mask_str = parse_current->next->next->data; 4396 } else { 4397 cil_ipaddr_init(&nodecon->mask); 4398 4399 rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask); 4400 if (rc != SEPOL_OK) { 4401 goto exit; 4402 } 4403 } 4404 4405 if (parse_current->next->next->next->cl_head == NULL ) { 4406 nodecon->context_str = parse_current->next->next->next->data; 4407 } else { 4408 cil_context_init(&nodecon->context); 4409 4410 rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context); 4411 if (rc != SEPOL_OK) { 4412 goto exit; 4413 } 4414 } 4415 4416 ast_node->data = nodecon; 4417 ast_node->flavor = CIL_NODECON; 4418 4419 return SEPOL_OK; 4420 4421 exit: 4422 cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration"); 4423 cil_destroy_nodecon(nodecon); 4424 return rc; 4425 } 4426 4427 void cil_destroy_nodecon(struct cil_nodecon *nodecon) 4428 { 4429 if (nodecon == NULL) { 4430 return; 4431 } 4432 4433 if (nodecon->addr_str == NULL && nodecon->addr != NULL) { 4434 cil_destroy_ipaddr(nodecon->addr); 4435 } 4436 4437 if (nodecon->mask_str == NULL && nodecon->mask != NULL) { 4438 cil_destroy_ipaddr(nodecon->mask); 4439 } 4440 4441 if (nodecon->context_str == NULL && nodecon->context != NULL) { 4442 cil_destroy_context(nodecon->context); 4443 } 4444 4445 free(nodecon); 4446 } 4447 4448 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4449 { 4450 enum cil_syntax syntax[] = { 4451 CIL_SYN_STRING, 4452 CIL_SYN_STRING, 4453 CIL_SYN_STRING, 4454 CIL_SYN_STRING | CIL_SYN_LIST, 4455 CIL_SYN_END 4456 }; 4457 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4458 int rc = SEPOL_ERR; 4459 struct cil_genfscon *genfscon = NULL; 4460 4461 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4462 goto exit; 4463 } 4464 4465 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4466 if (rc != SEPOL_OK) { 4467 goto exit; 4468 } 4469 4470 cil_genfscon_init(&genfscon); 4471 4472 genfscon->fs_str = parse_current->next->data; 4473 genfscon->path_str = parse_current->next->next->data; 4474 4475 if (parse_current->next->next->next->cl_head == NULL ) { 4476 genfscon->context_str = parse_current->next->next->next->data; 4477 } else { 4478 cil_context_init(&genfscon->context); 4479 4480 rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context); 4481 if (rc != SEPOL_OK) { 4482 goto exit; 4483 } 4484 } 4485 4486 ast_node->data = genfscon; 4487 ast_node->flavor = CIL_GENFSCON; 4488 4489 return SEPOL_OK; 4490 4491 exit: 4492 cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration"); 4493 cil_destroy_genfscon(genfscon); 4494 return SEPOL_ERR; 4495 } 4496 4497 void cil_destroy_genfscon(struct cil_genfscon *genfscon) 4498 { 4499 if (genfscon == NULL) { 4500 return; 4501 } 4502 4503 if (genfscon->context_str == NULL && genfscon->context != NULL) { 4504 cil_destroy_context(genfscon->context); 4505 } 4506 4507 free(genfscon); 4508 } 4509 4510 4511 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4512 { 4513 enum cil_syntax syntax[] = { 4514 CIL_SYN_STRING, 4515 CIL_SYN_STRING, 4516 CIL_SYN_STRING | CIL_SYN_LIST, 4517 CIL_SYN_STRING | CIL_SYN_LIST, 4518 CIL_SYN_END 4519 }; 4520 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4521 int rc = SEPOL_ERR; 4522 struct cil_netifcon *netifcon = NULL; 4523 4524 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4525 goto exit; 4526 } 4527 4528 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4529 if (rc != SEPOL_OK) { 4530 goto exit; 4531 } 4532 4533 cil_netifcon_init(&netifcon); 4534 4535 netifcon->interface_str = parse_current->next->data; 4536 4537 if (parse_current->next->next->cl_head == NULL) { 4538 netifcon->if_context_str = parse_current->next->next->data; 4539 } else { 4540 cil_context_init(&netifcon->if_context); 4541 4542 rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context); 4543 if (rc != SEPOL_OK) { 4544 goto exit; 4545 } 4546 } 4547 4548 if (parse_current->next->next->next->cl_head == NULL) { 4549 netifcon->packet_context_str = parse_current->next->next->next->data; 4550 } else { 4551 cil_context_init(&netifcon->packet_context); 4552 4553 rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context); 4554 if (rc != SEPOL_OK) { 4555 goto exit; 4556 } 4557 } 4558 4559 ast_node->data = netifcon; 4560 ast_node->flavor = CIL_NETIFCON; 4561 4562 return SEPOL_OK; 4563 4564 exit: 4565 cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration"); 4566 cil_destroy_netifcon(netifcon); 4567 return SEPOL_ERR; 4568 } 4569 4570 void cil_destroy_netifcon(struct cil_netifcon *netifcon) 4571 { 4572 if (netifcon == NULL) { 4573 return; 4574 } 4575 4576 if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) { 4577 cil_destroy_context(netifcon->if_context); 4578 } 4579 4580 if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) { 4581 cil_destroy_context(netifcon->packet_context); 4582 } 4583 4584 free(netifcon); 4585 } 4586 4587 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4588 { 4589 enum cil_syntax syntax[] = { 4590 CIL_SYN_STRING, 4591 CIL_SYN_STRING, 4592 CIL_SYN_STRING | CIL_SYN_LIST, 4593 CIL_SYN_END 4594 }; 4595 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4596 int rc = SEPOL_ERR; 4597 struct cil_pirqcon *pirqcon = NULL; 4598 4599 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4600 goto exit; 4601 } 4602 4603 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4604 if (rc != SEPOL_OK) { 4605 goto exit; 4606 } 4607 4608 cil_pirqcon_init(&pirqcon); 4609 4610 rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10); 4611 if (rc != SEPOL_OK) { 4612 goto exit; 4613 } 4614 4615 if (parse_current->next->next->cl_head == NULL) { 4616 pirqcon->context_str = parse_current->next->next->data; 4617 } else { 4618 cil_context_init(&pirqcon->context); 4619 4620 rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context); 4621 if (rc != SEPOL_OK) { 4622 goto exit; 4623 } 4624 } 4625 4626 ast_node->data = pirqcon; 4627 ast_node->flavor = CIL_PIRQCON; 4628 4629 return SEPOL_OK; 4630 4631 exit: 4632 cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration"); 4633 cil_destroy_pirqcon(pirqcon); 4634 return rc; 4635 } 4636 4637 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon) 4638 { 4639 if (pirqcon == NULL) { 4640 return; 4641 } 4642 4643 if (pirqcon->context_str == NULL && pirqcon->context != NULL) { 4644 cil_destroy_context(pirqcon->context); 4645 } 4646 4647 free(pirqcon); 4648 } 4649 4650 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4651 { 4652 enum cil_syntax syntax[] = { 4653 CIL_SYN_STRING, 4654 CIL_SYN_STRING | CIL_SYN_LIST, 4655 CIL_SYN_STRING | CIL_SYN_LIST, 4656 CIL_SYN_END 4657 }; 4658 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4659 int rc = SEPOL_ERR; 4660 struct cil_iomemcon *iomemcon = NULL; 4661 4662 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4663 goto exit; 4664 } 4665 4666 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4667 if (rc != SEPOL_OK) { 4668 goto exit; 4669 } 4670 4671 cil_iomemcon_init(&iomemcon); 4672 4673 if (parse_current->next->cl_head != NULL) { 4674 if (parse_current->next->cl_head->next != NULL && 4675 parse_current->next->cl_head->next->next == NULL) { 4676 rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0); 4677 if (rc != SEPOL_OK) { 4678 cil_log(CIL_ERR, "Improper iomem specified\n"); 4679 goto exit; 4680 } 4681 rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0); 4682 if (rc != SEPOL_OK) { 4683 cil_log(CIL_ERR, "Improper iomem specified\n"); 4684 goto exit; 4685 } 4686 } else { 4687 cil_log(CIL_ERR, "Improper iomem range specified\n"); 4688 rc = SEPOL_ERR; 4689 goto exit; 4690 } 4691 } else { 4692 rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0); 4693 if (rc != SEPOL_OK) { 4694 cil_log(CIL_ERR, "Improper iomem specified\n"); 4695 goto exit; 4696 } 4697 iomemcon->iomem_high = iomemcon->iomem_low; 4698 } 4699 4700 if (parse_current->next->next->cl_head == NULL ) { 4701 iomemcon->context_str = parse_current->next->next->data; 4702 } else { 4703 cil_context_init(&iomemcon->context); 4704 4705 rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context); 4706 if (rc != SEPOL_OK) { 4707 goto exit; 4708 } 4709 } 4710 4711 ast_node->data = iomemcon; 4712 ast_node->flavor = CIL_IOMEMCON; 4713 4714 return SEPOL_OK; 4715 4716 exit: 4717 cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration"); 4718 cil_destroy_iomemcon(iomemcon); 4719 return rc; 4720 } 4721 4722 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon) 4723 { 4724 if (iomemcon == NULL) { 4725 return; 4726 } 4727 4728 if (iomemcon->context_str == NULL && iomemcon->context != NULL) { 4729 cil_destroy_context(iomemcon->context); 4730 } 4731 4732 free(iomemcon); 4733 } 4734 4735 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4736 { 4737 enum cil_syntax syntax[] = { 4738 CIL_SYN_STRING, 4739 CIL_SYN_STRING | CIL_SYN_LIST, 4740 CIL_SYN_STRING | CIL_SYN_LIST, 4741 CIL_SYN_END 4742 }; 4743 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4744 int rc = SEPOL_ERR; 4745 struct cil_ioportcon *ioportcon = NULL; 4746 4747 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4748 goto exit; 4749 } 4750 4751 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4752 if (rc != SEPOL_OK) { 4753 goto exit; 4754 } 4755 4756 cil_ioportcon_init(&ioportcon); 4757 4758 if (parse_current->next->cl_head != NULL) { 4759 if (parse_current->next->cl_head->next != NULL && 4760 parse_current->next->cl_head->next->next == NULL) { 4761 rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0); 4762 if (rc != SEPOL_OK) { 4763 cil_log(CIL_ERR, "Improper ioport specified\n"); 4764 goto exit; 4765 } 4766 rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0); 4767 if (rc != SEPOL_OK) { 4768 cil_log(CIL_ERR, "Improper ioport specified\n"); 4769 goto exit; 4770 } 4771 } else { 4772 cil_log(CIL_ERR, "Improper ioport range specified\n"); 4773 rc = SEPOL_ERR; 4774 goto exit; 4775 } 4776 } else { 4777 rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0); 4778 if (rc != SEPOL_OK) { 4779 cil_log(CIL_ERR, "Improper ioport specified\n"); 4780 goto exit; 4781 } 4782 ioportcon->ioport_high = ioportcon->ioport_low; 4783 } 4784 4785 if (parse_current->next->next->cl_head == NULL ) { 4786 ioportcon->context_str = parse_current->next->next->data; 4787 } else { 4788 cil_context_init(&ioportcon->context); 4789 4790 rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context); 4791 if (rc != SEPOL_OK) { 4792 goto exit; 4793 } 4794 } 4795 4796 ast_node->data = ioportcon; 4797 ast_node->flavor = CIL_IOPORTCON; 4798 4799 return SEPOL_OK; 4800 4801 exit: 4802 cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration"); 4803 cil_destroy_ioportcon(ioportcon); 4804 return rc; 4805 } 4806 4807 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon) 4808 { 4809 if (ioportcon == NULL) { 4810 return; 4811 } 4812 4813 if (ioportcon->context_str == NULL && ioportcon->context != NULL) { 4814 cil_destroy_context(ioportcon->context); 4815 } 4816 4817 free(ioportcon); 4818 } 4819 4820 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4821 { 4822 enum cil_syntax syntax[] = { 4823 CIL_SYN_STRING, 4824 CIL_SYN_STRING, 4825 CIL_SYN_STRING | CIL_SYN_LIST, 4826 CIL_SYN_END 4827 }; 4828 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4829 int rc = SEPOL_ERR; 4830 struct cil_pcidevicecon *pcidevicecon = NULL; 4831 4832 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4833 goto exit; 4834 } 4835 4836 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4837 if (rc != SEPOL_OK) { 4838 goto exit; 4839 } 4840 4841 cil_pcidevicecon_init(&pcidevicecon); 4842 4843 rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0); 4844 if (rc != SEPOL_OK) { 4845 goto exit; 4846 } 4847 4848 if (parse_current->next->next->cl_head == NULL) { 4849 pcidevicecon->context_str = parse_current->next->next->data; 4850 } else { 4851 cil_context_init(&pcidevicecon->context); 4852 4853 rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context); 4854 if (rc != SEPOL_OK) { 4855 goto exit; 4856 } 4857 } 4858 4859 ast_node->data = pcidevicecon; 4860 ast_node->flavor = CIL_PCIDEVICECON; 4861 4862 return SEPOL_OK; 4863 4864 exit: 4865 cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration"); 4866 cil_destroy_pcidevicecon(pcidevicecon); 4867 return rc; 4868 } 4869 4870 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) 4871 { 4872 if (pcidevicecon == NULL) { 4873 return; 4874 } 4875 4876 if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) { 4877 cil_destroy_context(pcidevicecon->context); 4878 } 4879 4880 free(pcidevicecon); 4881 } 4882 4883 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4884 { 4885 enum cil_syntax syntax[] = { 4886 CIL_SYN_STRING, 4887 CIL_SYN_STRING, 4888 CIL_SYN_STRING | CIL_SYN_LIST, 4889 CIL_SYN_END 4890 }; 4891 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4892 int rc = SEPOL_ERR; 4893 struct cil_devicetreecon *devicetreecon = NULL; 4894 4895 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4896 goto exit; 4897 } 4898 4899 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4900 if (rc != SEPOL_OK) { 4901 goto exit; 4902 } 4903 4904 cil_devicetreecon_init(&devicetreecon); 4905 4906 devicetreecon->path = parse_current->next->data; 4907 4908 if (parse_current->next->next->cl_head == NULL) { 4909 devicetreecon->context_str = parse_current->next->next->data; 4910 } else { 4911 cil_context_init(&devicetreecon->context); 4912 4913 rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context); 4914 if (rc != SEPOL_OK) { 4915 goto exit; 4916 } 4917 } 4918 4919 ast_node->data = devicetreecon; 4920 ast_node->flavor = CIL_DEVICETREECON; 4921 4922 return SEPOL_OK; 4923 4924 exit: 4925 cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration"); 4926 cil_destroy_devicetreecon(devicetreecon); 4927 return rc; 4928 } 4929 4930 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon) 4931 { 4932 if (devicetreecon == NULL) { 4933 return; 4934 } 4935 4936 if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) { 4937 cil_destroy_context(devicetreecon->context); 4938 } 4939 4940 free(devicetreecon); 4941 } 4942 4943 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 4944 { 4945 enum cil_syntax syntax[] = { 4946 CIL_SYN_STRING, 4947 CIL_SYN_STRING, 4948 CIL_SYN_STRING, 4949 CIL_SYN_STRING | CIL_SYN_LIST, 4950 CIL_SYN_END 4951 }; 4952 int syntax_len = sizeof(syntax)/sizeof(*syntax); 4953 char *type = NULL; 4954 struct cil_fsuse *fsuse = NULL; 4955 int rc = SEPOL_ERR; 4956 4957 if (db == NULL || parse_current == NULL || ast_node == NULL) { 4958 goto exit; 4959 } 4960 4961 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 4962 if (rc != SEPOL_OK) { 4963 goto exit; 4964 } 4965 4966 type = parse_current->next->data; 4967 4968 cil_fsuse_init(&fsuse); 4969 4970 if (type == CIL_KEY_XATTR) { 4971 fsuse->type = CIL_FSUSE_XATTR; 4972 } else if (type == CIL_KEY_TASK) { 4973 fsuse->type = CIL_FSUSE_TASK; 4974 } else if (type == CIL_KEY_TRANS) { 4975 fsuse->type = CIL_FSUSE_TRANS; 4976 } else { 4977 cil_log(CIL_ERR, "Invalid fsuse type\n"); 4978 goto exit; 4979 } 4980 4981 fsuse->fs_str = parse_current->next->next->data; 4982 4983 if (parse_current->next->next->next->cl_head == NULL) { 4984 fsuse->context_str = parse_current->next->next->next->data; 4985 } else { 4986 cil_context_init(&fsuse->context); 4987 4988 rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context); 4989 if (rc != SEPOL_OK) { 4990 goto exit; 4991 } 4992 } 4993 4994 ast_node->data = fsuse; 4995 ast_node->flavor = CIL_FSUSE; 4996 4997 return SEPOL_OK; 4998 4999 exit: 5000 cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration"); 5001 cil_destroy_fsuse(fsuse); 5002 return SEPOL_ERR; 5003 } 5004 5005 void cil_destroy_fsuse(struct cil_fsuse *fsuse) 5006 { 5007 if (fsuse == NULL) { 5008 return; 5009 } 5010 5011 if (fsuse->context_str == NULL && fsuse->context != NULL) { 5012 cil_destroy_context(fsuse->context); 5013 } 5014 5015 free(fsuse); 5016 } 5017 5018 void cil_destroy_param(struct cil_param *param) 5019 { 5020 if (param == NULL) { 5021 return; 5022 } 5023 5024 free(param); 5025 } 5026 5027 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5028 { 5029 int rc = SEPOL_ERR; 5030 char *key = NULL; 5031 struct cil_macro *macro = NULL; 5032 struct cil_tree_node *macro_content = NULL; 5033 enum cil_syntax syntax[] = { 5034 CIL_SYN_STRING, 5035 CIL_SYN_STRING, 5036 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, 5037 CIL_SYN_N_LISTS | CIL_SYN_END, 5038 CIL_SYN_END 5039 }; 5040 int syntax_len = sizeof(syntax)/ sizeof(*syntax); 5041 5042 if (db == NULL || parse_current == NULL || ast_node == NULL) { 5043 goto exit; 5044 } 5045 5046 rc =__cil_verify_syntax(parse_current, syntax, syntax_len); 5047 if (rc != SEPOL_OK) { 5048 goto exit; 5049 } 5050 5051 cil_macro_init(¯o); 5052 5053 key = parse_current->next->data; 5054 5055 struct cil_tree_node *current_item = parse_current->next->next->cl_head; 5056 while (current_item != NULL) { 5057 enum cil_syntax param_syntax[] = { 5058 CIL_SYN_STRING, 5059 CIL_SYN_STRING, 5060 CIL_SYN_END 5061 }; 5062 int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax); 5063 char *kind = NULL; 5064 struct cil_param *param = NULL; 5065 5066 rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len); 5067 if (rc != SEPOL_OK) { 5068 goto exit; 5069 } 5070 5071 if (macro->params == NULL) { 5072 cil_list_init(¯o->params, CIL_LIST_ITEM); 5073 } 5074 5075 kind = current_item->cl_head->data; 5076 cil_param_init(¶m); 5077 5078 if (kind == CIL_KEY_TYPE) { 5079 param->flavor = CIL_TYPE; 5080 } else if (kind == CIL_KEY_ROLE) { 5081 param->flavor = CIL_ROLE; 5082 } else if (kind == CIL_KEY_USER) { 5083 param->flavor = CIL_USER; 5084 } else if (kind == CIL_KEY_SENSITIVITY) { 5085 param->flavor = CIL_SENS; 5086 } else if (kind == CIL_KEY_CATEGORY) { 5087 param->flavor = CIL_CAT; 5088 } else if (kind == CIL_KEY_CATSET) { 5089 param->flavor = CIL_CATSET; 5090 } else if (kind == CIL_KEY_LEVEL) { 5091 param->flavor = CIL_LEVEL; 5092 } else if (kind == CIL_KEY_LEVELRANGE) { 5093 param->flavor = CIL_LEVELRANGE; 5094 } else if (kind == CIL_KEY_CLASS) { 5095 param->flavor = CIL_CLASS; 5096 } else if (kind == CIL_KEY_IPADDR) { 5097 param->flavor = CIL_IPADDR; 5098 } else if (kind == CIL_KEY_MAP_CLASS) { 5099 param->flavor = CIL_MAP_CLASS; 5100 } else if (kind == CIL_KEY_CLASSPERMISSION) { 5101 param->flavor = CIL_CLASSPERMISSION; 5102 } else if (kind == CIL_KEY_BOOL) { 5103 param->flavor = CIL_BOOL; 5104 } else if (kind == CIL_KEY_STRING) { 5105 param->flavor = CIL_NAME; 5106 } else if (kind == CIL_KEY_NAME) { 5107 param->flavor = CIL_NAME; 5108 } else { 5109 cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind); 5110 cil_destroy_param(param); 5111 goto exit; 5112 } 5113 5114 param->str = current_item->cl_head->next->data; 5115 5116 rc = __cil_verify_name(param->str); 5117 if (rc != SEPOL_OK) { 5118 cil_destroy_param(param); 5119 goto exit; 5120 } 5121 5122 //walk current list and check for duplicate parameters 5123 struct cil_list_item *curr_param; 5124 cil_list_for_each(curr_param, macro->params) { 5125 if (param->str == ((struct cil_param*)curr_param->data)->str) { 5126 if (param->flavor == ((struct cil_param*)curr_param->data)->flavor) { 5127 cil_log(CIL_ERR, "Duplicate parameter\n"); 5128 cil_destroy_param(param); 5129 goto exit; 5130 } 5131 } 5132 } 5133 5134 cil_list_append(macro->params, CIL_PARAM, param); 5135 5136 current_item = current_item->next; 5137 } 5138 5139 /* we don't want the tree walker to walk the macro parameters (they were just handled above), so the subtree is deleted, and the next pointer of the 5140 node containing the macro name is updated to point to the start of the macro content */ 5141 macro_content = parse_current->next->next->next; 5142 cil_tree_subtree_destroy(parse_current->next->next); 5143 parse_current->next->next = macro_content; 5144 if (macro_content == NULL) { 5145 /* No statements in macro and macro parameter list was last node */ 5146 parse_current->parent->cl_tail = parse_current->next; 5147 } 5148 5149 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO); 5150 if (rc != SEPOL_OK) { 5151 goto exit; 5152 } 5153 5154 return SEPOL_OK; 5155 5156 exit: 5157 cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration"); 5158 cil_destroy_macro(macro); 5159 cil_clear_node(ast_node); 5160 return SEPOL_ERR; 5161 } 5162 5163 void cil_destroy_macro(struct cil_macro *macro) 5164 { 5165 if (macro == NULL) { 5166 return; 5167 } 5168 5169 cil_symtab_datum_destroy(¯o->datum); 5170 cil_symtab_array_destroy(macro->symtab); 5171 5172 if (macro->params != NULL) { 5173 cil_list_destroy(¯o->params, 1); 5174 } 5175 5176 free(macro); 5177 } 5178 5179 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5180 { 5181 enum cil_syntax syntax[] = { 5182 CIL_SYN_STRING, 5183 CIL_SYN_STRING, 5184 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END, 5185 CIL_SYN_END 5186 }; 5187 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5188 struct cil_call *call = NULL; 5189 int rc = SEPOL_ERR; 5190 5191 if (db == NULL || parse_current == NULL || ast_node == NULL) { 5192 goto exit; 5193 } 5194 5195 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5196 if (rc != SEPOL_OK) { 5197 goto exit; 5198 } 5199 5200 cil_call_init(&call); 5201 5202 call->macro_str = parse_current->next->data; 5203 5204 if (parse_current->next->next != NULL) { 5205 cil_tree_init(&call->args_tree); 5206 cil_copy_ast(db, parse_current->next->next, call->args_tree->root); 5207 } 5208 5209 ast_node->data = call; 5210 ast_node->flavor = CIL_CALL; 5211 5212 return SEPOL_OK; 5213 5214 exit: 5215 cil_tree_log(parse_current, CIL_ERR, "Bad macro call"); 5216 cil_destroy_call(call); 5217 return rc; 5218 } 5219 5220 void cil_destroy_call(struct cil_call *call) 5221 { 5222 if (call == NULL) { 5223 return; 5224 } 5225 5226 call->macro = NULL; 5227 5228 if (call->args_tree != NULL) { 5229 cil_tree_destroy(&call->args_tree); 5230 } 5231 5232 if (call->args != NULL) { 5233 cil_list_destroy(&call->args, 1); 5234 } 5235 5236 free(call); 5237 } 5238 5239 void cil_destroy_args(struct cil_args *args) 5240 { 5241 if (args == NULL) { 5242 return; 5243 } 5244 5245 if (args->arg_str != NULL) { 5246 args->arg_str = NULL; 5247 } else if (args->arg != NULL) { 5248 struct cil_tree_node *node = args->arg->nodes->head->data; 5249 switch (args->flavor) { 5250 case CIL_NAME: 5251 break; 5252 case CIL_CATSET: 5253 cil_destroy_catset((struct cil_catset *)args->arg); 5254 free(node); 5255 break; 5256 case CIL_LEVEL: 5257 cil_destroy_level((struct cil_level *)args->arg); 5258 free(node); 5259 break; 5260 case CIL_LEVELRANGE: 5261 cil_destroy_levelrange((struct cil_levelrange *)args->arg); 5262 free(node); 5263 break; 5264 case CIL_IPADDR: 5265 cil_destroy_ipaddr((struct cil_ipaddr *)args->arg); 5266 free(node); 5267 break; 5268 case CIL_CLASSPERMISSION: 5269 cil_destroy_classpermission((struct cil_classpermission *)args->arg); 5270 free(node); 5271 break; 5272 default: 5273 cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor); 5274 break; 5275 } 5276 } 5277 5278 args->param_str = NULL; 5279 args->arg = NULL; 5280 5281 free(args); 5282 } 5283 5284 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5285 { 5286 enum cil_syntax syntax[] = { 5287 CIL_SYN_STRING, 5288 CIL_SYN_STRING, 5289 CIL_SYN_N_LISTS | CIL_SYN_END, 5290 CIL_SYN_END 5291 }; 5292 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5293 char *key = NULL; 5294 struct cil_optional *optional = NULL; 5295 int rc = SEPOL_ERR; 5296 5297 if (db == NULL || parse_current == NULL || ast_node == NULL) { 5298 goto exit; 5299 } 5300 5301 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5302 if (rc != SEPOL_OK) { 5303 goto exit; 5304 } 5305 5306 cil_optional_init(&optional); 5307 5308 key = parse_current->next->data; 5309 5310 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL); 5311 if (rc != SEPOL_OK) 5312 goto exit; 5313 5314 return SEPOL_OK; 5315 5316 exit: 5317 cil_tree_log(parse_current, CIL_ERR, "Bad optional"); 5318 cil_destroy_optional(optional); 5319 cil_clear_node(ast_node); 5320 return rc; 5321 } 5322 5323 void cil_destroy_optional(struct cil_optional *optional) 5324 { 5325 if (optional == NULL) { 5326 return; 5327 } 5328 5329 cil_symtab_datum_destroy(&optional->datum); 5330 free(optional); 5331 } 5332 5333 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5334 { 5335 enum cil_syntax syntax[] = { 5336 CIL_SYN_STRING, 5337 CIL_SYN_STRING, 5338 CIL_SYN_END 5339 }; 5340 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5341 char *key = NULL; 5342 struct cil_policycap *polcap = NULL; 5343 int rc = SEPOL_ERR; 5344 5345 if (db == NULL || parse_current == NULL || ast_node == NULL) { 5346 goto exit; 5347 } 5348 5349 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5350 if (rc != SEPOL_OK) { 5351 goto exit; 5352 } 5353 5354 cil_policycap_init(&polcap); 5355 5356 key = parse_current->next->data; 5357 5358 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP); 5359 if (rc != SEPOL_OK) 5360 goto exit; 5361 5362 return SEPOL_OK; 5363 5364 exit: 5365 cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement"); 5366 cil_destroy_policycap(polcap); 5367 cil_clear_node(ast_node); 5368 return rc; 5369 } 5370 5371 void cil_destroy_policycap(struct cil_policycap *polcap) 5372 { 5373 if (polcap == NULL) { 5374 return; 5375 } 5376 5377 cil_symtab_datum_destroy(&polcap->datum); 5378 free(polcap); 5379 } 5380 5381 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5382 { 5383 enum cil_syntax syntax[] = { 5384 CIL_SYN_STRING, 5385 CIL_SYN_STRING, 5386 CIL_SYN_STRING, 5387 CIL_SYN_END 5388 }; 5389 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5390 char *key = NULL; 5391 struct cil_ipaddr *ipaddr = NULL; 5392 int rc = SEPOL_ERR; 5393 5394 if (db == NULL || parse_current == NULL || ast_node == NULL) { 5395 goto exit; 5396 } 5397 5398 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5399 if (rc != SEPOL_OK) { 5400 goto exit; 5401 } 5402 5403 cil_ipaddr_init(&ipaddr); 5404 5405 key = parse_current->next->data; 5406 5407 rc = cil_fill_ipaddr(parse_current->next->next, ipaddr); 5408 if (rc != SEPOL_OK) { 5409 goto exit; 5410 } 5411 5412 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR); 5413 if (rc != SEPOL_OK) { 5414 goto exit; 5415 } 5416 5417 return SEPOL_OK; 5418 5419 exit: 5420 cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement"); 5421 cil_destroy_ipaddr(ipaddr); 5422 cil_clear_node(ast_node); 5423 return rc; 5424 } 5425 5426 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr) 5427 { 5428 if (ipaddr == NULL) { 5429 return; 5430 } 5431 5432 cil_symtab_datum_destroy(&ipaddr->datum); 5433 free(ipaddr); 5434 } 5435 5436 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base) 5437 { 5438 int rc = SEPOL_ERR; 5439 char *endptr = NULL; 5440 int val; 5441 5442 if (int_node == NULL || integer == NULL) { 5443 goto exit; 5444 } 5445 5446 errno = 0; 5447 val = strtol(int_node->data, &endptr, base); 5448 if (errno != 0 || endptr == int_node->data || *endptr != '\0') { 5449 rc = SEPOL_ERR; 5450 goto exit; 5451 } 5452 5453 *integer = val; 5454 5455 return SEPOL_OK; 5456 5457 exit: 5458 cil_log(CIL_ERR, "Failed to create integer from string\n"); 5459 return rc; 5460 } 5461 5462 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base) 5463 { 5464 int rc = SEPOL_ERR; 5465 char *endptr = NULL; 5466 uint64_t val; 5467 5468 if (int_node == NULL || integer == NULL) { 5469 goto exit; 5470 } 5471 5472 errno = 0; 5473 val = strtoull(int_node->data, &endptr, base); 5474 if (errno != 0 || endptr == int_node->data || *endptr != '\0') { 5475 rc = SEPOL_ERR; 5476 goto exit; 5477 } 5478 5479 *integer = val; 5480 5481 return SEPOL_OK; 5482 5483 exit: 5484 cil_log(CIL_ERR, "Failed to create integer from string\n"); 5485 return rc; 5486 } 5487 5488 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr) 5489 { 5490 int rc = SEPOL_ERR; 5491 5492 if (addr_node == NULL || addr == NULL) { 5493 goto exit; 5494 } 5495 5496 if (addr_node->cl_head != NULL || addr_node->next != NULL) { 5497 goto exit; 5498 } 5499 5500 if (strchr(addr_node->data, '.') != NULL) { 5501 addr->family = AF_INET; 5502 } else { 5503 addr->family = AF_INET6; 5504 } 5505 5506 rc = inet_pton(addr->family, addr_node->data, &addr->ip); 5507 if (rc != 1) { 5508 rc = SEPOL_ERR; 5509 goto exit; 5510 } 5511 5512 return SEPOL_OK; 5513 5514 exit: 5515 cil_log(CIL_ERR, "Bad ip address or netmask\n"); 5516 return rc; 5517 } 5518 5519 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level) 5520 { 5521 int rc = SEPOL_ERR; 5522 enum cil_syntax syntax[] = { 5523 CIL_SYN_STRING, 5524 CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END, 5525 CIL_SYN_END 5526 }; 5527 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5528 5529 if (curr == NULL) { 5530 goto exit; 5531 } 5532 5533 rc = __cil_verify_syntax(curr, syntax, syntax_len); 5534 if (rc != SEPOL_OK) { 5535 goto exit; 5536 } 5537 5538 level->sens_str = curr->data; 5539 if (curr->next != NULL) { 5540 rc = cil_fill_cats(curr->next, &level->cats); 5541 if (rc != SEPOL_OK) { 5542 goto exit; 5543 } 5544 } 5545 5546 return SEPOL_OK; 5547 5548 exit: 5549 cil_log(CIL_ERR, "Bad level\n"); 5550 return rc; 5551 } 5552 5553 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats) 5554 { 5555 int rc = SEPOL_ERR; 5556 5557 cil_cats_init(cats); 5558 5559 rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr); 5560 if (rc != SEPOL_OK) { 5561 cil_destroy_cats(*cats); 5562 *cats = NULL; 5563 } 5564 5565 return rc; 5566 } 5567 5568 void cil_destroy_cats(struct cil_cats *cats) 5569 { 5570 if (cats == NULL) { 5571 return; 5572 } 5573 5574 cil_list_destroy(&cats->str_expr, CIL_TRUE); 5575 5576 cil_list_destroy(&cats->datum_expr, CIL_FALSE); 5577 5578 free(cats); 5579 } 5580 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) 5581 { 5582 enum cil_syntax syntax[] = { 5583 CIL_SYN_STRING, 5584 CIL_SYN_STRING, 5585 CIL_SYN_STRING, 5586 CIL_SYN_END 5587 }; 5588 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5589 struct cil_bounds *bounds = NULL; 5590 int rc = SEPOL_ERR; 5591 5592 if (db == NULL || parse_current == NULL || ast_node == NULL) { 5593 goto exit; 5594 } 5595 5596 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5597 if (rc != SEPOL_OK) { 5598 goto exit; 5599 } 5600 5601 cil_bounds_init(&bounds); 5602 5603 bounds->parent_str = parse_current->next->data; 5604 bounds->child_str = parse_current->next->next->data; 5605 5606 ast_node->data = bounds; 5607 5608 switch (flavor) { 5609 case CIL_USER: 5610 ast_node->flavor = CIL_USERBOUNDS; 5611 break; 5612 case CIL_ROLE: 5613 ast_node->flavor = CIL_ROLEBOUNDS; 5614 break; 5615 case CIL_TYPE: 5616 ast_node->flavor = CIL_TYPEBOUNDS; 5617 break; 5618 default: 5619 break; 5620 } 5621 5622 return SEPOL_OK; 5623 5624 exit: 5625 cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration"); 5626 cil_destroy_bounds(bounds); 5627 return rc; 5628 } 5629 5630 void cil_destroy_bounds(struct cil_bounds *bounds) 5631 { 5632 if (bounds == NULL) { 5633 return; 5634 } 5635 5636 free(bounds); 5637 } 5638 5639 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) 5640 { 5641 int rc = SEPOL_ERR; 5642 struct cil_default *def = NULL; 5643 char *object; 5644 enum cil_syntax syntax[] = { 5645 CIL_SYN_STRING, 5646 CIL_SYN_STRING | CIL_SYN_LIST, 5647 CIL_SYN_STRING, 5648 CIL_SYN_END 5649 }; 5650 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5651 5652 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5653 if (rc != SEPOL_OK) { 5654 goto exit; 5655 } 5656 5657 cil_default_init(&def); 5658 5659 def->flavor = flavor; 5660 5661 if (parse_current->next->cl_head == NULL) { 5662 cil_list_init(&def->class_strs, CIL_CLASS); 5663 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); 5664 } else { 5665 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); 5666 if (rc != SEPOL_OK) { 5667 goto exit; 5668 } 5669 } 5670 5671 object = parse_current->next->next->data; 5672 if (object == CIL_KEY_SOURCE) { 5673 def->object = CIL_DEFAULT_SOURCE; 5674 } else if (object == CIL_KEY_TARGET) { 5675 def->object = CIL_DEFAULT_TARGET; 5676 } else { 5677 cil_log(CIL_ERR,"Expected either 'source' or 'target'\n"); 5678 rc = SEPOL_ERR; 5679 goto exit; 5680 } 5681 5682 ast_node->data = def; 5683 ast_node->flavor = flavor; 5684 5685 return SEPOL_OK; 5686 5687 exit: 5688 cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current)); 5689 cil_destroy_default(def); 5690 return rc; 5691 } 5692 5693 void cil_destroy_default(struct cil_default *def) 5694 { 5695 if (def == NULL) { 5696 return; 5697 } 5698 5699 cil_list_destroy(&def->class_strs, CIL_TRUE); 5700 5701 cil_list_destroy(&def->class_datums, CIL_FALSE); 5702 5703 free(def); 5704 } 5705 5706 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5707 { 5708 int rc = SEPOL_ERR; 5709 struct cil_defaultrange *def = NULL; 5710 char *object; 5711 char *range; 5712 enum cil_syntax syntax[] = { 5713 CIL_SYN_STRING, 5714 CIL_SYN_STRING | CIL_SYN_LIST, 5715 CIL_SYN_STRING, 5716 CIL_SYN_STRING, 5717 CIL_SYN_END 5718 }; 5719 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5720 5721 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5722 if (rc != SEPOL_OK) { 5723 goto exit; 5724 } 5725 5726 cil_defaultrange_init(&def); 5727 5728 if (parse_current->next->cl_head == NULL) { 5729 cil_list_init(&def->class_strs, CIL_CLASS); 5730 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); 5731 } else { 5732 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); 5733 if (rc != SEPOL_OK) { 5734 goto exit; 5735 } 5736 } 5737 5738 object = parse_current->next->next->data; 5739 range = parse_current->next->next->next->data; 5740 if (object == CIL_KEY_SOURCE) { 5741 if (range == CIL_KEY_LOW) { 5742 def->object_range = CIL_DEFAULT_SOURCE_LOW; 5743 } else if (range == CIL_KEY_HIGH) { 5744 def->object_range = CIL_DEFAULT_SOURCE_HIGH; 5745 } else if (range == CIL_KEY_LOW_HIGH) { 5746 def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH; 5747 } else { 5748 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n"); 5749 rc = SEPOL_ERR; 5750 goto exit; 5751 } 5752 } else if (parse_current->next->next->data == CIL_KEY_TARGET) { 5753 if (range == CIL_KEY_LOW) { 5754 def->object_range = CIL_DEFAULT_TARGET_LOW; 5755 } else if (range == CIL_KEY_HIGH) { 5756 def->object_range = CIL_DEFAULT_TARGET_HIGH; 5757 } else if (range == CIL_KEY_LOW_HIGH) { 5758 def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH; 5759 } else { 5760 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n"); 5761 rc = SEPOL_ERR; 5762 goto exit; 5763 } 5764 } else { 5765 cil_log(CIL_ERR,"Expected either \'source\' or \'target\'\n"); 5766 rc = SEPOL_ERR; 5767 goto exit; 5768 } 5769 5770 ast_node->data = def; 5771 ast_node->flavor = CIL_DEFAULTRANGE; 5772 5773 return SEPOL_OK; 5774 5775 exit: 5776 cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration"); 5777 cil_destroy_defaultrange(def); 5778 return rc; 5779 } 5780 5781 void cil_destroy_defaultrange(struct cil_defaultrange *def) 5782 { 5783 if (def == NULL) { 5784 return; 5785 } 5786 5787 cil_list_destroy(&def->class_strs, CIL_TRUE); 5788 5789 cil_list_destroy(&def->class_datums, CIL_FALSE); 5790 5791 free(def); 5792 } 5793 5794 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5795 { 5796 int rc = SEPOL_ERR; 5797 enum cil_syntax syntax[] = { 5798 CIL_SYN_STRING, 5799 CIL_SYN_STRING, 5800 CIL_SYN_END 5801 }; 5802 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5803 struct cil_handleunknown *unknown = NULL; 5804 char *unknown_key; 5805 5806 if (parse_current == NULL || ast_node == NULL) { 5807 goto exit; 5808 } 5809 5810 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5811 if (rc != SEPOL_OK) { 5812 goto exit; 5813 } 5814 5815 cil_handleunknown_init(&unknown); 5816 5817 unknown_key = parse_current->next->data; 5818 if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) { 5819 unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN; 5820 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) { 5821 unknown->handle_unknown = SEPOL_DENY_UNKNOWN; 5822 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) { 5823 unknown->handle_unknown = SEPOL_REJECT_UNKNOWN; 5824 } else { 5825 cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT); 5826 rc = SEPOL_ERR; 5827 goto exit; 5828 } 5829 5830 ast_node->data = unknown; 5831 ast_node->flavor = CIL_HANDLEUNKNOWN; 5832 5833 return SEPOL_OK; 5834 5835 exit: 5836 cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown"); 5837 cil_destroy_handleunknown(unknown); 5838 return rc; 5839 } 5840 5841 void cil_destroy_handleunknown(struct cil_handleunknown *unk) 5842 { 5843 free(unk); 5844 } 5845 5846 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5847 { 5848 int rc = SEPOL_ERR; 5849 enum cil_syntax syntax[] = { 5850 CIL_SYN_STRING, 5851 CIL_SYN_STRING, 5852 CIL_SYN_END 5853 }; 5854 int syntax_len = sizeof(syntax)/sizeof(*syntax); 5855 struct cil_mls *mls = NULL; 5856 5857 if (parse_current == NULL || ast_node == NULL) { 5858 goto exit; 5859 } 5860 5861 rc = __cil_verify_syntax(parse_current, syntax, syntax_len); 5862 if (rc != SEPOL_OK) { 5863 goto exit; 5864 } 5865 5866 cil_mls_init(&mls); 5867 5868 if (parse_current->next->data == CIL_KEY_CONDTRUE) { 5869 mls->value = CIL_TRUE; 5870 } else if (parse_current->next->data == CIL_KEY_CONDFALSE) { 5871 mls->value = CIL_FALSE; 5872 } else { 5873 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); 5874 rc = SEPOL_ERR; 5875 goto exit; 5876 } 5877 5878 ast_node->data = mls; 5879 ast_node->flavor = CIL_MLS; 5880 5881 return SEPOL_OK; 5882 5883 exit: 5884 cil_tree_log(parse_current, CIL_ERR, "Bad mls"); 5885 cil_destroy_mls(mls); 5886 return rc; 5887 } 5888 5889 void cil_destroy_mls(struct cil_mls *mls) 5890 { 5891 free(mls); 5892 } 5893 5894 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) 5895 { 5896 /* No need to check syntax, because this is auto generated */ 5897 struct cil_src_info *info = NULL; 5898 5899 cil_src_info_init(&info); 5900 5901 info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE; 5902 info->path = parse_current->next->next->data; 5903 5904 ast_node->data = info; 5905 ast_node->flavor = CIL_SRC_INFO; 5906 5907 return SEPOL_OK; 5908 } 5909 5910 void cil_destroy_src_info(struct cil_src_info *info) 5911 { 5912 free(info); 5913 } 5914 5915 int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args) 5916 { 5917 struct cil_args_build *args = NULL; 5918 struct cil_tree_node *ast_current = NULL; 5919 struct cil_db *db = NULL; 5920 struct cil_tree_node *ast_node = NULL; 5921 struct cil_tree_node *macro = NULL; 5922 struct cil_tree_node *boolif = NULL; 5923 struct cil_tree_node *tunif = NULL; 5924 struct cil_tree_node *in = NULL; 5925 int rc = SEPOL_ERR; 5926 5927 if (parse_current == NULL || finished == NULL || extra_args == NULL) { 5928 goto exit; 5929 } 5930 5931 args = extra_args; 5932 ast_current = args->ast; 5933 db = args->db; 5934 macro = args->macro; 5935 boolif = args->boolif; 5936 tunif = args->tunif; 5937 in = args->in; 5938 5939 if (parse_current->parent->cl_head != parse_current) { 5940 /* ignore anything that isn't following a parenthesis */ 5941 rc = SEPOL_OK; 5942 goto exit; 5943 } else if (parse_current->data == NULL) { 5944 /* the only time parenthsis can immediately following parenthesis is if 5945 * the parent is the root node */ 5946 if (parse_current->parent->parent == NULL) { 5947 rc = SEPOL_OK; 5948 } else { 5949 cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis"); 5950 } 5951 goto exit; 5952 } 5953 5954 if (macro != NULL) { 5955 if (parse_current->data == CIL_KEY_MACRO || 5956 parse_current->data == CIL_KEY_TUNABLE || 5957 parse_current->data == CIL_KEY_IN || 5958 parse_current->data == CIL_KEY_BLOCK || 5959 parse_current->data == CIL_KEY_BLOCKINHERIT || 5960 parse_current->data == CIL_KEY_BLOCKABSTRACT) { 5961 rc = SEPOL_ERR; 5962 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data); 5963 goto exit; 5964 } 5965 } 5966 5967 if (boolif != NULL) { 5968 if (parse_current->data != CIL_KEY_CONDTRUE && 5969 parse_current->data != CIL_KEY_CONDFALSE && 5970 parse_current->data != CIL_KEY_AUDITALLOW && 5971 parse_current->data != CIL_KEY_TUNABLEIF && 5972 parse_current->data != CIL_KEY_ALLOW && 5973 parse_current->data != CIL_KEY_DONTAUDIT && 5974 parse_current->data != CIL_KEY_TYPETRANSITION && 5975 parse_current->data != CIL_KEY_TYPECHANGE && 5976 parse_current->data != CIL_KEY_CALL) { 5977 rc = SEPOL_ERR; 5978 cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data); 5979 if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { 5980 cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n", 5981 (char*)parse_current->data); 5982 } else { 5983 cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n", 5984 (char*)parse_current->data); 5985 } 5986 goto exit; 5987 } 5988 } 5989 5990 if (tunif != NULL) { 5991 if (parse_current->data == CIL_KEY_TUNABLE) { 5992 rc = SEPOL_ERR; 5993 cil_tree_log(parse_current, CIL_ERR, "Found tunable"); 5994 cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n"); 5995 goto exit; 5996 } 5997 } 5998 5999 if (in != NULL) { 6000 if (parse_current->data == CIL_KEY_IN) { 6001 rc = SEPOL_ERR; 6002 cil_tree_log(parse_current, CIL_ERR, "Found in-statement"); 6003 cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n"); 6004 goto exit; 6005 } 6006 } 6007 6008 cil_tree_node_init(&ast_node); 6009 6010 ast_node->parent = ast_current; 6011 ast_node->line = parse_current->line; 6012 ast_node->hll_line = parse_current->hll_line; 6013 6014 if (parse_current->data == CIL_KEY_BLOCK) { 6015 rc = cil_gen_block(db, parse_current, ast_node, 0); 6016 } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) { 6017 rc = cil_gen_blockinherit(db, parse_current, ast_node); 6018 } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) { 6019 rc = cil_gen_blockabstract(db, parse_current, ast_node); 6020 } else if (parse_current->data == CIL_KEY_IN) { 6021 rc = cil_gen_in(db, parse_current, ast_node); 6022 } else if (parse_current->data == CIL_KEY_CLASS) { 6023 rc = cil_gen_class(db, parse_current, ast_node); 6024 // To avoid parsing list of perms again 6025 *finished = CIL_TREE_SKIP_NEXT; 6026 } else if (parse_current->data == CIL_KEY_CLASSORDER) { 6027 rc = cil_gen_classorder(db, parse_current, ast_node); 6028 *finished = CIL_TREE_SKIP_NEXT; 6029 } else if (parse_current->data == CIL_KEY_MAP_CLASS) { 6030 rc = cil_gen_map_class(db, parse_current, ast_node); 6031 *finished = CIL_TREE_SKIP_NEXT; 6032 } else if (parse_current->data == CIL_KEY_CLASSMAPPING) { 6033 rc = cil_gen_classmapping(db, parse_current, ast_node); 6034 *finished = CIL_TREE_SKIP_NEXT; 6035 } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) { 6036 rc = cil_gen_classpermission(db, parse_current, ast_node); 6037 *finished = CIL_TREE_SKIP_NEXT; 6038 } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) { 6039 rc = cil_gen_classpermissionset(db, parse_current, ast_node); 6040 *finished = CIL_TREE_SKIP_NEXT; 6041 } else if (parse_current->data == CIL_KEY_COMMON) { 6042 rc = cil_gen_common(db, parse_current, ast_node); 6043 *finished = CIL_TREE_SKIP_NEXT; 6044 } else if (parse_current->data == CIL_KEY_CLASSCOMMON) { 6045 rc = cil_gen_classcommon(db, parse_current, ast_node); 6046 } else if (parse_current->data == CIL_KEY_SID) { 6047 rc = cil_gen_sid(db, parse_current, ast_node); 6048 *finished = CIL_TREE_SKIP_NEXT; 6049 } else if (parse_current->data == CIL_KEY_SIDCONTEXT) { 6050 rc = cil_gen_sidcontext(db, parse_current, ast_node); 6051 *finished = CIL_TREE_SKIP_NEXT; 6052 } else if (parse_current->data == CIL_KEY_SIDORDER) { 6053 rc = cil_gen_sidorder(db, parse_current, ast_node); 6054 *finished = CIL_TREE_SKIP_NEXT; 6055 } else if (parse_current->data == CIL_KEY_USER) { 6056 rc = cil_gen_user(db, parse_current, ast_node); 6057 } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) { 6058 rc = cil_gen_userattribute(db, parse_current, ast_node); 6059 } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) { 6060 rc = cil_gen_userattributeset(db, parse_current, ast_node); 6061 *finished = CIL_TREE_SKIP_NEXT; 6062 } else if (parse_current->data == CIL_KEY_USERLEVEL) { 6063 rc = cil_gen_userlevel(db, parse_current, ast_node); 6064 *finished = CIL_TREE_SKIP_NEXT; 6065 } else if (parse_current->data == CIL_KEY_USERRANGE) { 6066 rc = cil_gen_userrange(db, parse_current, ast_node); 6067 *finished = CIL_TREE_SKIP_NEXT; 6068 } else if (parse_current->data == CIL_KEY_USERBOUNDS) { 6069 rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER); 6070 } else if (parse_current->data == CIL_KEY_USERPREFIX) { 6071 rc = cil_gen_userprefix(db, parse_current, ast_node); 6072 } else if (parse_current->data == CIL_KEY_SELINUXUSER) { 6073 rc = cil_gen_selinuxuser(db, parse_current, ast_node); 6074 *finished = CIL_TREE_SKIP_NEXT; 6075 } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) { 6076 rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node); 6077 *finished = CIL_TREE_SKIP_NEXT; 6078 } else if (parse_current->data == CIL_KEY_TYPE) { 6079 rc = cil_gen_type(db, parse_current, ast_node); 6080 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) { 6081 rc = cil_gen_typeattribute(db, parse_current, ast_node); 6082 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) { 6083 rc = cil_gen_typeattributeset(db, parse_current, ast_node); 6084 *finished = CIL_TREE_SKIP_NEXT; 6085 } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) { 6086 rc = cil_gen_expandtypeattribute(db, parse_current, ast_node); 6087 *finished = CIL_TREE_SKIP_NEXT; 6088 } else if (parse_current->data == CIL_KEY_TYPEALIAS) { 6089 rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS); 6090 } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) { 6091 rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL); 6092 } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) { 6093 rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE); 6094 } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) { 6095 rc = cil_gen_typepermissive(db, parse_current, ast_node); 6096 } else if (parse_current->data == CIL_KEY_RANGETRANSITION) { 6097 rc = cil_gen_rangetransition(db, parse_current, ast_node); 6098 *finished = CIL_TREE_SKIP_NEXT; 6099 } else if (parse_current->data == CIL_KEY_ROLE) { 6100 rc = cil_gen_role(db, parse_current, ast_node); 6101 } else if (parse_current->data == CIL_KEY_USERROLE) { 6102 rc = cil_gen_userrole(db, parse_current, ast_node); 6103 } else if (parse_current->data == CIL_KEY_ROLETYPE) { 6104 rc = cil_gen_roletype(db, parse_current, ast_node); 6105 } else if (parse_current->data == CIL_KEY_ROLETRANSITION) { 6106 rc = cil_gen_roletransition(parse_current, ast_node); 6107 } else if (parse_current->data == CIL_KEY_ROLEALLOW) { 6108 rc = cil_gen_roleallow(db, parse_current, ast_node); 6109 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) { 6110 rc = cil_gen_roleattribute(db, parse_current, ast_node); 6111 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) { 6112 rc = cil_gen_roleattributeset(db, parse_current, ast_node); 6113 *finished = CIL_TREE_SKIP_NEXT; 6114 } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) { 6115 rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE); 6116 } else if (parse_current->data == CIL_KEY_BOOL) { 6117 rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE); 6118 } else if (parse_current->data == CIL_KEY_BOOLEANIF) { 6119 rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE); 6120 } else if(parse_current->data == CIL_KEY_TUNABLE) { 6121 if (db->preserve_tunables) { 6122 rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE); 6123 } else { 6124 rc = cil_gen_tunable(db, parse_current, ast_node); 6125 } 6126 } else if (parse_current->data == CIL_KEY_TUNABLEIF) { 6127 if (db->preserve_tunables) { 6128 rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE); 6129 } else { 6130 rc = cil_gen_tunif(db, parse_current, ast_node); 6131 } 6132 } else if (parse_current->data == CIL_KEY_CONDTRUE) { 6133 rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE); 6134 } else if (parse_current->data == CIL_KEY_CONDFALSE) { 6135 rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE); 6136 } else if (parse_current->data == CIL_KEY_ALLOW) { 6137 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED); 6138 // So that the object and perms lists do not get parsed again 6139 *finished = CIL_TREE_SKIP_NEXT; 6140 } else if (parse_current->data == CIL_KEY_AUDITALLOW) { 6141 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW); 6142 *finished = CIL_TREE_SKIP_NEXT; 6143 } else if (parse_current->data == CIL_KEY_DONTAUDIT) { 6144 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT); 6145 *finished = CIL_TREE_SKIP_NEXT; 6146 } else if (parse_current->data == CIL_KEY_NEVERALLOW) { 6147 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW); 6148 *finished = CIL_TREE_SKIP_NEXT; 6149 } else if (parse_current->data == CIL_KEY_ALLOWX) { 6150 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED); 6151 *finished = CIL_TREE_SKIP_NEXT; 6152 } else if (parse_current->data == CIL_KEY_AUDITALLOWX) { 6153 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW); 6154 *finished = CIL_TREE_SKIP_NEXT; 6155 } else if (parse_current->data == CIL_KEY_DONTAUDITX) { 6156 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT); 6157 *finished = CIL_TREE_SKIP_NEXT; 6158 } else if (parse_current->data == CIL_KEY_NEVERALLOWX) { 6159 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW); 6160 *finished = CIL_TREE_SKIP_NEXT; 6161 } else if (parse_current->data == CIL_KEY_PERMISSIONX) { 6162 rc = cil_gen_permissionx(db, parse_current, ast_node); 6163 *finished = CIL_TREE_SKIP_NEXT; 6164 } else if (parse_current->data == CIL_KEY_TYPETRANSITION) { 6165 rc = cil_gen_typetransition(db, parse_current, ast_node); 6166 } else if (parse_current->data == CIL_KEY_TYPECHANGE) { 6167 rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE); 6168 } else if (parse_current->data == CIL_KEY_TYPEMEMBER) { 6169 rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER); 6170 } else if (parse_current->data == CIL_KEY_SENSITIVITY) { 6171 rc = cil_gen_sensitivity(db, parse_current, ast_node); 6172 } else if (parse_current->data == CIL_KEY_SENSALIAS) { 6173 rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS); 6174 } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) { 6175 rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL); 6176 } else if (parse_current->data == CIL_KEY_CATEGORY) { 6177 rc = cil_gen_category(db, parse_current, ast_node); 6178 } else if (parse_current->data == CIL_KEY_CATALIAS) { 6179 rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS); 6180 } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) { 6181 rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL); 6182 } else if (parse_current->data == CIL_KEY_CATSET) { 6183 rc = cil_gen_catset(db, parse_current, ast_node); 6184 *finished = CIL_TREE_SKIP_NEXT; 6185 } else if (parse_current->data == CIL_KEY_CATORDER) { 6186 rc = cil_gen_catorder(db, parse_current, ast_node); 6187 *finished = CIL_TREE_SKIP_NEXT; 6188 } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) { 6189 rc = cil_gen_sensitivityorder(db, parse_current, ast_node); 6190 *finished = CIL_TREE_SKIP_NEXT; 6191 } else if (parse_current->data == CIL_KEY_SENSCAT) { 6192 rc = cil_gen_senscat(db, parse_current, ast_node); 6193 *finished = CIL_TREE_SKIP_NEXT; 6194 } else if (parse_current->data == CIL_KEY_LEVEL) { 6195 rc = cil_gen_level(db, parse_current, ast_node); 6196 *finished = CIL_TREE_SKIP_NEXT; 6197 } else if (parse_current->data == CIL_KEY_LEVELRANGE) { 6198 rc = cil_gen_levelrange(db, parse_current, ast_node); 6199 *finished = CIL_TREE_SKIP_NEXT; 6200 } else if (parse_current->data == CIL_KEY_CONSTRAIN) { 6201 rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN); 6202 *finished = CIL_TREE_SKIP_NEXT; 6203 } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) { 6204 rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN); 6205 *finished = CIL_TREE_SKIP_NEXT; 6206 } else if (parse_current->data == CIL_KEY_VALIDATETRANS) { 6207 rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS); 6208 *finished = CIL_TREE_SKIP_NEXT; 6209 } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) { 6210 rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS); 6211 *finished = CIL_TREE_SKIP_NEXT; 6212 } else if (parse_current->data == CIL_KEY_CONTEXT) { 6213 rc = cil_gen_context(db, parse_current, ast_node); 6214 *finished = CIL_TREE_SKIP_NEXT; 6215 } else if (parse_current->data == CIL_KEY_FILECON) { 6216 rc = cil_gen_filecon(db, parse_current, ast_node); 6217 *finished = CIL_TREE_SKIP_NEXT; 6218 } else if (parse_current->data == CIL_KEY_PORTCON) { 6219 rc = cil_gen_portcon(db, parse_current, ast_node); 6220 *finished = CIL_TREE_SKIP_NEXT; 6221 } else if (parse_current->data == CIL_KEY_NODECON) { 6222 rc = cil_gen_nodecon(db, parse_current, ast_node); 6223 *finished = CIL_TREE_SKIP_NEXT; 6224 } else if (parse_current->data == CIL_KEY_GENFSCON) { 6225 rc = cil_gen_genfscon(db, parse_current, ast_node); 6226 *finished = CIL_TREE_SKIP_NEXT; 6227 } else if (parse_current->data == CIL_KEY_NETIFCON) { 6228 rc = cil_gen_netifcon(db, parse_current, ast_node); 6229 *finished = CIL_TREE_SKIP_NEXT; 6230 } else if (parse_current->data == CIL_KEY_PIRQCON) { 6231 rc = cil_gen_pirqcon(db, parse_current, ast_node); 6232 *finished = CIL_TREE_SKIP_NEXT; 6233 } else if (parse_current->data == CIL_KEY_IOMEMCON) { 6234 rc = cil_gen_iomemcon(db, parse_current, ast_node); 6235 *finished = CIL_TREE_SKIP_NEXT; 6236 } else if (parse_current->data == CIL_KEY_IOPORTCON) { 6237 rc = cil_gen_ioportcon(db, parse_current, ast_node); 6238 *finished = CIL_TREE_SKIP_NEXT; 6239 } else if (parse_current->data == CIL_KEY_PCIDEVICECON) { 6240 rc = cil_gen_pcidevicecon(db, parse_current, ast_node); 6241 *finished = CIL_TREE_SKIP_NEXT; 6242 } else if (parse_current->data == CIL_KEY_DEVICETREECON) { 6243 rc = cil_gen_devicetreecon(db, parse_current, ast_node); 6244 *finished = CIL_TREE_SKIP_NEXT; 6245 } else if (parse_current->data == CIL_KEY_FSUSE) { 6246 rc = cil_gen_fsuse(db, parse_current, ast_node); 6247 *finished = CIL_TREE_SKIP_NEXT; 6248 } else if (parse_current->data == CIL_KEY_MACRO) { 6249 rc = cil_gen_macro(db, parse_current, ast_node); 6250 } else if (parse_current->data == CIL_KEY_CALL) { 6251 rc = cil_gen_call(db, parse_current, ast_node); 6252 *finished = 1; 6253 } else if (parse_current->data == CIL_KEY_POLICYCAP) { 6254 rc = cil_gen_policycap(db, parse_current, ast_node); 6255 *finished = 1; 6256 } else if (parse_current->data == CIL_KEY_OPTIONAL) { 6257 rc = cil_gen_optional(db, parse_current, ast_node); 6258 } else if (parse_current->data == CIL_KEY_IPADDR) { 6259 rc = cil_gen_ipaddr(db, parse_current, ast_node); 6260 } else if (parse_current->data == CIL_KEY_DEFAULTUSER) { 6261 rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER); 6262 *finished = CIL_TREE_SKIP_NEXT; 6263 } else if (parse_current->data == CIL_KEY_DEFAULTROLE) { 6264 rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE); 6265 *finished = CIL_TREE_SKIP_NEXT; 6266 } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) { 6267 rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE); 6268 *finished = CIL_TREE_SKIP_NEXT; 6269 } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) { 6270 rc = cil_gen_defaultrange(parse_current, ast_node); 6271 *finished = CIL_TREE_SKIP_NEXT; 6272 } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) { 6273 rc = cil_gen_handleunknown(parse_current, ast_node); 6274 *finished = CIL_TREE_SKIP_NEXT; 6275 } else if (parse_current->data == CIL_KEY_MLS) { 6276 rc = cil_gen_mls(parse_current, ast_node); 6277 *finished = CIL_TREE_SKIP_NEXT; 6278 } else if (parse_current->data == CIL_KEY_SRC_INFO) { 6279 rc = cil_gen_src_info(parse_current, ast_node); 6280 } else { 6281 cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data); 6282 rc = SEPOL_ERR; 6283 } 6284 6285 if (rc == SEPOL_OK) { 6286 if (ast_current->cl_head == NULL) { 6287 if (ast_current->flavor == CIL_MACRO) { 6288 args->macro = ast_current; 6289 } 6290 6291 if (ast_current->flavor == CIL_BOOLEANIF) { 6292 args->boolif = ast_current; 6293 } 6294 6295 if (ast_current->flavor == CIL_TUNABLEIF) { 6296 args->tunif = ast_current; 6297 } 6298 6299 if (ast_current->flavor == CIL_IN) { 6300 args->in = ast_current; 6301 } 6302 6303 ast_current->cl_head = ast_node; 6304 } else { 6305 ast_current->cl_tail->next = ast_node; 6306 } 6307 ast_current->cl_tail = ast_node; 6308 ast_current = ast_node; 6309 args->ast = ast_current; 6310 } else { 6311 cil_tree_node_destroy(&ast_node); 6312 } 6313 6314 exit: 6315 return rc; 6316 } 6317 6318 int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args) 6319 { 6320 int rc = SEPOL_ERR; 6321 struct cil_tree_node *ast = NULL; 6322 struct cil_args_build *args = NULL; 6323 6324 if (extra_args == NULL) { 6325 goto exit; 6326 } 6327 6328 args = extra_args; 6329 ast = args->ast; 6330 6331 if (ast->flavor == CIL_ROOT) { 6332 rc = SEPOL_OK; 6333 goto exit; 6334 } 6335 6336 args->ast = ast->parent; 6337 6338 if (ast->flavor == CIL_MACRO) { 6339 args->macro = NULL; 6340 } 6341 6342 if (ast->flavor == CIL_BOOLEANIF) { 6343 args->boolif = NULL; 6344 } 6345 6346 if (ast->flavor == CIL_TUNABLEIF) { 6347 args->tunif = NULL; 6348 } 6349 6350 if (ast->flavor == CIL_IN) { 6351 args->in = NULL; 6352 } 6353 6354 // At this point we no longer have any need for parse_current or any of its 6355 // siblings; they have all been converted to the appropriate AST node. The 6356 // full parse tree will get deleted elsewhere, but in an attempt to 6357 // minimize memory useage (of which the parse tree uses alot), start 6358 // deleting the parts we don't need now. 6359 cil_tree_children_destroy(parse_current->parent); 6360 6361 return SEPOL_OK; 6362 6363 exit: 6364 return rc; 6365 } 6366 6367 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast) 6368 { 6369 int rc = SEPOL_ERR; 6370 struct cil_args_build extra_args; 6371 6372 if (db == NULL || parse_tree == NULL || ast == NULL) { 6373 goto exit; 6374 } 6375 6376 extra_args.ast = ast; 6377 extra_args.db = db; 6378 extra_args.macro = NULL; 6379 extra_args.boolif = NULL; 6380 extra_args.tunif = NULL; 6381 extra_args.in = NULL; 6382 6383 rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args); 6384 if (rc != SEPOL_OK) { 6385 goto exit; 6386 } 6387 6388 return SEPOL_OK; 6389 6390 exit: 6391 return rc; 6392 } 6393