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