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