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