1 /* Author : Joshua Brindle <jbrindle (at) tresys.com> 2 * Karl MacMillan <kmacmillan (at) tresys.com> 3 * Jason Tang <jtang (at) tresys.com> 4 * Added support for binary policy modules 5 * 6 * Copyright (C) 2004 - 2005 Tresys Technology, LLC 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, version 2. 10 */ 11 12 #include <assert.h> 13 #include <stdarg.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 #include <sepol/policydb/policydb.h> 18 #include <sepol/policydb/avrule_block.h> 19 #include <sepol/policydb/conditional.h> 20 21 #include "queue.h" 22 #include "module_compiler.h" 23 24 union stack_item_u { 25 avrule_block_t *avrule; 26 cond_list_t *cond_list; 27 }; 28 29 typedef struct scope_stack { 30 union stack_item_u u; 31 int type; /* for above union: 1 = avrule block, 2 = conditional */ 32 avrule_decl_t *decl; /* if in an avrule block, which 33 * declaration is current */ 34 avrule_t *last_avrule; 35 int in_else; /* if in an avrule block, within ELSE branch */ 36 int require_given; /* 1 if this block had at least one require */ 37 struct scope_stack *parent, *child; 38 } scope_stack_t; 39 40 extern policydb_t *policydbp; 41 extern queue_t id_queue; 42 extern int yyerror(const char *msg); 43 __attribute__ ((format(printf, 1, 2))) 44 extern void yyerror2(const char *fmt, ...); 45 46 static int push_stack(int stack_type, ...); 47 static void pop_stack(void); 48 49 /* keep track of the last item added to the stack */ 50 static scope_stack_t *stack_top = NULL; 51 static avrule_block_t *last_block; 52 static uint32_t next_decl_id = 1; 53 54 static const char * const flavor_str[SYM_NUM] = { 55 [SYM_COMMONS] = "common", 56 [SYM_CLASSES] = "class", 57 [SYM_ROLES] = "role", 58 [SYM_TYPES] = "type", 59 [SYM_USERS] = "user", 60 [SYM_BOOLS] = "bool", 61 [SYM_LEVELS] = "level", 62 [SYM_CATS] = "cat" 63 }; 64 65 static void print_error_msg(int ret, uint32_t symbol_type) 66 { 67 switch (ret) { 68 case -3: 69 yyerror("Out of memory!"); 70 break; 71 case -2: 72 yyerror2("Duplicate declaration of %s", flavor_str[symbol_type]); 73 break; 74 case -1: 75 yyerror2("Could not declare %s here", flavor_str[symbol_type]); 76 break; 77 default: 78 yyerror("Unknown error"); 79 } 80 } 81 82 int define_policy(int pass, int module_header_given) 83 { 84 char *id; 85 86 if (module_header_given) { 87 if (policydbp->policy_type != POLICY_MOD) { 88 yyerror 89 ("Module specification found while not building a policy module.\n"); 90 return -1; 91 } 92 93 if (pass == 2) { 94 while ((id = queue_remove(id_queue)) != NULL) 95 free(id); 96 } else { 97 id = (char *)queue_remove(id_queue); 98 if (!id) { 99 yyerror("no module name"); 100 return -1; 101 } 102 policydbp->name = id; 103 if ((policydbp->version = 104 queue_remove(id_queue)) == NULL) { 105 yyerror 106 ("Expected a module version but none was found."); 107 return -1; 108 } 109 } 110 } else { 111 if (policydbp->policy_type == POLICY_MOD) { 112 yyerror 113 ("Building a policy module, but no module specification found.\n"); 114 return -1; 115 } 116 } 117 /* the first declaration within the global avrule 118 block will always have an id of 1 */ 119 next_decl_id = 2; 120 121 /* reset the scoping stack */ 122 while (stack_top != NULL) { 123 pop_stack(); 124 } 125 if (push_stack(1, policydbp->global, policydbp->global->branch_list) == 126 -1) { 127 return -1; 128 } 129 last_block = policydbp->global; 130 return 0; 131 } 132 133 /* Given the current parse stack, returns 1 if a declaration or require would 134 * be allowed here or 0 if not. For example, declarations and requirements are 135 * not allowed in conditionals, so if there are any conditionals in the 136 * current scope stack then this would return a 0. 137 */ 138 static int is_creation_allowed(void) 139 { 140 if (stack_top->type != 1 || stack_top->in_else) { 141 return 0; 142 } 143 return 1; 144 } 145 146 /* Attempt to declare or require a symbol within the current scope. 147 * Returns: 148 * 0: Success - Symbol had not been previously created. 149 * 1: Success - Symbol had already been created and caller must free datum. 150 * -1: Failure - Symbol cannot be created here 151 * -2: Failure - Duplicate declaration or type/attribute mismatch 152 * -3: Failure - Out of memory or some other error 153 */ 154 static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, 155 uint32_t * dest_value, uint32_t scope) 156 { 157 avrule_decl_t *decl = stack_top->decl; 158 int ret; 159 160 if (!is_creation_allowed()) { 161 return -1; 162 } 163 164 ret = symtab_insert(policydbp, symbol_type, key, datum, scope, 165 decl->decl_id, dest_value); 166 167 if (ret == 1 && dest_value) { 168 symtab_datum_t *s = 169 hashtab_search(policydbp->symtab[symbol_type].table, 170 key); 171 assert(s != NULL); 172 173 if (symbol_type == SYM_LEVELS) { 174 *dest_value = ((level_datum_t *)s)->level->sens; 175 } else { 176 *dest_value = s->value; 177 } 178 } else if (ret == -2) { 179 return -2; 180 } else if (ret < 0) { 181 return -3; 182 } 183 184 return ret; 185 } 186 187 /* Attempt to declare a symbol within the current declaration. If 188 * currently within a non-conditional and in a non-else branch then 189 * insert the symbol, return 0 on success if symbol was undeclared. 190 * For roles and users, it is legal to have multiple declarations; as 191 * such return 1 to indicate that caller must free() the datum because 192 * it was not added. If symbols may not be declared here return -1. 193 * For duplicate declarations return -2. For all else, including out 194 * of memory, return -3. Note that dest_value and datum_value might 195 * not be restricted pointers. */ 196 int declare_symbol(uint32_t symbol_type, 197 hashtab_key_t key, hashtab_datum_t datum, 198 uint32_t * dest_value, uint32_t * datum_value) 199 { 200 avrule_decl_t *decl = stack_top->decl; 201 int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_DECL); 202 203 if (ret < 0) { 204 return ret; 205 } 206 207 if (ebitmap_set_bit(decl->declared.scope + symbol_type, 208 *datum_value - 1, 1)) { 209 return -3; 210 } 211 212 return ret; 213 } 214 215 static int role_implicit_bounds(hashtab_t roles_tab, 216 char *role_id, role_datum_t *role) 217 { 218 role_datum_t *bounds; 219 char *bounds_id, *delim; 220 221 delim = strrchr(role_id, '.'); 222 if (!delim) 223 return 0; /* no implicit boundary */ 224 225 bounds_id = strdup(role_id); 226 if (!bounds_id) { 227 yyerror("out of memory"); 228 return -1; 229 } 230 bounds_id[(size_t)(delim - role_id)] = '\0'; 231 232 bounds = hashtab_search(roles_tab, bounds_id); 233 if (!bounds) { 234 yyerror2("role %s doesn't exist, is implicit bounds of %s", 235 bounds_id, role_id); 236 return -1; 237 } 238 239 if (!role->bounds) 240 role->bounds = bounds->s.value; 241 else if (role->bounds != bounds->s.value) { 242 yyerror2("role %s has inconsistent bounds %s/%s", 243 role_id, bounds_id, 244 policydbp->p_role_val_to_name[role->bounds - 1]); 245 return -1; 246 } 247 free(bounds_id); 248 249 return 0; 250 } 251 252 static int create_role(uint32_t scope, unsigned char isattr, role_datum_t **role, char **key) 253 { 254 char *id = queue_remove(id_queue); 255 role_datum_t *datum = NULL; 256 int ret; 257 uint32_t value; 258 259 *role = NULL; 260 *key = NULL; 261 isattr = isattr ? ROLE_ATTRIB : ROLE_ROLE; 262 263 if (id == NULL) { 264 yyerror("no role name"); 265 return -1; 266 } 267 268 datum = malloc(sizeof(*datum)); 269 if (datum == NULL) { 270 yyerror("Out of memory!"); 271 free(id); 272 return -1; 273 } 274 275 role_datum_init(datum); 276 datum->flavor = isattr; 277 278 if (scope == SCOPE_DECL) { 279 ret = declare_symbol(SYM_ROLES, id, datum, &value, &value); 280 } else { 281 ret = require_symbol(SYM_ROLES, id, datum, &value, &value); 282 } 283 284 datum->s.value = value; 285 286 if (ret == 0) { 287 *role = datum; 288 *key = strdup(id); 289 if (*key == NULL) { 290 yyerror("Out of memory!"); 291 return -1; 292 } 293 } else if (ret == 1) { 294 *role = hashtab_search(policydbp->symtab[SYM_ROLES].table, id); 295 if (*role && (isattr != (*role)->flavor)) { 296 yyerror2("Identifier %s used as both an attribute and a role", 297 id); 298 free(id); 299 role_datum_destroy(datum); 300 free(datum); 301 return -1; 302 } 303 *role = datum; 304 *key = id; 305 } else { 306 print_error_msg(ret, SYM_ROLES); 307 free(id); 308 role_datum_destroy(datum); 309 free(datum); 310 } 311 312 return ret; 313 } 314 315 role_datum_t *declare_role(unsigned char isattr) 316 { 317 char *key = NULL; 318 role_datum_t *role = NULL; 319 role_datum_t *dest_role = NULL; 320 hashtab_t roles_tab; 321 int ret, ret2; 322 323 ret = create_role(SCOPE_DECL, isattr, &role, &key); 324 if (ret < 0) { 325 return NULL; 326 } 327 328 /* create a new role_datum_t for this decl, if necessary */ 329 assert(stack_top->type == 1); 330 331 if (stack_top->parent == NULL) { 332 /* in parent, so use global symbol table */ 333 roles_tab = policydbp->p_roles.table; 334 } else { 335 roles_tab = stack_top->decl->p_roles.table; 336 } 337 338 dest_role = hashtab_search(roles_tab, key); 339 if (dest_role == NULL) { 340 if (ret == 0) { 341 dest_role = malloc(sizeof(*dest_role)); 342 if (dest_role == NULL) { 343 yyerror("Out of memory!"); 344 free(key); 345 return NULL; 346 } 347 role_datum_init(dest_role); 348 dest_role->s.value = role->s.value; 349 dest_role->flavor = role->flavor; 350 } else { 351 dest_role = role; 352 } 353 ret2 = role_implicit_bounds(roles_tab, key, dest_role); 354 if (ret2 != 0) { 355 free(key); 356 role_datum_destroy(dest_role); 357 free(dest_role); 358 return NULL; 359 } 360 ret2 = hashtab_insert(roles_tab, key, dest_role); 361 if (ret2 != 0) { 362 yyerror("Out of memory!"); 363 free(key); 364 role_datum_destroy(dest_role); 365 free(dest_role); 366 return NULL; 367 } 368 } else { 369 free(key); 370 if (ret == 1) { 371 role_datum_destroy(role); 372 free(role); 373 } 374 } 375 376 if (ret == 0) { 377 ret2 = ebitmap_set_bit(&dest_role->dominates, dest_role->s.value - 1, 1); 378 if (ret2 != 0) { 379 yyerror("out of memory"); 380 return NULL; 381 } 382 } 383 384 return dest_role; 385 } 386 387 static int create_type(uint32_t scope, unsigned char isattr, type_datum_t **type) 388 { 389 char *id; 390 type_datum_t *datum; 391 int ret; 392 uint32_t value = 0; 393 394 *type = NULL; 395 isattr = isattr ? TYPE_ATTRIB : TYPE_TYPE; 396 397 id = (char *)queue_remove(id_queue); 398 if (!id) { 399 yyerror("no type/attribute name?"); 400 return -1; 401 } 402 if (strcmp(id, "self") == 0) { 403 yyerror("\"self\" is a reserved type name."); 404 free(id); 405 return -1; 406 } 407 408 datum = malloc(sizeof(*datum)); 409 if (!datum) { 410 yyerror("Out of memory!"); 411 free(id); 412 return -1; 413 } 414 type_datum_init(datum); 415 datum->primary = 1; 416 datum->flavor = isattr; 417 418 if (scope == SCOPE_DECL) { 419 ret = declare_symbol(SYM_TYPES, id, datum, &value, &value); 420 } else { 421 ret = require_symbol(SYM_TYPES, id, datum, &value, &value); 422 } 423 424 if (ret == 0) { 425 datum->s.value = value; 426 *type = datum; 427 } else if (ret == 1) { 428 type_datum_destroy(datum); 429 free(datum); 430 *type = hashtab_search(policydbp->symtab[SYM_TYPES].table, id); 431 if (*type && (isattr != (*type)->flavor)) { 432 yyerror2("Identifier %s used as both an attribute and a type", 433 id); 434 free(id); 435 return -1; 436 } 437 free(id); 438 } else { 439 print_error_msg(ret, SYM_TYPES); 440 free(id); 441 type_datum_destroy(datum); 442 free(datum); 443 } 444 445 return ret; 446 } 447 448 type_datum_t *declare_type(unsigned char primary, unsigned char isattr) 449 { 450 type_datum_t *type = NULL; 451 int ret = create_type(SCOPE_DECL, isattr, &type); 452 453 if (ret == 0) { 454 type->primary = primary; 455 } 456 457 return type; 458 } 459 460 static int user_implicit_bounds(hashtab_t users_tab, 461 char *user_id, user_datum_t *user) 462 { 463 user_datum_t *bounds; 464 char *bounds_id, *delim; 465 466 delim = strrchr(user_id, '.'); 467 if (!delim) 468 return 0; /* no implicit boundary */ 469 470 bounds_id = strdup(user_id); 471 if (!bounds_id) { 472 yyerror("out of memory"); 473 return -1; 474 } 475 bounds_id[(size_t)(delim - user_id)] = '\0'; 476 477 bounds = hashtab_search(users_tab, bounds_id); 478 if (!bounds) { 479 yyerror2("user %s doesn't exist, is implicit bounds of %s", 480 bounds_id, user_id); 481 return -1; 482 } 483 484 if (!user->bounds) 485 user->bounds = bounds->s.value; 486 else if (user->bounds != bounds->s.value) { 487 yyerror2("user %s has inconsistent bounds %s/%s", 488 user_id, bounds_id, 489 policydbp->p_role_val_to_name[user->bounds - 1]); 490 return -1; 491 } 492 free(bounds_id); 493 494 return 0; 495 } 496 497 static int create_user(uint32_t scope, user_datum_t **user, char **key) 498 { 499 char *id = queue_remove(id_queue); 500 user_datum_t *datum = NULL; 501 int ret; 502 uint32_t value; 503 504 *user = NULL; 505 *key = NULL; 506 507 if (id == NULL) { 508 yyerror("no user name"); 509 return -1; 510 } 511 512 datum = malloc(sizeof(*datum)); 513 if (datum == NULL) { 514 yyerror("Out of memory!"); 515 free(id); 516 return -1; 517 } 518 519 user_datum_init(datum); 520 521 if (scope == SCOPE_DECL) { 522 ret = declare_symbol(SYM_USERS, id, datum, &value, &value); 523 } else { 524 ret = require_symbol(SYM_USERS, id, datum, &value, &value); 525 } 526 527 datum->s.value = value; 528 529 if (ret == 0) { 530 *user = datum; 531 *key = strdup(id); 532 if (*key == NULL) { 533 yyerror("Out of memory!"); 534 return -1; 535 } 536 } else if (ret == 1) { 537 *user = datum; 538 *key = id; 539 } else { 540 print_error_msg(ret, SYM_USERS); 541 free(id); 542 user_datum_destroy(datum); 543 free(datum); 544 } 545 546 return ret; 547 } 548 549 user_datum_t *declare_user(void) 550 { 551 char *key = NULL; 552 user_datum_t *user = NULL; 553 user_datum_t *dest_user = NULL; 554 hashtab_t users_tab; 555 int ret, ret2; 556 557 ret = create_user(SCOPE_DECL, &user, &key); 558 if (ret < 0) { 559 return NULL; 560 } 561 562 /* create a new user_datum_t for this decl, if necessary */ 563 assert(stack_top->type == 1); 564 565 if (stack_top->parent == NULL) { 566 /* in parent, so use global symbol table */ 567 users_tab = policydbp->p_users.table; 568 } else { 569 users_tab = stack_top->decl->p_users.table; 570 } 571 572 dest_user = hashtab_search(users_tab, key); 573 if (dest_user == NULL) { 574 if (ret == 0) { 575 dest_user = malloc(sizeof(*dest_user)); 576 if (dest_user == NULL) { 577 yyerror("Out of memory!"); 578 free(key); 579 return NULL; 580 } 581 user_datum_init(dest_user); 582 dest_user->s.value = user->s.value; 583 } else { 584 dest_user = user; 585 } 586 ret2 = user_implicit_bounds(users_tab, key, dest_user); 587 if (ret2 != 0) { 588 free(key); 589 user_datum_destroy(dest_user); 590 free(dest_user); 591 return NULL; 592 } 593 ret2 = hashtab_insert(users_tab, key, dest_user); 594 if (ret2 != 0) { 595 yyerror("Out of memory!"); 596 free(key); 597 user_datum_destroy(dest_user); 598 free(dest_user); 599 return NULL; 600 } 601 } else { 602 free(key); 603 if (ret == 1) { 604 user_datum_destroy(user); 605 free(user); 606 } 607 } 608 609 return dest_user; 610 } 611 612 /* Return a type_datum_t for the local avrule_decl with the given ID. 613 * If it does not exist, create one with the same value as 'value'. 614 * This function assumes that the ID is within scope. c.f., 615 * is_id_in_scope(). 616 * 617 * NOTE: this function usurps ownership of id afterwards. The caller 618 * shall not reference it nor free() it afterwards. 619 */ 620 type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr) 621 { 622 type_datum_t *dest_typdatum; 623 hashtab_t types_tab; 624 assert(stack_top->type == 1); 625 if (stack_top->parent == NULL) { 626 /* in global, so use global symbol table */ 627 types_tab = policydbp->p_types.table; 628 } else { 629 types_tab = stack_top->decl->p_types.table; 630 } 631 dest_typdatum = hashtab_search(types_tab, id); 632 if (!dest_typdatum) { 633 dest_typdatum = (type_datum_t *) malloc(sizeof(type_datum_t)); 634 if (dest_typdatum == NULL) { 635 free(id); 636 return NULL; 637 } 638 type_datum_init(dest_typdatum); 639 dest_typdatum->s.value = value; 640 dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE; 641 dest_typdatum->primary = 1; 642 if (hashtab_insert(types_tab, id, dest_typdatum)) { 643 free(id); 644 type_datum_destroy(dest_typdatum); 645 free(dest_typdatum); 646 return NULL; 647 } 648 649 } else { 650 free(id); 651 if (dest_typdatum->flavor != isattr ? TYPE_ATTRIB : TYPE_TYPE) { 652 return NULL; 653 } 654 } 655 return dest_typdatum; 656 } 657 658 /* Return a role_datum_t for the local avrule_decl with the given ID. 659 * If it does not exist, create one with the same value as 'value'. 660 * This function assumes that the ID is within scope. c.f., 661 * is_id_in_scope(). 662 * 663 * NOTE: this function usurps ownership of id afterwards. The caller 664 * shall not reference it nor free() it afterwards. 665 */ 666 role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr) 667 { 668 role_datum_t *dest_roledatum; 669 hashtab_t roles_tab; 670 671 assert(stack_top->type == 1); 672 673 if (stack_top->parent == NULL) { 674 /* in global, so use global symbol table */ 675 roles_tab = policydbp->p_roles.table; 676 } else { 677 roles_tab = stack_top->decl->p_roles.table; 678 } 679 680 dest_roledatum = hashtab_search(roles_tab, id); 681 if (!dest_roledatum) { 682 dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t)); 683 if (dest_roledatum == NULL) { 684 free(id); 685 return NULL; 686 } 687 688 role_datum_init(dest_roledatum); 689 dest_roledatum->s.value = value; 690 dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; 691 692 if (hashtab_insert(roles_tab, id, dest_roledatum)) { 693 free(id); 694 role_datum_destroy(dest_roledatum); 695 free(dest_roledatum); 696 return NULL; 697 } 698 } else { 699 free(id); 700 if (dest_roledatum->flavor != isattr ? ROLE_ATTRIB : ROLE_ROLE) 701 return NULL; 702 } 703 704 return dest_roledatum; 705 } 706 707 /* Attempt to require a symbol within the current scope. If currently 708 * within an optional (and not its else branch), add the symbol to the 709 * required list. Return 0 on success, 1 if caller needs to free() 710 * datum. If symbols may not be declared here return -1. For duplicate 711 * declarations return -2. For all else, including out of memory, 712 * return -3.. Note that dest_value and datum_value might not be 713 * restricted pointers. 714 */ 715 int require_symbol(uint32_t symbol_type, 716 hashtab_key_t key, hashtab_datum_t datum, 717 uint32_t * dest_value, uint32_t * datum_value) 718 { 719 avrule_decl_t *decl = stack_top->decl; 720 int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_REQ); 721 722 if (ret < 0) { 723 return ret; 724 } 725 726 if (ebitmap_set_bit(decl->required.scope + symbol_type, 727 *datum_value - 1, 1)) { 728 return -3; 729 } 730 731 stack_top->require_given = 1; 732 return ret; 733 } 734 735 int add_perm_to_class(uint32_t perm_value, uint32_t class_value) 736 { 737 avrule_decl_t *decl = stack_top->decl; 738 scope_index_t *scope; 739 740 assert(perm_value >= 1); 741 assert(class_value >= 1); 742 scope = &decl->required; 743 if (class_value > scope->class_perms_len) { 744 uint32_t i; 745 ebitmap_t *new_map = realloc(scope->class_perms_map, 746 class_value * sizeof(*new_map)); 747 if (new_map == NULL) { 748 return -1; 749 } 750 scope->class_perms_map = new_map; 751 for (i = scope->class_perms_len; i < class_value; i++) { 752 ebitmap_init(scope->class_perms_map + i); 753 } 754 scope->class_perms_len = class_value; 755 } 756 if (ebitmap_set_bit(scope->class_perms_map + class_value - 1, 757 perm_value - 1, 1)) { 758 return -1; 759 } 760 return 0; 761 } 762 763 static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p 764 __attribute__ ((unused))) 765 { 766 if (key) 767 free(key); 768 free(datum); 769 return 0; 770 } 771 772 static void class_datum_destroy(class_datum_t * cladatum) 773 { 774 if (cladatum != NULL) { 775 hashtab_map(cladatum->permissions.table, perm_destroy, NULL); 776 hashtab_destroy(cladatum->permissions.table); 777 free(cladatum); 778 } 779 } 780 781 int require_class(int pass) 782 { 783 char *class_id = queue_remove(id_queue); 784 char *perm_id = NULL; 785 class_datum_t *datum = NULL; 786 perm_datum_t *perm = NULL; 787 int ret; 788 789 if (pass == 2) { 790 free(class_id); 791 while ((perm_id = queue_remove(id_queue)) != NULL) 792 free(perm_id); 793 return 0; 794 } 795 796 /* first add the class if it is not already there */ 797 if (class_id == NULL) { 798 yyerror("no class name for class definition?"); 799 return -1; 800 } 801 802 if ((datum = calloc(1, sizeof(*datum))) == NULL || 803 symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) { 804 yyerror("Out of memory!"); 805 class_datum_destroy(datum); 806 return -1; 807 } 808 ret = 809 require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value, 810 &datum->s.value); 811 if (ret < 0) { 812 print_error_msg(ret, SYM_CLASSES); 813 free(class_id); 814 class_datum_destroy(datum); 815 return -1; 816 } 817 818 if (ret == 0) { 819 /* a new class was added; reindex everything */ 820 if (policydb_index_classes(policydbp)) { 821 yyerror("Out of memory!"); 822 return -1; 823 } 824 } else { 825 class_datum_destroy(datum); 826 datum = hashtab_search(policydbp->p_classes.table, class_id); 827 assert(datum); /* the class datum should have existed */ 828 free(class_id); 829 } 830 831 /* now add each of the permissions to this class's requirements */ 832 while ((perm_id = queue_remove(id_queue)) != NULL) { 833 int allocated = 0; 834 835 /* Is the permission already in the table? */ 836 perm = hashtab_search(datum->permissions.table, perm_id); 837 if (!perm && datum->comdatum) 838 perm = 839 hashtab_search(datum->comdatum->permissions.table, 840 perm_id); 841 if (perm) { 842 /* Yes, drop the name. */ 843 free(perm_id); 844 } else { 845 /* No - allocate and insert an entry for it. */ 846 if (policydbp->policy_type == POLICY_BASE) { 847 yyerror2 848 ("Base policy - require of permission %s without prior declaration.", 849 perm_id); 850 free(perm_id); 851 return -1; 852 } 853 allocated = 1; 854 if ((perm = malloc(sizeof(*perm))) == NULL) { 855 yyerror("Out of memory!"); 856 free(perm_id); 857 return -1; 858 } 859 memset(perm, 0, sizeof(*perm)); 860 ret = 861 hashtab_insert(datum->permissions.table, perm_id, 862 perm); 863 if (ret) { 864 yyerror("Out of memory!"); 865 free(perm_id); 866 free(perm); 867 return -1; 868 } 869 perm->s.value = datum->permissions.nprim + 1; 870 } 871 872 if (add_perm_to_class(perm->s.value, datum->s.value) == -1) { 873 yyerror("Out of memory!"); 874 return -1; 875 } 876 877 /* Update number of primitives if we allocated one. */ 878 if (allocated) 879 datum->permissions.nprim++; 880 } 881 return 0; 882 } 883 884 static int require_role_or_attribute(int pass, unsigned char isattr) 885 { 886 char *key = NULL; 887 role_datum_t *role = NULL; 888 int ret; 889 890 if (pass == 2) { 891 free(queue_remove(id_queue)); 892 return 0; 893 } 894 895 ret = create_role(SCOPE_REQ, isattr, &role, &key); 896 if (ret < 0) { 897 return -1; 898 } 899 900 free(key); 901 902 if (ret == 0) { 903 ret = ebitmap_set_bit(&role->dominates, role->s.value - 1, 1); 904 if (ret != 0) { 905 yyerror("Out of memory"); 906 return -1; 907 } 908 } else { 909 role_datum_destroy(role); 910 free(role); 911 } 912 913 return 0; 914 } 915 916 int require_role(int pass) 917 { 918 return require_role_or_attribute(pass, 0); 919 } 920 921 int require_attribute_role(int pass) 922 { 923 return require_role_or_attribute(pass, 1); 924 } 925 926 static int require_type_or_attribute(int pass, unsigned char isattr) 927 { 928 type_datum_t *type = NULL; 929 int ret; 930 931 if (pass == 2) { 932 free(queue_remove(id_queue)); 933 return 0; 934 } 935 936 ret = create_type(SCOPE_REQ, isattr, &type); 937 938 if (ret < 0) { 939 return -1; 940 } 941 942 return 0; 943 } 944 945 int require_type(int pass) 946 { 947 return require_type_or_attribute(pass, 0); 948 } 949 950 int require_attribute(int pass) 951 { 952 return require_type_or_attribute(pass, 1); 953 } 954 955 int require_user(int pass) 956 { 957 char *key = NULL; 958 user_datum_t *user = NULL; 959 int ret; 960 961 if (pass == 1) { 962 free(queue_remove(id_queue)); 963 return 0; 964 } 965 966 ret = create_user(SCOPE_REQ, &user, &key); 967 if (ret < 0) { 968 return -1; 969 } 970 971 free(key); 972 973 if (ret == 1) { 974 user_datum_destroy(user); 975 free(user); 976 } 977 978 return 0; 979 } 980 981 static int require_bool_tunable(int pass, int is_tunable) 982 { 983 char *id = queue_remove(id_queue); 984 cond_bool_datum_t *booldatum = NULL; 985 int retval; 986 if (pass == 2) { 987 free(id); 988 return 0; 989 } 990 if (id == NULL) { 991 yyerror("no boolean name"); 992 return -1; 993 } 994 if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) { 995 cond_destroy_bool(id, booldatum, NULL); 996 yyerror("Out of memory!"); 997 return -1; 998 } 999 if (is_tunable) 1000 booldatum->flags |= COND_BOOL_FLAGS_TUNABLE; 1001 retval = 1002 require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum, 1003 &booldatum->s.value, &booldatum->s.value); 1004 if (retval != 0) { 1005 cond_destroy_bool(id, booldatum, NULL); 1006 if (retval < 0) { 1007 print_error_msg(retval, SYM_BOOLS); 1008 return -1; 1009 } 1010 } 1011 1012 return 0; 1013 } 1014 1015 int require_bool(int pass) 1016 { 1017 return require_bool_tunable(pass, 0); 1018 } 1019 1020 int require_tunable(int pass) 1021 { 1022 return require_bool_tunable(pass, 1); 1023 } 1024 1025 int require_sens(int pass) 1026 { 1027 char *id = queue_remove(id_queue); 1028 level_datum_t *level = NULL; 1029 int retval; 1030 if (pass == 2) { 1031 free(id); 1032 return 0; 1033 } 1034 if (!id) { 1035 yyerror("no sensitivity name"); 1036 return -1; 1037 } 1038 level = malloc(sizeof(level_datum_t)); 1039 if (!level) { 1040 free(id); 1041 yyerror("Out of memory!"); 1042 return -1; 1043 } 1044 level_datum_init(level); 1045 level->level = malloc(sizeof(mls_level_t)); 1046 if (!level->level) { 1047 free(id); 1048 level_datum_destroy(level); 1049 free(level); 1050 yyerror("Out of memory!"); 1051 return -1; 1052 } 1053 mls_level_init(level->level); 1054 retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level, 1055 &level->level->sens, &level->level->sens); 1056 if (retval != 0) { 1057 free(id); 1058 mls_level_destroy(level->level); 1059 free(level->level); 1060 level_datum_destroy(level); 1061 free(level); 1062 if (retval < 0) { 1063 print_error_msg(retval, SYM_LEVELS); 1064 return -1; 1065 } 1066 } 1067 1068 return 0; 1069 } 1070 1071 int require_cat(int pass) 1072 { 1073 char *id = queue_remove(id_queue); 1074 cat_datum_t *cat = NULL; 1075 int retval; 1076 if (pass == 2) { 1077 free(id); 1078 return 0; 1079 } 1080 if (!id) { 1081 yyerror("no category name"); 1082 return -1; 1083 } 1084 cat = malloc(sizeof(cat_datum_t)); 1085 if (!cat) { 1086 free(id); 1087 yyerror("Out of memory!"); 1088 return -1; 1089 } 1090 cat_datum_init(cat); 1091 1092 retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat, 1093 &cat->s.value, &cat->s.value); 1094 if (retval != 0) { 1095 free(id); 1096 cat_datum_destroy(cat); 1097 free(cat); 1098 if (retval < 0) { 1099 print_error_msg(retval, SYM_CATS); 1100 return -1; 1101 } 1102 } 1103 1104 return 0; 1105 } 1106 1107 static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) 1108 { 1109 uint32_t i; 1110 if (stack == NULL) { 1111 return 0; /* no matching scope found */ 1112 } 1113 if (stack->type == 1) { 1114 avrule_decl_t *decl = stack->decl; 1115 for (i = 0; i < scope->decl_ids_len; i++) { 1116 if (scope->decl_ids[i] == decl->decl_id) { 1117 return 1; 1118 } 1119 } 1120 } else { 1121 /* note that conditionals can't declare or require 1122 * symbols, so skip this level */ 1123 } 1124 1125 /* not within scope of this stack, so try its parent */ 1126 return is_scope_in_stack(scope, stack->parent); 1127 } 1128 1129 int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id) 1130 { 1131 scope_datum_t *scope = 1132 (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type]. 1133 table, id); 1134 if (scope == NULL) { 1135 return 1; /* id is not known, so return success */ 1136 } 1137 return is_scope_in_stack(scope, stack_top); 1138 } 1139 1140 static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value, 1141 scope_index_t * scope) 1142 { 1143 if (class_value > scope->class_perms_len) { 1144 return 1; 1145 } 1146 if (ebitmap_get_bit(scope->class_perms_map + class_value - 1, 1147 perm_value - 1)) { 1148 return 1; 1149 } 1150 return 0; 1151 } 1152 1153 static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value, 1154 scope_stack_t * stack) 1155 { 1156 if (stack == NULL) { 1157 return 0; /* no matching scope found */ 1158 } 1159 if (stack->type == 1) { 1160 avrule_decl_t *decl = stack->decl; 1161 if (is_perm_in_scope_index 1162 (perm_value, class_value, &decl->required) 1163 || is_perm_in_scope_index(perm_value, class_value, 1164 &decl->declared)) { 1165 return 1; 1166 } 1167 } else { 1168 /* note that conditionals can't declare or require 1169 * symbols, so skip this level */ 1170 } 1171 1172 /* not within scope of this stack, so try its parent */ 1173 return is_perm_in_stack(perm_value, class_value, stack->parent); 1174 } 1175 1176 int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id) 1177 { 1178 class_datum_t *cladatum = 1179 (class_datum_t *) hashtab_search(policydbp->p_classes.table, 1180 class_id); 1181 perm_datum_t *perdatum; 1182 if (cladatum == NULL) { 1183 return 1; 1184 } 1185 perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table, 1186 perm_id); 1187 if (perdatum == NULL) { 1188 return 1; 1189 } 1190 return is_perm_in_stack(perdatum->s.value, cladatum->s.value, 1191 stack_top); 1192 } 1193 1194 cond_list_t *get_current_cond_list(cond_list_t * cond) 1195 { 1196 /* FIX ME: do something different here if in a nested 1197 * conditional? */ 1198 avrule_decl_t *decl = stack_top->decl; 1199 return get_decl_cond_list(policydbp, decl, cond); 1200 } 1201 1202 /* Append the new conditional node to the existing ones. During 1203 * expansion the list will be reversed -- i.e., the last AV rule will 1204 * be the first one listed in the policy. This matches the behavior 1205 * of the upstream compiler. */ 1206 void append_cond_list(cond_list_t * cond) 1207 { 1208 cond_list_t *old_cond = get_current_cond_list(cond); 1209 avrule_t *tmp; 1210 assert(old_cond != NULL); /* probably out of memory */ 1211 if (old_cond->avtrue_list == NULL) { 1212 old_cond->avtrue_list = cond->avtrue_list; 1213 } else { 1214 for (tmp = old_cond->avtrue_list; tmp->next != NULL; 1215 tmp = tmp->next) ; 1216 tmp->next = cond->avtrue_list; 1217 } 1218 if (old_cond->avfalse_list == NULL) { 1219 old_cond->avfalse_list = cond->avfalse_list; 1220 } else { 1221 for (tmp = old_cond->avfalse_list; tmp->next != NULL; 1222 tmp = tmp->next) ; 1223 tmp->next = cond->avfalse_list; 1224 } 1225 1226 old_cond->flags |= cond->flags; 1227 } 1228 1229 void append_avrule(avrule_t * avrule) 1230 { 1231 avrule_decl_t *decl = stack_top->decl; 1232 1233 /* currently avrules follow a completely different code path 1234 * for handling avrules and compute types 1235 * (define_cond_avrule_te_avtab, define_cond_compute_type); 1236 * therefore there ought never be a conditional on top of the 1237 * scope stack */ 1238 assert(stack_top->type == 1); 1239 1240 if (stack_top->last_avrule == NULL) { 1241 decl->avrules = avrule; 1242 } else { 1243 stack_top->last_avrule->next = avrule; 1244 } 1245 stack_top->last_avrule = avrule; 1246 } 1247 1248 /* this doesn't actually append, but really prepends it */ 1249 void append_role_trans(role_trans_rule_t * role_tr_rules) 1250 { 1251 avrule_decl_t *decl = stack_top->decl; 1252 1253 /* role transitions are not allowed within conditionals */ 1254 assert(stack_top->type == 1); 1255 1256 role_tr_rules->next = decl->role_tr_rules; 1257 decl->role_tr_rules = role_tr_rules; 1258 } 1259 1260 /* this doesn't actually append, but really prepends it */ 1261 void append_role_allow(role_allow_rule_t * role_allow_rules) 1262 { 1263 avrule_decl_t *decl = stack_top->decl; 1264 1265 /* role allows are not allowed within conditionals */ 1266 assert(stack_top->type == 1); 1267 1268 role_allow_rules->next = decl->role_allow_rules; 1269 decl->role_allow_rules = role_allow_rules; 1270 } 1271 1272 /* this doesn't actually append, but really prepends it */ 1273 void append_filename_trans(filename_trans_rule_t * filename_trans_rules) 1274 { 1275 avrule_decl_t *decl = stack_top->decl; 1276 1277 /* filename transitions are not allowed within conditionals */ 1278 assert(stack_top->type == 1); 1279 1280 filename_trans_rules->next = decl->filename_trans_rules; 1281 decl->filename_trans_rules = filename_trans_rules; 1282 } 1283 1284 /* this doesn't actually append, but really prepends it */ 1285 void append_range_trans(range_trans_rule_t * range_tr_rules) 1286 { 1287 avrule_decl_t *decl = stack_top->decl; 1288 1289 /* range transitions are not allowed within conditionals */ 1290 assert(stack_top->type == 1); 1291 1292 range_tr_rules->next = decl->range_tr_rules; 1293 decl->range_tr_rules = range_tr_rules; 1294 } 1295 1296 int begin_optional(int pass) 1297 { 1298 avrule_block_t *block = NULL; 1299 avrule_decl_t *decl; 1300 if (pass == 1) { 1301 /* allocate a new avrule block for this optional block */ 1302 if ((block = avrule_block_create()) == NULL || 1303 (decl = avrule_decl_create(next_decl_id)) == NULL) { 1304 goto cleanup; 1305 } 1306 block->flags |= AVRULE_OPTIONAL; 1307 block->branch_list = decl; 1308 last_block->next = block; 1309 } else { 1310 /* select the next block from the chain built during pass 1 */ 1311 block = last_block->next; 1312 assert(block != NULL && 1313 block->branch_list != NULL && 1314 block->branch_list->decl_id == next_decl_id); 1315 decl = block->branch_list; 1316 } 1317 if (push_stack(1, block, decl) == -1) { 1318 goto cleanup; 1319 } 1320 stack_top->last_avrule = NULL; 1321 last_block = block; 1322 next_decl_id++; 1323 return 0; 1324 cleanup: 1325 yyerror("Out of memory!"); 1326 avrule_block_destroy(block); 1327 return -1; 1328 } 1329 1330 int end_optional(int pass __attribute__ ((unused))) 1331 { 1332 /* once nested conditionals are allowed, do the stack unfolding here */ 1333 pop_stack(); 1334 return 0; 1335 } 1336 1337 int begin_optional_else(int pass) 1338 { 1339 avrule_decl_t *decl; 1340 assert(stack_top->type == 1 && stack_top->in_else == 0); 1341 if (pass == 1) { 1342 /* allocate a new declaration and add it to the 1343 * current chain */ 1344 if ((decl = avrule_decl_create(next_decl_id)) == NULL) { 1345 yyerror("Out of memory!"); 1346 return -1; 1347 } 1348 stack_top->decl->next = decl; 1349 } else { 1350 /* pick the (hopefully last) declaration of this 1351 avrule block, built from pass 1 */ 1352 decl = stack_top->decl->next; 1353 assert(decl != NULL && 1354 decl->next == NULL && decl->decl_id == next_decl_id); 1355 } 1356 stack_top->in_else = 1; 1357 stack_top->decl = decl; 1358 stack_top->last_avrule = NULL; 1359 stack_top->require_given = 0; 1360 next_decl_id++; 1361 return 0; 1362 } 1363 1364 static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack) 1365 { 1366 uint32_t i; 1367 if (stack == NULL) { 1368 return 0; 1369 } 1370 if (stack->type == 1) { 1371 scope_index_t *src_scope = &stack->decl->required; 1372 scope_index_t *dest_scope = &dest->required; 1373 for (i = 0; i < SYM_NUM; i++) { 1374 ebitmap_t *src_bitmap = &src_scope->scope[i]; 1375 ebitmap_t *dest_bitmap = &dest_scope->scope[i]; 1376 if (ebitmap_union(dest_bitmap, src_bitmap)) { 1377 yyerror("Out of memory!"); 1378 return -1; 1379 } 1380 } 1381 /* now copy class permissions */ 1382 if (src_scope->class_perms_len > dest_scope->class_perms_len) { 1383 ebitmap_t *new_map = 1384 realloc(dest_scope->class_perms_map, 1385 src_scope->class_perms_len * 1386 sizeof(*new_map)); 1387 if (new_map == NULL) { 1388 yyerror("Out of memory!"); 1389 return -1; 1390 } 1391 dest_scope->class_perms_map = new_map; 1392 for (i = dest_scope->class_perms_len; 1393 i < src_scope->class_perms_len; i++) { 1394 ebitmap_init(dest_scope->class_perms_map + i); 1395 } 1396 dest_scope->class_perms_len = 1397 src_scope->class_perms_len; 1398 } 1399 for (i = 0; i < src_scope->class_perms_len; i++) { 1400 ebitmap_t *src_bitmap = &src_scope->class_perms_map[i]; 1401 ebitmap_t *dest_bitmap = 1402 &dest_scope->class_perms_map[i]; 1403 if (ebitmap_union(dest_bitmap, src_bitmap)) { 1404 yyerror("Out of memory!"); 1405 return -1; 1406 } 1407 } 1408 } 1409 return copy_requirements(dest, stack->parent); 1410 } 1411 1412 /* During pass 1, check that at least one thing was required within 1413 * this block, for those places where a REQUIRED is necessary. During 1414 * pass 2, have this block inherit its parents' requirements. Return 1415 * 0 on success, -1 on failure. */ 1416 int end_avrule_block(int pass) 1417 { 1418 avrule_decl_t *decl = stack_top->decl; 1419 assert(stack_top->type == 1); 1420 if (pass == 2) { 1421 /* this avrule_decl inherits all of its parents' 1422 * requirements */ 1423 if (copy_requirements(decl, stack_top->parent) == -1) { 1424 return -1; 1425 } 1426 return 0; 1427 } 1428 if (!stack_top->in_else && !stack_top->require_given) { 1429 if (policydbp->policy_type == POLICY_BASE 1430 && stack_top->parent != NULL) { 1431 /* if this is base no require should be in the global block */ 1432 return 0; 1433 } else { 1434 /* non-ELSE branches must have at least one thing required */ 1435 yyerror("This block has no require section."); 1436 return -1; 1437 } 1438 } 1439 return 0; 1440 } 1441 1442 /* Push a new scope on to the stack and update the 'last' pointer. 1443 * Return 0 on success, -1 if out * of memory. */ 1444 static int push_stack(int stack_type, ...) 1445 { 1446 scope_stack_t *s = calloc(1, sizeof(*s)); 1447 va_list ap; 1448 if (s == NULL) { 1449 return -1; 1450 } 1451 va_start(ap, stack_type); 1452 switch (s->type = stack_type) { 1453 case 1:{ 1454 s->u.avrule = va_arg(ap, avrule_block_t *); 1455 s->decl = va_arg(ap, avrule_decl_t *); 1456 break; 1457 } 1458 case 2:{ 1459 s->u.cond_list = va_arg(ap, cond_list_t *); 1460 break; 1461 } 1462 default: 1463 /* invalid stack type given */ 1464 assert(0); 1465 } 1466 va_end(ap); 1467 s->parent = stack_top; 1468 s->child = NULL; 1469 stack_top = s; 1470 return 0; 1471 } 1472 1473 /* Pop off the most recently added from the stack. Update the 'last' 1474 * pointer. */ 1475 static void pop_stack(void) 1476 { 1477 scope_stack_t *parent; 1478 assert(stack_top != NULL); 1479 parent = stack_top->parent; 1480 if (parent != NULL) { 1481 parent->child = NULL; 1482 } 1483 free(stack_top); 1484 stack_top = parent; 1485 } 1486