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 return -1; 806 } 807 ret = 808 require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value, 809 &datum->s.value); 810 if (ret < 0) { 811 print_error_msg(ret, SYM_CLASSES); 812 free(class_id); 813 class_datum_destroy(datum); 814 return -1; 815 } 816 817 if (ret == 0) { 818 /* a new class was added; reindex everything */ 819 if (policydb_index_classes(policydbp)) { 820 yyerror("Out of memory!"); 821 return -1; 822 } 823 } else { 824 class_datum_destroy(datum); 825 datum = hashtab_search(policydbp->p_classes.table, class_id); 826 assert(datum); /* the class datum should have existed */ 827 free(class_id); 828 } 829 830 /* now add each of the permissions to this class's requirements */ 831 while ((perm_id = queue_remove(id_queue)) != NULL) { 832 int allocated = 0; 833 834 /* Is the permission already in the table? */ 835 perm = hashtab_search(datum->permissions.table, perm_id); 836 if (!perm && datum->comdatum) 837 perm = 838 hashtab_search(datum->comdatum->permissions.table, 839 perm_id); 840 if (perm) { 841 /* Yes, drop the name. */ 842 free(perm_id); 843 } else { 844 /* No - allocate and insert an entry for it. */ 845 if (policydbp->policy_type == POLICY_BASE) { 846 yyerror2 847 ("Base policy - require of permission %s without prior declaration.", 848 perm_id); 849 free(perm_id); 850 return -1; 851 } 852 allocated = 1; 853 if ((perm = malloc(sizeof(*perm))) == NULL) { 854 yyerror("Out of memory!"); 855 free(perm_id); 856 return -1; 857 } 858 memset(perm, 0, sizeof(*perm)); 859 ret = 860 hashtab_insert(datum->permissions.table, perm_id, 861 perm); 862 if (ret) { 863 yyerror("Out of memory!"); 864 free(perm_id); 865 free(perm); 866 return -1; 867 } 868 perm->s.value = datum->permissions.nprim + 1; 869 } 870 871 if (add_perm_to_class(perm->s.value, datum->s.value) == -1) { 872 yyerror("Out of memory!"); 873 return -1; 874 } 875 876 /* Update number of primitives if we allocated one. */ 877 if (allocated) 878 datum->permissions.nprim++; 879 } 880 return 0; 881 } 882 883 static int require_role_or_attribute(int pass, unsigned char isattr) 884 { 885 char *key = NULL; 886 role_datum_t *role = NULL; 887 int ret; 888 889 if (pass == 2) { 890 free(queue_remove(id_queue)); 891 return 0; 892 } 893 894 ret = create_role(SCOPE_REQ, isattr, &role, &key); 895 if (ret < 0) { 896 return -1; 897 } 898 899 free(key); 900 901 if (ret == 0) { 902 ret = ebitmap_set_bit(&role->dominates, role->s.value - 1, 1); 903 if (ret != 0) { 904 yyerror("Out of memory"); 905 return -1; 906 } 907 } else { 908 role_datum_destroy(role); 909 free(role); 910 } 911 912 return 0; 913 } 914 915 int require_role(int pass) 916 { 917 return require_role_or_attribute(pass, 0); 918 } 919 920 int require_attribute_role(int pass) 921 { 922 return require_role_or_attribute(pass, 1); 923 } 924 925 static int require_type_or_attribute(int pass, unsigned char isattr) 926 { 927 type_datum_t *type = NULL; 928 int ret; 929 930 if (pass == 2) { 931 free(queue_remove(id_queue)); 932 return 0; 933 } 934 935 ret = create_type(SCOPE_REQ, isattr, &type); 936 937 if (ret < 0) { 938 return -1; 939 } 940 941 return 0; 942 } 943 944 int require_type(int pass) 945 { 946 return require_type_or_attribute(pass, 0); 947 } 948 949 int require_attribute(int pass) 950 { 951 return require_type_or_attribute(pass, 1); 952 } 953 954 int require_user(int pass) 955 { 956 char *key = NULL; 957 user_datum_t *user = NULL; 958 int ret; 959 960 if (pass == 1) { 961 free(queue_remove(id_queue)); 962 return 0; 963 } 964 965 ret = create_user(SCOPE_REQ, &user, &key); 966 if (ret < 0) { 967 return -1; 968 } 969 970 free(key); 971 972 if (ret == 1) { 973 user_datum_destroy(user); 974 free(user); 975 } 976 977 return 0; 978 } 979 980 static int require_bool_tunable(int pass, int is_tunable) 981 { 982 char *id = queue_remove(id_queue); 983 cond_bool_datum_t *booldatum = NULL; 984 int retval; 985 if (pass == 2) { 986 free(id); 987 return 0; 988 } 989 if (id == NULL) { 990 yyerror("no boolean name"); 991 return -1; 992 } 993 if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) { 994 cond_destroy_bool(id, booldatum, NULL); 995 yyerror("Out of memory!"); 996 return -1; 997 } 998 if (is_tunable) 999 booldatum->flags |= COND_BOOL_FLAGS_TUNABLE; 1000 retval = 1001 require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum, 1002 &booldatum->s.value, &booldatum->s.value); 1003 if (retval != 0) { 1004 cond_destroy_bool(id, booldatum, NULL); 1005 if (retval < 0) { 1006 print_error_msg(retval, SYM_BOOLS); 1007 return -1; 1008 } 1009 } 1010 1011 return 0; 1012 } 1013 1014 int require_bool(int pass) 1015 { 1016 return require_bool_tunable(pass, 0); 1017 } 1018 1019 int require_tunable(int pass) 1020 { 1021 return require_bool_tunable(pass, 1); 1022 } 1023 1024 int require_sens(int pass) 1025 { 1026 char *id = queue_remove(id_queue); 1027 level_datum_t *level = NULL; 1028 int retval; 1029 if (pass == 2) { 1030 free(id); 1031 return 0; 1032 } 1033 if (!id) { 1034 yyerror("no sensitivity name"); 1035 return -1; 1036 } 1037 level = malloc(sizeof(level_datum_t)); 1038 if (!level) { 1039 free(id); 1040 yyerror("Out of memory!"); 1041 return -1; 1042 } 1043 level_datum_init(level); 1044 level->level = malloc(sizeof(mls_level_t)); 1045 if (!level->level) { 1046 free(id); 1047 level_datum_destroy(level); 1048 free(level); 1049 yyerror("Out of memory!"); 1050 return -1; 1051 } 1052 mls_level_init(level->level); 1053 retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level, 1054 &level->level->sens, &level->level->sens); 1055 if (retval != 0) { 1056 free(id); 1057 mls_level_destroy(level->level); 1058 free(level->level); 1059 level_datum_destroy(level); 1060 free(level); 1061 if (retval < 0) { 1062 print_error_msg(retval, SYM_LEVELS); 1063 return -1; 1064 } 1065 } 1066 1067 return 0; 1068 } 1069 1070 int require_cat(int pass) 1071 { 1072 char *id = queue_remove(id_queue); 1073 cat_datum_t *cat = NULL; 1074 int retval; 1075 if (pass == 2) { 1076 free(id); 1077 return 0; 1078 } 1079 if (!id) { 1080 yyerror("no category name"); 1081 return -1; 1082 } 1083 cat = malloc(sizeof(cat_datum_t)); 1084 if (!cat) { 1085 free(id); 1086 yyerror("Out of memory!"); 1087 return -1; 1088 } 1089 cat_datum_init(cat); 1090 1091 retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat, 1092 &cat->s.value, &cat->s.value); 1093 if (retval != 0) { 1094 free(id); 1095 cat_datum_destroy(cat); 1096 free(cat); 1097 if (retval < 0) { 1098 print_error_msg(retval, SYM_CATS); 1099 return -1; 1100 } 1101 } 1102 1103 return 0; 1104 } 1105 1106 static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) 1107 { 1108 uint32_t i; 1109 if (stack == NULL) { 1110 return 0; /* no matching scope found */ 1111 } 1112 if (stack->type == 1) { 1113 avrule_decl_t *decl = stack->decl; 1114 for (i = 0; i < scope->decl_ids_len; i++) { 1115 if (scope->decl_ids[i] == decl->decl_id) { 1116 return 1; 1117 } 1118 } 1119 } else { 1120 /* note that conditionals can't declare or require 1121 * symbols, so skip this level */ 1122 } 1123 1124 /* not within scope of this stack, so try its parent */ 1125 return is_scope_in_stack(scope, stack->parent); 1126 } 1127 1128 int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id) 1129 { 1130 scope_datum_t *scope = 1131 (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type]. 1132 table, id); 1133 if (scope == NULL) { 1134 return 1; /* id is not known, so return success */ 1135 } 1136 return is_scope_in_stack(scope, stack_top); 1137 } 1138 1139 static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value, 1140 scope_index_t * scope) 1141 { 1142 if (class_value > scope->class_perms_len) { 1143 return 1; 1144 } 1145 if (ebitmap_get_bit(scope->class_perms_map + class_value - 1, 1146 perm_value - 1)) { 1147 return 1; 1148 } 1149 return 0; 1150 } 1151 1152 static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value, 1153 scope_stack_t * stack) 1154 { 1155 if (stack == NULL) { 1156 return 0; /* no matching scope found */ 1157 } 1158 if (stack->type == 1) { 1159 avrule_decl_t *decl = stack->decl; 1160 if (is_perm_in_scope_index 1161 (perm_value, class_value, &decl->required) 1162 || is_perm_in_scope_index(perm_value, class_value, 1163 &decl->declared)) { 1164 return 1; 1165 } 1166 } else { 1167 /* note that conditionals can't declare or require 1168 * symbols, so skip this level */ 1169 } 1170 1171 /* not within scope of this stack, so try its parent */ 1172 return is_perm_in_stack(perm_value, class_value, stack->parent); 1173 } 1174 1175 int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id) 1176 { 1177 class_datum_t *cladatum = 1178 (class_datum_t *) hashtab_search(policydbp->p_classes.table, 1179 class_id); 1180 perm_datum_t *perdatum; 1181 if (cladatum == NULL) { 1182 return 1; 1183 } 1184 perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table, 1185 perm_id); 1186 if (perdatum == NULL) { 1187 return 1; 1188 } 1189 return is_perm_in_stack(perdatum->s.value, cladatum->s.value, 1190 stack_top); 1191 } 1192 1193 cond_list_t *get_current_cond_list(cond_list_t * cond) 1194 { 1195 /* FIX ME: do something different here if in a nested 1196 * conditional? */ 1197 avrule_decl_t *decl = stack_top->decl; 1198 return get_decl_cond_list(policydbp, decl, cond); 1199 } 1200 1201 /* Append the new conditional node to the existing ones. During 1202 * expansion the list will be reversed -- i.e., the last AV rule will 1203 * be the first one listed in the policy. This matches the behavior 1204 * of the upstream compiler. */ 1205 void append_cond_list(cond_list_t * cond) 1206 { 1207 cond_list_t *old_cond = get_current_cond_list(cond); 1208 avrule_t *tmp; 1209 assert(old_cond != NULL); /* probably out of memory */ 1210 if (old_cond->avtrue_list == NULL) { 1211 old_cond->avtrue_list = cond->avtrue_list; 1212 } else { 1213 for (tmp = old_cond->avtrue_list; tmp->next != NULL; 1214 tmp = tmp->next) ; 1215 tmp->next = cond->avtrue_list; 1216 } 1217 if (old_cond->avfalse_list == NULL) { 1218 old_cond->avfalse_list = cond->avfalse_list; 1219 } else { 1220 for (tmp = old_cond->avfalse_list; tmp->next != NULL; 1221 tmp = tmp->next) ; 1222 tmp->next = cond->avfalse_list; 1223 } 1224 1225 old_cond->flags |= cond->flags; 1226 } 1227 1228 void append_avrule(avrule_t * avrule) 1229 { 1230 avrule_decl_t *decl = stack_top->decl; 1231 1232 /* currently avrules follow a completely different code path 1233 * for handling avrules and compute types 1234 * (define_cond_avrule_te_avtab, define_cond_compute_type); 1235 * therefore there ought never be a conditional on top of the 1236 * scope stack */ 1237 assert(stack_top->type == 1); 1238 1239 if (stack_top->last_avrule == NULL) { 1240 decl->avrules = avrule; 1241 } else { 1242 stack_top->last_avrule->next = avrule; 1243 } 1244 stack_top->last_avrule = avrule; 1245 } 1246 1247 /* this doesn't actually append, but really prepends it */ 1248 void append_role_trans(role_trans_rule_t * role_tr_rules) 1249 { 1250 avrule_decl_t *decl = stack_top->decl; 1251 1252 /* role transitions are not allowed within conditionals */ 1253 assert(stack_top->type == 1); 1254 1255 role_tr_rules->next = decl->role_tr_rules; 1256 decl->role_tr_rules = role_tr_rules; 1257 } 1258 1259 /* this doesn't actually append, but really prepends it */ 1260 void append_role_allow(role_allow_rule_t * role_allow_rules) 1261 { 1262 avrule_decl_t *decl = stack_top->decl; 1263 1264 /* role allows are not allowed within conditionals */ 1265 assert(stack_top->type == 1); 1266 1267 role_allow_rules->next = decl->role_allow_rules; 1268 decl->role_allow_rules = role_allow_rules; 1269 } 1270 1271 /* this doesn't actually append, but really prepends it */ 1272 void append_filename_trans(filename_trans_rule_t * filename_trans_rules) 1273 { 1274 avrule_decl_t *decl = stack_top->decl; 1275 1276 /* filename transitions are not allowed within conditionals */ 1277 assert(stack_top->type == 1); 1278 1279 filename_trans_rules->next = decl->filename_trans_rules; 1280 decl->filename_trans_rules = filename_trans_rules; 1281 } 1282 1283 /* this doesn't actually append, but really prepends it */ 1284 void append_range_trans(range_trans_rule_t * range_tr_rules) 1285 { 1286 avrule_decl_t *decl = stack_top->decl; 1287 1288 /* range transitions are not allowed within conditionals */ 1289 assert(stack_top->type == 1); 1290 1291 range_tr_rules->next = decl->range_tr_rules; 1292 decl->range_tr_rules = range_tr_rules; 1293 } 1294 1295 int begin_optional(int pass) 1296 { 1297 avrule_block_t *block = NULL; 1298 avrule_decl_t *decl; 1299 if (pass == 1) { 1300 /* allocate a new avrule block for this optional block */ 1301 if ((block = avrule_block_create()) == NULL || 1302 (decl = avrule_decl_create(next_decl_id)) == NULL) { 1303 goto cleanup; 1304 } 1305 block->flags |= AVRULE_OPTIONAL; 1306 block->branch_list = decl; 1307 last_block->next = block; 1308 } else { 1309 /* select the next block from the chain built during pass 1 */ 1310 block = last_block->next; 1311 assert(block != NULL && 1312 block->branch_list != NULL && 1313 block->branch_list->decl_id == next_decl_id); 1314 decl = block->branch_list; 1315 } 1316 if (push_stack(1, block, decl) == -1) { 1317 goto cleanup; 1318 } 1319 stack_top->last_avrule = NULL; 1320 last_block = block; 1321 next_decl_id++; 1322 return 0; 1323 cleanup: 1324 yyerror("Out of memory!"); 1325 avrule_block_destroy(block); 1326 return -1; 1327 } 1328 1329 int end_optional(int pass __attribute__ ((unused))) 1330 { 1331 /* once nested conditionals are allowed, do the stack unfolding here */ 1332 pop_stack(); 1333 return 0; 1334 } 1335 1336 int begin_optional_else(int pass) 1337 { 1338 avrule_decl_t *decl; 1339 assert(stack_top->type == 1 && stack_top->in_else == 0); 1340 if (pass == 1) { 1341 /* allocate a new declaration and add it to the 1342 * current chain */ 1343 if ((decl = avrule_decl_create(next_decl_id)) == NULL) { 1344 yyerror("Out of memory!"); 1345 return -1; 1346 } 1347 stack_top->decl->next = decl; 1348 } else { 1349 /* pick the (hopefully last) declaration of this 1350 avrule block, built from pass 1 */ 1351 decl = stack_top->decl->next; 1352 assert(decl != NULL && 1353 decl->next == NULL && decl->decl_id == next_decl_id); 1354 } 1355 stack_top->in_else = 1; 1356 stack_top->decl = decl; 1357 stack_top->last_avrule = NULL; 1358 stack_top->require_given = 0; 1359 next_decl_id++; 1360 return 0; 1361 } 1362 1363 static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack) 1364 { 1365 uint32_t i; 1366 if (stack == NULL) { 1367 return 0; 1368 } 1369 if (stack->type == 1) { 1370 scope_index_t *src_scope = &stack->decl->required; 1371 scope_index_t *dest_scope = &dest->required; 1372 for (i = 0; i < SYM_NUM; i++) { 1373 ebitmap_t *src_bitmap = &src_scope->scope[i]; 1374 ebitmap_t *dest_bitmap = &dest_scope->scope[i]; 1375 if (ebitmap_union(dest_bitmap, src_bitmap)) { 1376 yyerror("Out of memory!"); 1377 return -1; 1378 } 1379 } 1380 /* now copy class permissions */ 1381 if (src_scope->class_perms_len > dest_scope->class_perms_len) { 1382 ebitmap_t *new_map = 1383 realloc(dest_scope->class_perms_map, 1384 src_scope->class_perms_len * 1385 sizeof(*new_map)); 1386 if (new_map == NULL) { 1387 yyerror("Out of memory!"); 1388 return -1; 1389 } 1390 dest_scope->class_perms_map = new_map; 1391 for (i = dest_scope->class_perms_len; 1392 i < src_scope->class_perms_len; i++) { 1393 ebitmap_init(dest_scope->class_perms_map + i); 1394 } 1395 dest_scope->class_perms_len = 1396 src_scope->class_perms_len; 1397 } 1398 for (i = 0; i < src_scope->class_perms_len; i++) { 1399 ebitmap_t *src_bitmap = &src_scope->class_perms_map[i]; 1400 ebitmap_t *dest_bitmap = 1401 &dest_scope->class_perms_map[i]; 1402 if (ebitmap_union(dest_bitmap, src_bitmap)) { 1403 yyerror("Out of memory!"); 1404 return -1; 1405 } 1406 } 1407 } 1408 return copy_requirements(dest, stack->parent); 1409 } 1410 1411 /* During pass 1, check that at least one thing was required within 1412 * this block, for those places where a REQUIRED is necessary. During 1413 * pass 2, have this block inherit its parents' requirements. Return 1414 * 0 on success, -1 on failure. */ 1415 int end_avrule_block(int pass) 1416 { 1417 avrule_decl_t *decl = stack_top->decl; 1418 assert(stack_top->type == 1); 1419 if (pass == 2) { 1420 /* this avrule_decl inherits all of its parents' 1421 * requirements */ 1422 if (copy_requirements(decl, stack_top->parent) == -1) { 1423 return -1; 1424 } 1425 return 0; 1426 } 1427 if (!stack_top->in_else && !stack_top->require_given) { 1428 if (policydbp->policy_type == POLICY_BASE 1429 && stack_top->parent != NULL) { 1430 /* if this is base no require should be in the global block */ 1431 return 0; 1432 } else { 1433 /* non-ELSE branches must have at least one thing required */ 1434 yyerror("This block has no require section."); 1435 return -1; 1436 } 1437 } 1438 return 0; 1439 } 1440 1441 /* Push a new scope on to the stack and update the 'last' pointer. 1442 * Return 0 on success, -1 if out * of memory. */ 1443 static int push_stack(int stack_type, ...) 1444 { 1445 scope_stack_t *s = calloc(1, sizeof(*s)); 1446 va_list ap; 1447 if (s == NULL) { 1448 return -1; 1449 } 1450 va_start(ap, stack_type); 1451 switch (s->type = stack_type) { 1452 case 1:{ 1453 s->u.avrule = va_arg(ap, avrule_block_t *); 1454 s->decl = va_arg(ap, avrule_decl_t *); 1455 break; 1456 } 1457 case 2:{ 1458 s->u.cond_list = va_arg(ap, cond_list_t *); 1459 break; 1460 } 1461 default: 1462 /* invalid stack type given */ 1463 assert(0); 1464 } 1465 va_end(ap); 1466 s->parent = stack_top; 1467 s->child = NULL; 1468 stack_top = s; 1469 return 0; 1470 } 1471 1472 /* Pop off the most recently added from the stack. Update the 'last' 1473 * pointer. */ 1474 static void pop_stack(void) 1475 { 1476 scope_stack_t *parent; 1477 assert(stack_top != NULL); 1478 parent = stack_top->parent; 1479 if (parent != NULL) { 1480 parent->child = NULL; 1481 } 1482 free(stack_top); 1483 stack_top = parent; 1484 } 1485