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 return NULL; 65 } 66 } 67 68 for (i = 0; i < SYM_NUM; i++) { 69 ebitmap_init(&decl->required.scope[i]); 70 ebitmap_init(&decl->declared.scope[i]); 71 } 72 return decl; 73} 74 75/* note that unlike the other destroy functions, this one does /NOT/ 76 * destroy the pointer itself */ 77static void scope_index_destroy(scope_index_t * scope) 78{ 79 unsigned int i; 80 if (scope == NULL) { 81 return; 82 } 83 for (i = 0; i < SYM_NUM; i++) { 84 ebitmap_destroy(scope->scope + i); 85 } 86 for (i = 0; i < scope->class_perms_len; i++) { 87 ebitmap_destroy(scope->class_perms_map + i); 88 } 89 free(scope->class_perms_map); 90} 91 92void avrule_decl_destroy(avrule_decl_t * x) 93{ 94 if (x == NULL) { 95 return; 96 } 97 cond_list_destroy(x->cond_list); 98 avrule_list_destroy(x->avrules); 99 role_trans_rule_list_destroy(x->role_tr_rules); 100 filename_trans_rule_list_destroy(x->filename_trans_rules); 101 role_allow_rule_list_destroy(x->role_allow_rules); 102 range_trans_rule_list_destroy(x->range_tr_rules); 103 scope_index_destroy(&x->required); 104 scope_index_destroy(&x->declared); 105 symtabs_destroy(x->symtab); 106 free(x->module_name); 107 free(x); 108} 109 110void avrule_block_destroy(avrule_block_t * x) 111{ 112 avrule_decl_t *decl; 113 if (x == NULL) { 114 return; 115 } 116 decl = x->branch_list; 117 while (decl != NULL) { 118 avrule_decl_t *next_decl = decl->next; 119 avrule_decl_destroy(decl); 120 decl = next_decl; 121 } 122 free(x); 123} 124 125void avrule_block_list_destroy(avrule_block_t * x) 126{ 127 while (x != NULL) { 128 avrule_block_t *next = x->next; 129 avrule_block_destroy(x); 130 x = next; 131 } 132} 133 134/* Get a conditional node from a avrule_decl with the same expression. 135 * If that expression does not exist then create one. */ 136cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, 137 cond_list_t * cond) 138{ 139 cond_list_t *result; 140 int was_created; 141 result = cond_node_find(p, cond, decl->cond_list, &was_created); 142 if (result != NULL && was_created) { 143 result->next = decl->cond_list; 144 decl->cond_list = result; 145 } 146 return result; 147} 148 149/* Look up an identifier in a policy's scoping table. If it is there, 150 * marked as SCOPE_DECL, and any of its declaring block has been enabled, 151 * then return 1. Otherwise return 0. Can only be called after the 152 * decl_val_to_struct index has been created */ 153int is_id_enabled(char *id, policydb_t * p, int symbol_table) 154{ 155 scope_datum_t *scope = 156 (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); 157 uint32_t i; 158 if (scope == NULL) { 159 return 0; 160 } 161 if (scope->scope != SCOPE_DECL) { 162 return 0; 163 } 164 for (i = 0; i < scope->decl_ids_len; i++) { 165 avrule_decl_t *decl = 166 p->decl_val_to_struct[scope->decl_ids[i] - 1]; 167 if (decl != NULL && decl->enabled) { 168 return 1; 169 } 170 } 171 return 0; 172} 173 174/* Check if a particular permission is present within the given class, 175 * and that the class is enabled. Returns 1 if both conditions are 176 * true, 0 if neither could be found or if the class id disabled. */ 177int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p) 178{ 179 class_datum_t *cladatum; 180 perm_datum_t *perm; 181 if (!is_id_enabled(class_id, p, SYM_CLASSES)) { 182 return 0; 183 } 184 cladatum = 185 (class_datum_t *) hashtab_search(p->p_classes.table, class_id); 186 if (cladatum == NULL) { 187 return 0; 188 } 189 perm = hashtab_search(cladatum->permissions.table, perm_id); 190 if (perm == NULL && cladatum->comdatum != 0) { 191 /* permission was not in this class. before giving 192 * up, check the class's parent */ 193 perm = 194 hashtab_search(cladatum->comdatum->permissions.table, 195 perm_id); 196 } 197 if (perm == NULL) { 198 return 0; 199 } 200 return 1; 201} 202