1/* Authors: Jason Tang <jtang@tresys.com> 2 * 3 * Functions that manipulate a logical block (conditional, optional, 4 * or global scope) for a policy module. 5 * 6 * Copyright (C) 2005 Tresys Technology, LLC 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23#include <sepol/policydb/policydb.h> 24#include <sepol/policydb/conditional.h> 25#include <sepol/policydb/avrule_block.h> 26 27#include <assert.h> 28#include <stdlib.h> 29 30/* It is anticipated that there be less declarations within an avrule 31 * block than the global policy. Thus the symbol table sizes are 32 * smaller than those listed in policydb.c */ 33static unsigned int symtab_sizes[SYM_NUM] = { 34 2, 35 4, 36 8, 37 32, 38 16, 39 4, 40 2, 41 2, 42}; 43 44avrule_block_t *avrule_block_create(void) 45{ 46 avrule_block_t *block; 47 if ((block = calloc(1, sizeof(*block))) == NULL) { 48 return NULL; 49 } 50 return block; 51} 52 53avrule_decl_t *avrule_decl_create(uint32_t decl_id) 54{ 55 avrule_decl_t *decl; 56 int i; 57 if ((decl = calloc(1, sizeof(*decl))) == NULL) { 58 return NULL; 59 } 60 decl->decl_id = decl_id; 61 for (i = 0; i < SYM_NUM; i++) { 62 if (symtab_init(&decl->symtab[i], symtab_sizes[i])) { 63 avrule_decl_destroy(decl); 64 free(decl); 65 return NULL; 66 } 67 } 68 69 for (i = 0; i < SYM_NUM; i++) { 70 ebitmap_init(&decl->required.scope[i]); 71 ebitmap_init(&decl->declared.scope[i]); 72 } 73 return decl; 74} 75 76/* note that unlike the other destroy functions, this one does /NOT/ 77 * destroy the pointer itself */ 78static void scope_index_destroy(scope_index_t * scope) 79{ 80 unsigned int i; 81 if (scope == NULL) { 82 return; 83 } 84 for (i = 0; i < SYM_NUM; i++) { 85 ebitmap_destroy(scope->scope + i); 86 } 87 for (i = 0; i < scope->class_perms_len; i++) { 88 ebitmap_destroy(scope->class_perms_map + i); 89 } 90 free(scope->class_perms_map); 91} 92 93void avrule_decl_destroy(avrule_decl_t * x) 94{ 95 if (x == NULL) { 96 return; 97 } 98 cond_list_destroy(x->cond_list); 99 avrule_list_destroy(x->avrules); 100 role_trans_rule_list_destroy(x->role_tr_rules); 101 filename_trans_rule_list_destroy(x->filename_trans_rules); 102 role_allow_rule_list_destroy(x->role_allow_rules); 103 range_trans_rule_list_destroy(x->range_tr_rules); 104 scope_index_destroy(&x->required); 105 scope_index_destroy(&x->declared); 106 symtabs_destroy(x->symtab); 107 free(x->module_name); 108 free(x); 109} 110 111void avrule_block_destroy(avrule_block_t * x) 112{ 113 avrule_decl_t *decl; 114 if (x == NULL) { 115 return; 116 } 117 decl = x->branch_list; 118 while (decl != NULL) { 119 avrule_decl_t *next_decl = decl->next; 120 avrule_decl_destroy(decl); 121 decl = next_decl; 122 } 123 free(x); 124} 125 126void avrule_block_list_destroy(avrule_block_t * x) 127{ 128 while (x != NULL) { 129 avrule_block_t *next = x->next; 130 avrule_block_destroy(x); 131 x = next; 132 } 133} 134 135/* Get a conditional node from a avrule_decl with the same expression. 136 * If that expression does not exist then create one. */ 137cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, 138 cond_list_t * cond) 139{ 140 cond_list_t *result; 141 int was_created; 142 result = cond_node_find(p, cond, decl->cond_list, &was_created); 143 if (result != NULL && was_created) { 144 result->next = decl->cond_list; 145 decl->cond_list = result; 146 } 147 return result; 148} 149 150/* Look up an identifier in a policy's scoping table. If it is there, 151 * marked as SCOPE_DECL, and any of its declaring block has been enabled, 152 * then return 1. Otherwise return 0. Can only be called after the 153 * decl_val_to_struct index has been created */ 154int is_id_enabled(char *id, policydb_t * p, int symbol_table) 155{ 156 scope_datum_t *scope = 157 (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); 158 uint32_t i; 159 if (scope == NULL) { 160 return 0; 161 } 162 if (scope->scope != SCOPE_DECL) { 163 return 0; 164 } 165 for (i = 0; i < scope->decl_ids_len; i++) { 166 avrule_decl_t *decl = 167 p->decl_val_to_struct[scope->decl_ids[i] - 1]; 168 if (decl != NULL && decl->enabled) { 169 return 1; 170 } 171 } 172 return 0; 173} 174 175/* Check if a particular permission is present within the given class, 176 * and that the class is enabled. Returns 1 if both conditions are 177 * true, 0 if neither could be found or if the class id disabled. */ 178int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p) 179{ 180 class_datum_t *cladatum; 181 perm_datum_t *perm; 182 if (!is_id_enabled(class_id, p, SYM_CLASSES)) { 183 return 0; 184 } 185 cladatum = 186 (class_datum_t *) hashtab_search(p->p_classes.table, class_id); 187 if (cladatum == NULL) { 188 return 0; 189 } 190 perm = hashtab_search(cladatum->permissions.table, perm_id); 191 if (perm == NULL && cladatum->comdatum != 0) { 192 /* permission was not in this class. before giving 193 * up, check the class's parent */ 194 perm = 195 hashtab_search(cladatum->comdatum->permissions.table, 196 perm_id); 197 } 198 if (perm == NULL) { 199 return 0; 200 } 201 return 1; 202} 203