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 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 */ 78 static 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 93 void 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 111 void 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 126 void 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. */ 137 cond_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 */ 154 int 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. */ 178 int 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