1 /* Authors: Jason Tang <jtang (at) 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 */ 33 static unsigned int symtab_sizes[SYM_NUM] = { 34 2, 35 4, 36 8, 37 32, 38 16, 39 4, 40 2, 41 2, 42 }; 43 44 avrule_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 53 avrule_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 */ 77 static 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 if (scope->class_perms_map) { 87 for (i = 0; i < scope->class_perms_len; i++) { 88 ebitmap_destroy(scope->class_perms_map + i); 89 } 90 } 91 free(scope->class_perms_map); 92 } 93 94 void avrule_decl_destroy(avrule_decl_t * x) 95 { 96 if (x == NULL) { 97 return; 98 } 99 cond_list_destroy(x->cond_list); 100 avrule_list_destroy(x->avrules); 101 role_trans_rule_list_destroy(x->role_tr_rules); 102 filename_trans_rule_list_destroy(x->filename_trans_rules); 103 role_allow_rule_list_destroy(x->role_allow_rules); 104 range_trans_rule_list_destroy(x->range_tr_rules); 105 scope_index_destroy(&x->required); 106 scope_index_destroy(&x->declared); 107 symtabs_destroy(x->symtab); 108 free(x->module_name); 109 free(x); 110 } 111 112 void avrule_block_destroy(avrule_block_t * x) 113 { 114 avrule_decl_t *decl; 115 if (x == NULL) { 116 return; 117 } 118 decl = x->branch_list; 119 while (decl != NULL) { 120 avrule_decl_t *next_decl = decl->next; 121 avrule_decl_destroy(decl); 122 decl = next_decl; 123 } 124 free(x); 125 } 126 127 void avrule_block_list_destroy(avrule_block_t * x) 128 { 129 while (x != NULL) { 130 avrule_block_t *next = x->next; 131 avrule_block_destroy(x); 132 x = next; 133 } 134 } 135 136 /* Get a conditional node from a avrule_decl with the same expression. 137 * If that expression does not exist then create one. */ 138 cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, 139 cond_list_t * cond) 140 { 141 cond_list_t *result; 142 int was_created; 143 result = cond_node_find(p, cond, decl->cond_list, &was_created); 144 if (result != NULL && was_created) { 145 result->next = decl->cond_list; 146 decl->cond_list = result; 147 } 148 return result; 149 } 150 151 /* Look up an identifier in a policy's scoping table. If it is there, 152 * marked as SCOPE_DECL, and any of its declaring block has been enabled, 153 * then return 1. Otherwise return 0. Can only be called after the 154 * decl_val_to_struct index has been created */ 155 int is_id_enabled(char *id, policydb_t * p, int symbol_table) 156 { 157 scope_datum_t *scope = 158 (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); 159 avrule_decl_t *decl; 160 uint32_t len = scope->decl_ids_len; 161 162 if (scope == NULL) { 163 return 0; 164 } 165 if (scope->scope != SCOPE_DECL) { 166 return 0; 167 } 168 169 if (len < 1) { 170 return 0; 171 } 172 173 if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) { 174 uint32_t i; 175 for (i = 0; i < len; i++) { 176 decl = p->decl_val_to_struct[scope->decl_ids[i] - 1]; 177 if (decl != NULL && decl->enabled) { 178 return 1; 179 } 180 } 181 } else { 182 decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1]; 183 if (decl != NULL && decl->enabled) { 184 return 1; 185 } 186 } 187 188 return 0; 189 } 190 191 /* Check if a particular permission is present within the given class, 192 * and that the class is enabled. Returns 1 if both conditions are 193 * true, 0 if neither could be found or if the class id disabled. */ 194 int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p) 195 { 196 class_datum_t *cladatum; 197 perm_datum_t *perm; 198 if (!is_id_enabled(class_id, p, SYM_CLASSES)) { 199 return 0; 200 } 201 cladatum = 202 (class_datum_t *) hashtab_search(p->p_classes.table, class_id); 203 if (cladatum == NULL) { 204 return 0; 205 } 206 perm = hashtab_search(cladatum->permissions.table, perm_id); 207 if (perm == NULL && cladatum->comdatum != 0) { 208 /* permission was not in this class. before giving 209 * up, check the class's parent */ 210 perm = 211 hashtab_search(cladatum->comdatum->permissions.table, 212 perm_id); 213 } 214 if (perm == NULL) { 215 return 0; 216 } 217 return 1; 218 } 219