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