module_compiler.c

Go to the documentation of this file.
00001 /**
00002  *  @file
00003  *
00004  *  This file is a copy of module_compiler.c from NSA's CVS repository.
00005  *
00006  * Author : Joshua Brindle <jbrindle@tresys.com>
00007  *          Karl MacMillan <kmacmillan@tresys.com>
00008  *          Jason Tang     <jtang@tresys.com>
00009  *      Added support for binary policy modules
00010  *
00011  * Copyright (C) 2004 - 2005 Tresys Technology, LLC
00012  *      This program is free software; you can redistribute it and/or modify
00013  *      it under the terms of the GNU General Public License as published by
00014  *      the Free Software Foundation, version 2.
00015  */
00016 
00017 #include <config.h>
00018 
00019 #include <assert.h>
00020 #include <stdarg.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 
00024 #include <sepol/policydb/policydb.h>
00025 #include <sepol/policydb/avrule_block.h>
00026 #include <sepol/policydb/conditional.h>
00027 
00028 #include "queue.h"
00029 #include "module_compiler.h"
00030 
00031 union stack_item_u
00032 {
00033         avrule_block_t *avrule;
00034         cond_list_t *cond_list;
00035 };
00036 
00037 typedef struct scope_stack
00038 {
00039         union stack_item_u u;
00040         int type;                      /* for above union: 1 = avrule block, 2 = conditional */
00041         avrule_decl_t *decl;           /* if in an avrule block, which
00042                                         * declaration is current */
00043         avrule_t *last_avrule;
00044         int in_else;                   /* if in an avrule block, within ELSE branch */
00045         int require_given;             /* 1 if this block had at least one require */
00046         struct scope_stack *parent, *child;
00047 } scope_stack_t;
00048 
00049 extern policydb_t *policydbp;
00050 extern queue_t id_queue;
00051 extern int yyerror(char *msg);
00052 extern void yyerror2(char *fmt, ...);
00053 
00054 static int push_stack(int stack_type, ...);
00055 static void pop_stack(void);
00056 
00057 /* keep track of the last item added to the stack */
00058 static scope_stack_t *stack_top = NULL;
00059 static avrule_block_t *last_block;
00060 static uint32_t next_decl_id = 1;
00061 
00062 int define_policy(int pass, int module_header_given)
00063 {
00064         char *id;
00065 
00066         if (module_header_given) {
00067                 if (policydbp->policy_type != POLICY_MOD) {
00068                         yyerror("Module specification found while not building a policy module.\n");
00069                         return -1;
00070                 }
00071 
00072                 if (pass == 2) {
00073                         while ((id = queue_remove(id_queue)) != NULL)
00074                                 free(id);
00075                 } else {
00076                         id = (char *)queue_remove(id_queue);
00077                         if (!id) {
00078                                 yyerror("no module name");
00079                                 return -1;
00080                         }
00081                         policydbp->name = id;
00082                         if ((policydbp->version = queue_remove(id_queue)) == NULL) {
00083                                 yyerror("Expected a module version but none was found.");
00084                                 return -1;
00085                         }
00086                 }
00087         } else {
00088                 if (policydbp->policy_type == POLICY_MOD) {
00089                         yyerror("Building a policy module, but no module specification found.\n");
00090                         return -1;
00091                 }
00092         }
00093         /* the first declaration within the global avrule
00094          * block will always have an id of 1 */
00095         next_decl_id = 2;
00096 
00097         /* reset the scoping stack */
00098         while (stack_top != NULL) {
00099                 pop_stack();
00100         }
00101         if (push_stack(1, policydbp->global, policydbp->global->branch_list) == -1) {
00102                 return -1;
00103         }
00104         last_block = policydbp->global;
00105         return 0;
00106 }
00107 
00108 /* Given the current parse stack, returns 1 if a declaration would be
00109  * allowed here or 0 if not.  For example, declarations are not
00110  * allowed in conditionals, so if there are any conditionals in the
00111  * current scope stack then this would return a 0.
00112  */
00113 static int is_declaration_allowed(void)
00114 {
00115         if (stack_top->type != 1 || stack_top->in_else) {
00116                 return 0;
00117         }
00118         return 1;
00119 }
00120 
00121 /* Attempt to declare a symbol within the current declaration.  If
00122  * currently within a non-conditional and in a non-else branch then
00123  * insert the symbol, return 0 on success if symbol was undeclared.
00124  * For roles and users, it is legal to have multiple declarations; as
00125  * such return 1 to indicate that caller must free() the datum because
00126  * it was not added.  If symbols may not be declared here return -1.
00127  * For duplicate declarations return -2.  For all else, including out
00128  * of memory, return -3.  Note that dest_value and datum_value might
00129  * not be restricted pointers. */
00130 int declare_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, uint32_t * dest_value, uint32_t * datum_value)
00131 {
00132         avrule_decl_t *decl = stack_top->decl;
00133         int retval;
00134 
00135         /* first check that symbols may be declared here */
00136         if (!is_declaration_allowed()) {
00137                 return -1;
00138         }
00139         retval = symtab_insert(policydbp, symbol_type, key, datum, SCOPE_DECL, decl->decl_id, dest_value);
00140         if (retval == 1) {
00141                 symtab_datum_t *s = (symtab_datum_t *) hashtab_search(policydbp->symtab[symbol_type].table,
00142                                                                       key);
00143                 assert(s != NULL);
00144 
00145                 if (symbol_type == SYM_LEVELS) {
00146                         *dest_value = ((level_datum_t *) s)->level->sens;
00147                 } else {
00148                         *dest_value = s->value;
00149                 }
00150         } else if (retval == -2) {
00151                 return -2;
00152         } else if (retval < 0) {
00153                 return -3;
00154         } else {                       /* fall through possible if retval is 0 */
00155         }
00156         if (datum_value != NULL) {
00157                 if (ebitmap_set_bit(decl->declared.scope + symbol_type, *datum_value - 1, 1)) {
00158                         return -3;
00159                 }
00160         }
00161         return retval;
00162 }
00163 
00164 role_datum_t *declare_role(void)
00165 {
00166         char *id = queue_remove(id_queue), *dest_id = NULL;
00167         role_datum_t *role = NULL, *dest_role = NULL;
00168         int retval;
00169         uint32_t value;
00170 
00171         if (id == NULL) {
00172                 yyerror("no role name");
00173                 return NULL;
00174         }
00175         if ((role = (role_datum_t *) malloc(sizeof(*role))) == NULL) {
00176                 yyerror("Out of memory!");
00177                 free(id);
00178                 return NULL;
00179         }
00180         role_datum_init(role);
00181 
00182         retval = declare_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &value, &value);
00183         if (retval == 0) {
00184                 role->s.value = value;
00185                 if ((dest_id = strdup(id)) == NULL) {
00186                         yyerror("Out of memory!");
00187                         return NULL;
00188                 }
00189         } else {
00190                 /* this role was already declared in this module, or error */
00191                 dest_id = id;
00192                 role_datum_destroy(role);
00193                 free(role);
00194         }
00195         if (retval == 0 || retval == 1) {
00196                 /* create a new role_datum_t for this decl, if necessary */
00197                 hashtab_t roles_tab;
00198                 assert(stack_top->type == 1);
00199                 if (stack_top->parent == NULL) {
00200                         /* in parent, so use global symbol table */
00201                         roles_tab = policydbp->p_roles.table;
00202                 } else {
00203                         roles_tab = stack_top->decl->p_roles.table;
00204                 }
00205                 dest_role = (role_datum_t *) hashtab_search(roles_tab, dest_id);
00206                 if (dest_role == NULL) {
00207                         if ((dest_role = (role_datum_t *) malloc(sizeof(*dest_role))) == NULL) {
00208                                 yyerror("Out of memory!");
00209                                 free(dest_id);
00210                                 return NULL;
00211                         }
00212                         role_datum_init(dest_role);
00213                         dest_role->s.value = value;
00214                         if (hashtab_insert(roles_tab, dest_id, dest_role)) {
00215                                 yyerror("Out of memory!");
00216                                 free(dest_id);
00217                                 role_datum_destroy(dest_role);
00218                                 free(dest_role);
00219                                 return NULL;
00220                         }
00221                 } else {
00222                         free(dest_id);
00223                 }
00224         } else {
00225                 free(dest_id);
00226         }
00227         switch (retval) {
00228         case -3:
00229         {
00230                 yyerror("Out of memory!");
00231                 return NULL;
00232         }
00233         case -2:
00234         {
00235                 yyerror("duplicate declaration of role");
00236                 return NULL;
00237         }
00238         case -1:
00239         {
00240                 yyerror("could not declare role here");
00241                 return NULL;
00242         }
00243         case 0:
00244         {
00245                 if (ebitmap_set_bit(&dest_role->dominates, role->s.value - 1, 1)) {
00246                         yyerror("out of memory");
00247                         return NULL;
00248                 }
00249                 return dest_role;
00250         }
00251         case 1:
00252         {
00253                 return dest_role;      /* role already declared for this block */
00254         }
00255         default:
00256         {
00257                 assert(0);             /* should never get here */
00258         }
00259         }
00260 }
00261 
00262 type_datum_t *declare_type(unsigned char primary, unsigned char isattr)
00263 {
00264         char *id;
00265         type_datum_t *typdatum;
00266         int retval;
00267         uint32_t value = 0;
00268 
00269         id = (char *)queue_remove(id_queue);
00270         if (!id) {
00271                 yyerror("no type/attribute name?");
00272                 return NULL;
00273         }
00274         if (strcmp(id, "self") == 0) {
00275                 yyerror("'self' is a reserved type name and may not be declared.");
00276                 free(id);
00277                 return NULL;
00278         }
00279 
00280         typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
00281         if (!typdatum) {
00282                 yyerror("Out of memory!");
00283                 free(id);
00284                 return NULL;
00285         }
00286         type_datum_init(typdatum);
00287         typdatum->primary = primary;
00288         typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
00289 
00290         retval = declare_symbol(SYM_TYPES, id, typdatum, &value, &value);
00291         if (retval == 0 || retval == 1) {
00292                 if (typdatum->primary) {
00293                         typdatum->s.value = value;
00294                 }
00295         } else {
00296                 /* error occurred (can't have duplicate type declarations) */
00297                 free(id);
00298                 type_datum_destroy(typdatum);
00299                 free(typdatum);
00300         }
00301         switch (retval) {
00302         case -3:
00303         {
00304                 yyerror("Out of memory!");
00305                 return NULL;
00306         }
00307         case -2:
00308         {
00309                 yyerror2("duplicate declaration of type/attribute");
00310                 return NULL;
00311         }
00312         case -1:
00313         {
00314                 yyerror("could not declare type/attribute here");
00315                 return NULL;
00316         }
00317         case 0:
00318         case 1:
00319         {
00320                 return typdatum;
00321         }
00322         default:
00323         {
00324                 assert(0);             /* should never get here */
00325         }
00326         }
00327 }
00328 
00329 user_datum_t *declare_user(void)
00330 {
00331         char *id = queue_remove(id_queue), *dest_id = NULL;
00332         user_datum_t *user = NULL, *dest_user = NULL;
00333         int retval;
00334         uint32_t value = 0;
00335 
00336         if (id == NULL) {
00337                 yyerror("no user name");
00338                 return NULL;
00339         }
00340         if ((user = (user_datum_t *) malloc(sizeof(*user))) == NULL) {
00341                 yyerror("Out of memory!");
00342                 free(id);
00343                 return NULL;
00344         }
00345         user_datum_init(user);
00346 
00347         retval = declare_symbol(SYM_USERS, id, (hashtab_datum_t *) user, &value, &value);
00348 
00349         if (retval == 0) {
00350                 user->s.value = value;
00351                 if ((dest_id = strdup(id)) == NULL) {
00352                         yyerror("Out of memory!");
00353                         return NULL;
00354                 }
00355         } else {
00356                 /* this user was already declared in this module, or error */
00357                 dest_id = id;
00358                 user_datum_destroy(user);
00359                 free(user);
00360         }
00361         if (retval == 0 || retval == 1) {
00362                 /* create a new user_datum_t for this decl, if necessary */
00363                 hashtab_t users_tab;
00364                 assert(stack_top->type == 1);
00365                 if (stack_top->parent == NULL) {
00366                         /* in parent, so use global symbol table */
00367                         users_tab = policydbp->p_users.table;
00368                 } else {
00369                         users_tab = stack_top->decl->p_users.table;
00370                 }
00371                 dest_user = (user_datum_t *) hashtab_search(users_tab, dest_id);
00372                 if (dest_user == NULL) {
00373                         if ((dest_user = (user_datum_t *) malloc(sizeof(*dest_user))) == NULL) {
00374                                 yyerror("Out of memory!");
00375                                 free(dest_id);
00376                                 return NULL;
00377                         }
00378                         user_datum_init(dest_user);
00379                         dest_user->s.value = value;
00380                         if (hashtab_insert(users_tab, dest_id, dest_user)) {
00381                                 yyerror("Out of memory!");
00382                                 free(dest_id);
00383                                 user_datum_destroy(dest_user);
00384                                 free(dest_user);
00385                                 return NULL;
00386                         }
00387                 } else {
00388                         free(dest_id);
00389                 }
00390         } else {
00391                 free(dest_id);
00392         }
00393         switch (retval) {
00394         case -3:
00395         {
00396                 yyerror("Out of memory!");
00397                 return NULL;
00398         }
00399         case -2:
00400         {
00401                 yyerror("duplicate declaration of user");
00402                 return NULL;
00403         }
00404         case -1:
00405         {
00406                 yyerror("could not declare user here");
00407                 return NULL;
00408         }
00409         case 0:
00410         {
00411                 return dest_user;
00412         }
00413         case 1:
00414         {
00415                 return dest_user;      /* user already declared for this block */
00416         }
00417         default:
00418         {
00419                 assert(0);             /* should never get here */
00420         }
00421         }
00422 }
00423 
00424 /* Return a type_datum_t for the local avrule_decl with the given ID.
00425  * If it does not exist, create one with the same value as 'value'.
00426  * This function assumes that the ID is within scope.  c.f.,
00427  * is_id_in_scope().
00428  *
00429  * NOTE: this function usurps ownership of id afterwards.  The caller
00430  * shall not reference it nor free() it afterwards.
00431  */
00432 type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr)
00433 {
00434         type_datum_t *dest_typdatum;
00435         hashtab_t types_tab;
00436         assert(stack_top->type == 1);
00437         if (stack_top->parent == NULL) {
00438                 /* in global, so use global symbol table */
00439                 types_tab = policydbp->p_types.table;
00440         } else {
00441                 types_tab = stack_top->decl->p_types.table;
00442         }
00443         dest_typdatum = hashtab_search(types_tab, id);
00444         if (!dest_typdatum) {
00445                 dest_typdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
00446                 if (dest_typdatum == NULL) {
00447                         free(id);
00448                         return NULL;
00449                 }
00450                 type_datum_init(dest_typdatum);
00451                 dest_typdatum->s.value = value;
00452                 dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
00453                 dest_typdatum->primary = 1;
00454                 if (hashtab_insert(types_tab, id, dest_typdatum)) {
00455                         free(id);
00456                         type_datum_destroy(dest_typdatum);
00457                         free(dest_typdatum);
00458                         return NULL;
00459                 }
00460 
00461         } else {
00462                 free(id);
00463                 if (dest_typdatum->flavor != isattr ? TYPE_ATTRIB : TYPE_TYPE) {
00464                         return NULL;
00465                 }
00466         }
00467         return dest_typdatum;
00468 }
00469 
00470 /* Given the current parse stack, returns 1 if a requirement would be
00471  * allowed here or 0 if not.  For example, the ELSE branch may never
00472  * have its own requirements.
00473  */
00474 static int is_require_allowed(void)
00475 {
00476         if (stack_top->type == 1 && !stack_top->in_else) {
00477                 return 1;
00478         }
00479         return 0;
00480 }
00481 
00482 /* Attempt to require a symbol within the current scope.  If currently
00483  * within an optional (and not its else branch), add the symbol to the
00484  * required list.  Return 0 on success, 1 if caller needs to free()
00485  * datum.  If symbols may not be declared here return -1.  For duplicate
00486  * declarations return -2.  For all else, including out of memory,
00487  * return -3..  Note that dest_value and datum_value might not be
00488  * restricted pointers.
00489  */
00490 int require_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, uint32_t * dest_value, uint32_t * datum_value)
00491 {
00492         avrule_decl_t *decl = stack_top->decl;
00493         int retval;
00494 
00495         /* first check that symbols may be required here */
00496         if (!is_require_allowed()) {
00497                 return -1;
00498         }
00499         retval = symtab_insert(policydbp, symbol_type, key, datum, SCOPE_REQ, decl->decl_id, dest_value);
00500         if (retval == 1) {
00501                 symtab_datum_t *s = (symtab_datum_t *) hashtab_search(policydbp->symtab[symbol_type].table,
00502                                                                       key);
00503                 assert(s != NULL);
00504 
00505                 if (symbol_type == SYM_LEVELS) {
00506                         *dest_value = ((level_datum_t *) s)->level->sens;
00507                 } else {
00508                         *dest_value = s->value;
00509                 }
00510         } else if (retval == -2) {
00511                 /* ignore require statements if that symbol was
00512                  * previously declared and is in current scope */
00513                 int prev_declaration_ok = 0;
00514                 if (is_id_in_scope(symbol_type, key)) {
00515                         if (symbol_type == SYM_TYPES) {
00516                                 /* check that previous symbol has same
00517                                  * type/attribute-ness */
00518                                 unsigned char new_isattr = ((type_datum_t *) datum)->flavor;
00519                                 type_datum_t *old_datum = (type_datum_t *) hashtab_search(policydbp->symtab[SYM_TYPES].table, key);
00520                                 assert(old_datum != NULL);
00521                                 unsigned char old_isattr = old_datum->flavor;
00522                                 prev_declaration_ok = (old_isattr == new_isattr ? 1 : 0);
00523                         } else {
00524                                 prev_declaration_ok = 1;
00525                         }
00526                 }
00527                 if (prev_declaration_ok) {
00528                         /* ignore this require statement because it
00529                          * was already declared within my scope */
00530                         stack_top->require_given = 1;
00531                         return 1;
00532                 } else {
00533                         /* previous declaration was not in scope or
00534                          * had a mismatched type/attribute, so
00535                          * generate an error */
00536                         return -2;
00537                 }
00538         } else if (retval < 0) {
00539                 return -3;
00540         } else {                       /* fall through possible if retval is 0 or 1 */
00541         }
00542         if (datum_value != NULL) {
00543                 if (ebitmap_set_bit(decl->required.scope + symbol_type, *datum_value - 1, 1)) {
00544                         return -3;
00545                 }
00546         }
00547         stack_top->require_given = 1;
00548         return retval;
00549 }
00550 
00551 int add_perm_to_class(uint32_t perm_value, uint32_t class_value)
00552 {
00553         avrule_decl_t *decl = stack_top->decl;
00554         scope_index_t *scope;
00555 
00556         assert(perm_value >= 1);
00557         assert(class_value >= 1);
00558         scope = &decl->required;
00559         if (class_value > scope->class_perms_len) {
00560                 int i;
00561                 ebitmap_t *new_map = realloc(scope->class_perms_map,
00562                                              class_value * sizeof(*new_map));
00563                 if (new_map == NULL) {
00564                         return -1;
00565                 }
00566                 scope->class_perms_map = new_map;
00567                 for (i = scope->class_perms_len; i < class_value; i++) {
00568                         ebitmap_init(scope->class_perms_map + i);
00569                 }
00570                 scope->class_perms_len = class_value;
00571         }
00572         if (ebitmap_set_bit(scope->class_perms_map + class_value - 1, perm_value - 1, 1)) {
00573                 return -1;
00574         }
00575         return 0;
00576 }
00577 
00578 static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused)))
00579 {
00580         if (key)
00581                 free(key);
00582         free(datum);
00583         return 0;
00584 }
00585 
00586 static void class_datum_destroy(class_datum_t * cladatum)
00587 {
00588         if (cladatum != NULL) {
00589                 hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
00590                 hashtab_destroy(cladatum->permissions.table);
00591                 free(cladatum);
00592         }
00593 }
00594 
00595 int require_class(int pass)
00596 {
00597         char *class_id = queue_remove(id_queue);
00598         char *perm_id = NULL;
00599         class_datum_t *datum = NULL;
00600         perm_datum_t *perm = NULL;
00601         int ret;
00602 
00603         if (pass == 2) {
00604                 free(class_id);
00605                 while ((perm_id = queue_remove(id_queue)) != NULL)
00606                         free(perm_id);
00607                 return 0;
00608         }
00609 
00610         /* first add the class if it is not already there */
00611         if (class_id == NULL) {
00612                 yyerror("no class name for class definition?");
00613                 return -1;
00614         }
00615 
00616         if ((datum = calloc(1, sizeof(*datum))) == NULL || symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
00617                 yyerror("Out of memory!");
00618                 goto cleanup;
00619         }
00620         ret = require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value, &datum->s.value);
00621         switch (ret) {
00622         case -3:
00623         {
00624                 yyerror("Out of memory!");
00625                 free(class_id);
00626                 class_datum_destroy(datum);
00627                 goto cleanup;
00628         }
00629         case -2:
00630         {
00631                 yyerror("duplicate declaration of class");
00632                 free(class_id);
00633                 class_datum_destroy(datum);
00634                 goto cleanup;
00635         }
00636         case -1:
00637         {
00638                 yyerror("could not require class here");
00639                 free(class_id);
00640                 class_datum_destroy(datum);
00641                 goto cleanup;
00642         }
00643         case 0:
00644         {
00645                 /* a new class was added; reindex everything */
00646                 if (policydb_index_classes(policydbp)) {
00647                         yyerror("Out of memory!");
00648                         goto cleanup;
00649                 }
00650                 break;
00651         }
00652         case 1:
00653         {
00654                 class_datum_destroy(datum);
00655                 datum = hashtab_search(policydbp->p_classes.table, class_id);
00656                 assert(datum);         /* the class datum should have existed */
00657                 free(class_id);
00658                 break;
00659         }
00660         default:
00661         {
00662                 assert(0);             /* should never get here */
00663         }
00664         }
00665 
00666         /* now add each of the permissions to this class's requirements */
00667         while ((perm_id = queue_remove(id_queue)) != NULL) {
00668                 int allocated = 0;
00669 
00670                 /* Is the permission already in the table? */
00671                 perm = hashtab_search(datum->permissions.table, perm_id);
00672                 if (!perm && datum->comdatum)
00673                         perm = hashtab_search(datum->comdatum->permissions.table, perm_id);
00674                 if (perm) {
00675                         /* Yes, drop the name. */
00676                         free(perm_id);
00677                 } else {
00678                         /* No - allocate and insert an entry for it. */
00679                         if (policydbp->policy_type == POLICY_BASE) {
00680                                 yyerror2("Base policy - require of permission %s without prior declaration.", perm_id);
00681                                 free(perm_id);
00682                                 goto cleanup;
00683                         }
00684                         allocated = 1;
00685                         if ((perm = malloc(sizeof(*perm))) == NULL) {
00686                                 yyerror("Out of memory!");
00687                                 free(perm_id);
00688                                 goto cleanup;
00689                         }
00690                         memset(perm, 0, sizeof(*perm));
00691                         ret = hashtab_insert(datum->permissions.table, perm_id, perm);
00692                         if (ret) {
00693                                 yyerror("Out of memory!");
00694                                 free(perm_id);
00695                                 free(perm);
00696                                 goto cleanup;
00697                         }
00698                         perm->s.value = datum->permissions.nprim + 1;
00699                 }
00700 
00701                 if (add_perm_to_class(perm->s.value, datum->s.value) == -1) {
00702                         yyerror("Out of memory!");
00703                         goto cleanup;
00704                 }
00705 
00706                 /* Update number of primitives if we allocated one. */
00707                 if (allocated)
00708                         datum->permissions.nprim++;
00709         }
00710         return 0;
00711       cleanup:
00712         return -1;
00713 }
00714 
00715 int require_role(int pass)
00716 {
00717         char *id = queue_remove(id_queue);
00718         role_datum_t *role = NULL;
00719         int retval;
00720         if (pass == 2) {
00721                 free(id);
00722                 return 0;
00723         }
00724         if (id == NULL) {
00725                 yyerror("no role name");
00726                 return -1;
00727         }
00728         if ((role = malloc(sizeof(*role))) == NULL) {
00729                 free(id);
00730                 yyerror("Out of memory!");
00731                 return -1;
00732         }
00733         role_datum_init(role);
00734         retval = require_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &role->s.value, &role->s.value);
00735         if (retval != 0) {
00736                 free(id);
00737                 role_datum_destroy(role);
00738                 free(role);
00739         }
00740         switch (retval) {
00741         case -3:
00742         {
00743                 yyerror("Out of memory!");
00744                 return -1;
00745         }
00746         case -2:
00747         {
00748                 yyerror("duplicate declaration of role");
00749                 return -1;
00750         }
00751         case -1:
00752         {
00753                 yyerror("could not require role here");
00754                 return -1;
00755         }
00756         case 0:
00757         {
00758                 /* all roles dominate themselves */
00759                 if (ebitmap_set_bit(&role->dominates, role->s.value - 1, 1)) {
00760                         yyerror("Out of memory");
00761                         return -1;
00762                 }
00763                 return 0;
00764         }
00765         case 1:
00766         {
00767                 return 0;              /* role already required */
00768         }
00769         default:
00770         {
00771                 assert(0);             /* should never get here */
00772         }
00773         }
00774 }
00775 
00776 static int require_type_or_attribute(int pass, unsigned char isattr)
00777 {
00778         char *id = queue_remove(id_queue);
00779         type_datum_t *type = NULL;
00780         int retval;
00781         if (pass == 2) {
00782                 free(id);
00783                 return 0;
00784         }
00785         if (id == NULL) {
00786                 yyerror("no type name");
00787                 return -1;
00788         }
00789         if ((type = malloc(sizeof(*type))) == NULL) {
00790                 free(id);
00791                 yyerror("Out of memory!");
00792                 return -1;
00793         }
00794         type_datum_init(type);
00795         type->primary = 1;
00796         type->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
00797         retval = require_symbol(SYM_TYPES, id, (hashtab_datum_t *) type, &type->s.value, &type->s.value);
00798         if (retval != 0) {
00799                 free(id);
00800                 free(type);
00801         }
00802         switch (retval) {
00803         case -3:
00804         {
00805                 yyerror("Out of memory!");
00806                 return -1;
00807         }
00808         case -2:
00809         {
00810                 yyerror("duplicate declaration of type/attribute");
00811                 return -1;
00812         }
00813         case -1:
00814         {
00815                 yyerror("could not require type/attribute here");
00816                 return -1;
00817         }
00818         case 0:
00819         {
00820                 return 0;
00821         }
00822         case 1:
00823         {
00824                 return 0;              /* type already required */
00825         }
00826         default:
00827         {
00828                 assert(0);             /* should never get here */
00829         }
00830         }
00831 }
00832 
00833 int require_type(int pass)
00834 {
00835         return require_type_or_attribute(pass, 0);
00836 }
00837 
00838 int require_attribute(int pass)
00839 {
00840         return require_type_or_attribute(pass, 1);
00841 }
00842 
00843 int require_user(int pass)
00844 {
00845         char *id = queue_remove(id_queue);
00846         user_datum_t *user = NULL;
00847         int retval;
00848         if (pass == 1) {
00849                 free(id);
00850                 return 0;
00851         }
00852         if (id == NULL) {
00853                 yyerror("no user name");
00854                 return -1;
00855         }
00856         if ((user = malloc(sizeof(*user))) == NULL) {
00857                 free(id);
00858                 yyerror("Out of memory!");
00859                 return -1;
00860         }
00861         user_datum_init(user);
00862         retval = require_symbol(SYM_USERS, id, (hashtab_datum_t *) user, &user->s.value, &user->s.value);
00863         if (retval != 0) {
00864                 free(id);
00865                 user_datum_destroy(user);
00866         }
00867         switch (retval) {
00868         case -3:
00869         {
00870                 yyerror("Out of memory!");
00871                 return -1;
00872         }
00873         case -2:
00874         {
00875                 yyerror("duplicate declaration of user");
00876                 return -1;
00877         }
00878         case -1:
00879         {
00880                 yyerror("could not require user here");
00881                 return -1;
00882         }
00883         case 0:
00884         {
00885                 return 0;
00886         }
00887         case 1:
00888         {
00889                 return 0;              /* user already required */
00890         }
00891         default:
00892         {
00893                 assert(0);             /* should never get here */
00894         }
00895         }
00896 }
00897 
00898 int require_bool(int pass)
00899 {
00900         char *id = queue_remove(id_queue);
00901         cond_bool_datum_t *booldatum = NULL;
00902         int retval;
00903         if (pass == 2) {
00904                 free(id);
00905                 return 0;
00906         }
00907         if (id == NULL) {
00908                 yyerror("no boolean name");
00909                 return -1;
00910         }
00911         if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) {
00912                 cond_destroy_bool(id, booldatum, NULL);
00913                 yyerror("Out of memory!");
00914                 return -1;
00915         }
00916         retval = require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum, &booldatum->s.value, &booldatum->s.value);
00917         if (retval != 0) {
00918                 cond_destroy_bool(id, booldatum, NULL);
00919         }
00920         switch (retval) {
00921         case -3:
00922         {
00923                 yyerror("Out of memory!");
00924                 return -1;
00925         }
00926         case -2:
00927         {
00928                 yyerror("duplicate declaration of boolean");
00929                 return -1;
00930         }
00931         case -1:
00932         {
00933                 yyerror("could not require boolean here");
00934                 return -1;
00935         }
00936         case 0:
00937         {
00938                 return 0;
00939         }
00940         case 1:
00941         {
00942                 return 0;              /* boolean already required */
00943         }
00944         default:
00945         {
00946                 assert(0);             /* should never get here */
00947         }
00948         }
00949 }
00950 
00951 int require_sens(int pass)
00952 {
00953         char *id = queue_remove(id_queue);
00954         level_datum_t *level = NULL;
00955         int retval;
00956         if (pass == 2) {
00957                 free(id);
00958                 return 0;
00959         }
00960         if (!id) {
00961                 yyerror("no sensitivity name");
00962                 return -1;
00963         }
00964         level = malloc(sizeof(level_datum_t));
00965         if (!level) {
00966                 free(id);
00967                 yyerror("Out of memory!");
00968                 return -1;
00969         }
00970         level_datum_init(level);
00971         level->level = malloc(sizeof(mls_level_t));
00972         if (!level->level) {
00973                 free(id);
00974                 level_datum_destroy(level);
00975                 free(level);
00976                 yyerror("Out of memory!");
00977                 return -1;
00978         }
00979         mls_level_init(level->level);
00980         retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level, &level->level->sens, &level->level->sens);
00981         if (retval != 0) {
00982                 free(id);
00983                 mls_level_destroy(level->level);
00984                 free(level->level);
00985                 level_datum_destroy(level);
00986                 free(level);
00987         }
00988         switch (retval) {
00989         case -3:
00990         {
00991                 yyerror("Out of memory!");
00992                 return -1;
00993         }
00994         case -2:
00995         {
00996                 yyerror("duplicate declaration of sensitivity");
00997                 return -1;
00998         }
00999         case -1:
01000         {
01001                 yyerror("could not require sensitivity here");
01002                 return -1;
01003         }
01004         case 0:
01005         {
01006                 return 0;
01007         }
01008         case 1:
01009         {
01010                 return 0;              /* sensitivity already required */
01011         }
01012         default:
01013         {
01014                 assert(0);             /* should never get here */
01015         }
01016         }
01017 }
01018 
01019 int require_cat(int pass)
01020 {
01021         char *id = queue_remove(id_queue);
01022         cat_datum_t *cat = NULL;
01023         int retval;
01024         if (pass == 2) {
01025                 free(id);
01026                 return 0;
01027         }
01028         if (!id) {
01029                 yyerror("no category name");
01030                 return -1;
01031         }
01032         cat = malloc(sizeof(cat_datum_t));
01033         if (!cat) {
01034                 free(id);
01035                 yyerror("Out of memory!");
01036                 return -1;
01037         }
01038         cat_datum_init(cat);
01039 
01040         retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat, &cat->s.value, &cat->s.value);
01041         if (retval != 0) {
01042                 free(id);
01043                 cat_datum_destroy(cat);
01044                 free(cat);
01045         }
01046         switch (retval) {
01047         case -3:
01048         {
01049                 yyerror("Out of memory!");
01050                 return -1;
01051         }
01052         case -2:
01053         {
01054                 yyerror("duplicate declaration of category");
01055                 return -1;
01056         }
01057         case -1:
01058         {
01059                 yyerror("could not require category here");
01060                 return -1;
01061         }
01062         case 0:
01063         {
01064                 return 0;
01065         }
01066         case 1:
01067         {
01068                 return 0;              /* category already required */
01069         }
01070         default:
01071         {
01072                 assert(0);             /* should never get here */
01073         }
01074         }
01075 }
01076 
01077 static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
01078 {
01079         int i;
01080         if (stack == NULL) {
01081                 return 0;              /* no matching scope found */
01082         }
01083         if (stack->type == 1) {
01084                 avrule_decl_t *decl = stack->decl;
01085                 for (i = 0; i < scope->decl_ids_len; i++) {
01086                         if (scope->decl_ids[i] == decl->decl_id) {
01087                                 return 1;
01088                         }
01089                 }
01090         } else {
01091                 /* note that conditionals can't declare or require
01092                  * symbols, so skip this level */
01093         }
01094 
01095         /* not within scope of this stack, so try its parent */
01096         return is_scope_in_stack(scope, stack->parent);
01097 }
01098 
01099 int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
01100 {
01101         scope_datum_t *scope = (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].table, id);
01102         if (scope == NULL) {
01103                 return 1;              /* id is not known, so return success */
01104         }
01105         return is_scope_in_stack(scope, stack_top);
01106 }
01107 
01108 static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value, scope_index_t * scope)
01109 {
01110         if (class_value > scope->class_perms_len) {
01111                 return 1;
01112         }
01113         if (ebitmap_get_bit(scope->class_perms_map + class_value - 1, perm_value - 1)) {
01114                 return 1;
01115         }
01116         return 0;
01117 }
01118 
01119 static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value, scope_stack_t * stack)
01120 {
01121         if (stack == NULL) {
01122                 return 0;              /* no matching scope found */
01123         }
01124         if (stack->type == 1) {
01125                 avrule_decl_t *decl = stack->decl;
01126                 if (is_perm_in_scope_index(perm_value, class_value, &decl->required)
01127                     || is_perm_in_scope_index(perm_value, class_value, &decl->declared)) {
01128                         return 1;
01129                 }
01130         } else {
01131                 /* note that conditionals can't declare or require
01132                  * symbols, so skip this level */
01133         }
01134 
01135         /* not within scope of this stack, so try its parent */
01136         return is_perm_in_stack(perm_value, class_value, stack->parent);
01137 }
01138 
01139 int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id)
01140 {
01141         class_datum_t *cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table,
01142                                                                    class_id);
01143         perm_datum_t *perdatum;
01144         if (cladatum == NULL) {
01145                 return 1;
01146         }
01147         perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table, perm_id);
01148         if (perdatum == NULL) {
01149                 return 1;
01150         }
01151         return is_perm_in_stack(perdatum->s.value, cladatum->s.value, stack_top);
01152 }
01153 
01154 cond_list_t *get_current_cond_list(cond_list_t * cond)
01155 {
01156         /* FIX ME: do something different here if in a nested
01157          * conditional? */
01158         avrule_decl_t *decl = stack_top->decl;
01159         return get_decl_cond_list(policydbp, decl, cond);
01160 }
01161 
01162 /* Append the new conditional node to the existing ones.  During
01163  * expansion the list will be reversed -- i.e., the last AV rule will
01164  * be the first one listed in the policy.  This matches the behavior
01165  * of the upstream compiler. */
01166 void append_cond_list(cond_list_t * cond)
01167 {
01168         cond_list_t *old_cond = get_current_cond_list(cond);
01169         avrule_t *tmp;
01170         assert(old_cond != NULL);      /* probably out of memory */
01171         if (old_cond->avtrue_list == NULL) {
01172                 old_cond->avtrue_list = cond->avtrue_list;
01173         } else {
01174                 for (tmp = old_cond->avtrue_list; tmp->next != NULL; tmp = tmp->next) ;
01175                 tmp->next = cond->avtrue_list;
01176         }
01177         if (old_cond->avfalse_list == NULL) {
01178                 old_cond->avfalse_list = cond->avfalse_list;
01179         } else {
01180                 for (tmp = old_cond->avfalse_list; tmp->next != NULL; tmp = tmp->next) ;
01181                 tmp->next = cond->avfalse_list;
01182         }
01183 }
01184 
01185 void append_avrule(avrule_t * avrule)
01186 {
01187         avrule_decl_t *decl = stack_top->decl;
01188 
01189         /* currently avrules follow a completely different code path
01190          * for handling avrules and compute types
01191          * (define_cond_avrule_te_avtab, define_cond_compute_type);
01192          * therefore there ought never be a conditional on top of the
01193          * scope stack */
01194         assert(stack_top->type == 1);
01195 
01196         if (stack_top->last_avrule == NULL) {
01197                 decl->avrules = avrule;
01198         } else {
01199                 stack_top->last_avrule->next = avrule;
01200         }
01201         stack_top->last_avrule = avrule;
01202 }
01203 
01204 /* this doesn't actually append, but really prepends it */
01205 void append_role_trans(role_trans_rule_t * role_tr_rules)
01206 {
01207         avrule_decl_t *decl = stack_top->decl;
01208 
01209         /* role transitions are not allowed within conditionals */
01210         assert(stack_top->type == 1);
01211 
01212         role_tr_rules->next = decl->role_tr_rules;
01213         decl->role_tr_rules = role_tr_rules;
01214 }
01215 
01216 /* this doesn't actually append, but really prepends it */
01217 void append_role_allow(role_allow_rule_t * role_allow_rules)
01218 {
01219         avrule_decl_t *decl = stack_top->decl;
01220 
01221         /* role allows are not allowed within conditionals */
01222         assert(stack_top->type == 1);
01223 
01224         role_allow_rules->next = decl->role_allow_rules;
01225         decl->role_allow_rules = role_allow_rules;
01226 }
01227 
01228 /* this doesn't actually append, but really prepends it */
01229 void append_range_trans(range_trans_rule_t * range_tr_rules)
01230 {
01231         avrule_decl_t *decl = stack_top->decl;
01232 
01233         /* range transitions are not allowed within conditionals */
01234         assert(stack_top->type == 1);
01235 
01236         range_tr_rules->next = decl->range_tr_rules;
01237         decl->range_tr_rules = range_tr_rules;
01238 }
01239 
01240 int begin_optional(int pass)
01241 {
01242         avrule_block_t *block = NULL;
01243         avrule_decl_t *decl;
01244         if (pass == 1) {
01245                 /* allocate a new avrule block for this optional block */
01246                 if ((block = avrule_block_create()) == NULL || (decl = avrule_decl_create(next_decl_id)) == NULL) {
01247                         goto cleanup;
01248                 }
01249                 block->flags |= AVRULE_OPTIONAL;
01250                 block->branch_list = decl;
01251                 last_block->next = block;
01252         } else {
01253                 /* select the next block from the chain built during pass 1 */
01254                 block = last_block->next;
01255                 assert(block != NULL && block->branch_list != NULL && block->branch_list->decl_id == next_decl_id);
01256                 decl = block->branch_list;
01257         }
01258         if (push_stack(1, block, decl) == -1) {
01259                 goto cleanup;
01260         }
01261         stack_top->last_avrule = NULL;
01262         last_block = block;
01263         next_decl_id++;
01264         return 0;
01265       cleanup:
01266         yyerror("Out of memory!");
01267         avrule_block_destroy(block);
01268         return -1;
01269 }
01270 
01271 int end_optional(int pass)
01272 {
01273         /* once nested conditionals are allowed, do the stack unfolding here */
01274         pop_stack();
01275         return 0;
01276 }
01277 
01278 int begin_optional_else(int pass)
01279 {
01280         avrule_decl_t *decl;
01281         assert(stack_top->type == 1 && stack_top->in_else == 0);
01282         if (pass == 1) {
01283                 /* allocate a new declaration and add it to the
01284                  * current chain */
01285                 if ((decl = avrule_decl_create(next_decl_id)) == NULL) {
01286                         yyerror("Out of memory!");
01287                         return -1;
01288                 }
01289                 stack_top->decl->next = decl;
01290         } else {
01291                 /* pick the (hopefully last) declaration of this
01292                  * avrule block, built from pass 1 */
01293                 decl = stack_top->decl->next;
01294                 assert(decl != NULL && decl->next == NULL && decl->decl_id == next_decl_id);
01295         }
01296         stack_top->in_else = 1;
01297         stack_top->decl = decl;
01298         stack_top->last_avrule = NULL;
01299         stack_top->require_given = 0;
01300         next_decl_id++;
01301         return 0;
01302 }
01303 
01304 static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
01305 {
01306         int i;
01307         if (stack == NULL) {
01308                 return 0;
01309         }
01310         if (stack->type == 1) {
01311                 scope_index_t *src_scope = &stack->decl->required;
01312                 scope_index_t *dest_scope = &dest->required;
01313                 for (i = 0; i < SYM_NUM; i++) {
01314                         ebitmap_t *src_bitmap = &src_scope->scope[i];
01315                         ebitmap_t *dest_bitmap = &dest_scope->scope[i];
01316                         if (ebitmap_union(dest_bitmap, src_bitmap)) {
01317                                 yyerror("Out of memory!");
01318                                 return -1;
01319                         }
01320                 }
01321                 /* now copy class permissions */
01322                 if (src_scope->class_perms_len > dest_scope->class_perms_len) {
01323                         ebitmap_t *new_map = realloc(dest_scope->class_perms_map,
01324                                                      src_scope->class_perms_len * sizeof(*new_map));
01325                         if (new_map == NULL) {
01326                                 yyerror("Out of memory!");
01327                                 return -1;
01328                         }
01329                         dest_scope->class_perms_map = new_map;
01330                         for (i = dest_scope->class_perms_len; i < src_scope->class_perms_len; i++) {
01331                                 ebitmap_init(dest_scope->class_perms_map + i);
01332                         }
01333                         dest_scope->class_perms_len = src_scope->class_perms_len;
01334                 }
01335                 for (i = 0; i < src_scope->class_perms_len; i++) {
01336                         ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
01337                         ebitmap_t *dest_bitmap = &dest_scope->class_perms_map[i];
01338                         if (ebitmap_union(dest_bitmap, src_bitmap)) {
01339                                 yyerror("Out of memory!");
01340                                 return -1;
01341                         }
01342                 }
01343         }
01344         return copy_requirements(dest, stack->parent);
01345 }
01346 
01347 /* During pass 1, check that at least one thing was required within
01348  * this block, for those places where a REQUIRED is necessary.  During
01349  * pass 2, have this block inherit its parents' requirements.  Return
01350  * 0 on success, -1 on failure. */
01351 int end_avrule_block(int pass)
01352 {
01353         avrule_decl_t *decl = stack_top->decl;
01354         assert(stack_top->type == 1);
01355         if (pass == 2) {
01356                 /* this avrule_decl inherits all of its parents'
01357                  * requirements */
01358                 if (copy_requirements(decl, stack_top->parent) == -1) {
01359                         return -1;
01360                 }
01361                 return 0;
01362         }
01363         if (!stack_top->in_else && !stack_top->require_given) {
01364                 if (policydbp->policy_type == POLICY_BASE && stack_top->parent != NULL) {
01365                         /* if this is base no require should be in the global block */
01366                         return 0;
01367                 } else {
01368                         /* non-ELSE branches must have at least one thing required */
01369                         yyerror("This block has no require section.");
01370                         return -1;
01371                 }
01372         }
01373         return 0;
01374 }
01375 
01376 /* Push a new scope on to the stack and update the 'last' pointer.
01377  * Return 0 on success, -1 if out * of memory. */
01378 static int push_stack(int stack_type, ...)
01379 {
01380         scope_stack_t *s = calloc(1, sizeof(*s));
01381         va_list ap;
01382         if (s == NULL) {
01383                 return -1;
01384         }
01385         va_start(ap, stack_type);
01386         switch (s->type = stack_type) {
01387         case 1:
01388         {
01389                 s->u.avrule = va_arg(ap, avrule_block_t *);
01390                 s->decl = va_arg(ap, avrule_decl_t *);
01391                 break;
01392         }
01393         case 2:
01394         {
01395                 s->u.cond_list = va_arg(ap, cond_list_t *);
01396                 break;
01397         }
01398         default:
01399                 /* invalid stack type given */
01400                 assert(0);
01401         }
01402         va_end(ap);
01403         s->parent = stack_top;
01404         s->child = NULL;
01405         stack_top = s;
01406         return 0;
01407 }
01408 
01409 /* Pop off the most recently added from the stack.  Update the 'last'
01410  * pointer. */
01411 static void pop_stack(void)
01412 {
01413         scope_stack_t *parent;
01414         assert(stack_top != NULL);
01415         parent = stack_top->parent;
01416         if (parent != NULL) {
01417                 parent->child = NULL;
01418         }
01419         free(stack_top);
01420         stack_top = parent;
01421 }