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