16cd6a6acSopenharmony_ci/* Authors: Jason Tang <jtang@tresys.com> 26cd6a6acSopenharmony_ci * 36cd6a6acSopenharmony_ci * Functions that manipulate a logical block (conditional, optional, 46cd6a6acSopenharmony_ci * or global scope) for a policy module. 56cd6a6acSopenharmony_ci * 66cd6a6acSopenharmony_ci * Copyright (C) 2005 Tresys Technology, LLC 76cd6a6acSopenharmony_ci * 86cd6a6acSopenharmony_ci * This library is free software; you can redistribute it and/or 96cd6a6acSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 106cd6a6acSopenharmony_ci * License as published by the Free Software Foundation; either 116cd6a6acSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 126cd6a6acSopenharmony_ci * 136cd6a6acSopenharmony_ci * This library is distributed in the hope that it will be useful, 146cd6a6acSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 156cd6a6acSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 166cd6a6acSopenharmony_ci * Lesser General Public License for more details. 176cd6a6acSopenharmony_ci * 186cd6a6acSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 196cd6a6acSopenharmony_ci * License along with this library; if not, write to the Free Software 206cd6a6acSopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 216cd6a6acSopenharmony_ci */ 226cd6a6acSopenharmony_ci 236cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 246cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h> 256cd6a6acSopenharmony_ci#include <sepol/policydb/avrule_block.h> 266cd6a6acSopenharmony_ci 276cd6a6acSopenharmony_ci#include <assert.h> 286cd6a6acSopenharmony_ci#include <stdlib.h> 296cd6a6acSopenharmony_ci 306cd6a6acSopenharmony_ci/* It is anticipated that there be less declarations within an avrule 316cd6a6acSopenharmony_ci * block than the global policy. Thus the symbol table sizes are 326cd6a6acSopenharmony_ci * smaller than those listed in policydb.c */ 336cd6a6acSopenharmony_cistatic const unsigned int symtab_sizes[SYM_NUM] = { 346cd6a6acSopenharmony_ci 2, 356cd6a6acSopenharmony_ci 4, 366cd6a6acSopenharmony_ci 8, 376cd6a6acSopenharmony_ci 32, 386cd6a6acSopenharmony_ci 16, 396cd6a6acSopenharmony_ci 4, 406cd6a6acSopenharmony_ci 2, 416cd6a6acSopenharmony_ci 2, 426cd6a6acSopenharmony_ci}; 436cd6a6acSopenharmony_ci 446cd6a6acSopenharmony_ciavrule_block_t *avrule_block_create(void) 456cd6a6acSopenharmony_ci{ 466cd6a6acSopenharmony_ci avrule_block_t *block; 476cd6a6acSopenharmony_ci if ((block = calloc(1, sizeof(*block))) == NULL) { 486cd6a6acSopenharmony_ci return NULL; 496cd6a6acSopenharmony_ci } 506cd6a6acSopenharmony_ci return block; 516cd6a6acSopenharmony_ci} 526cd6a6acSopenharmony_ci 536cd6a6acSopenharmony_ciavrule_decl_t *avrule_decl_create(uint32_t decl_id) 546cd6a6acSopenharmony_ci{ 556cd6a6acSopenharmony_ci avrule_decl_t *decl; 566cd6a6acSopenharmony_ci int i; 576cd6a6acSopenharmony_ci if ((decl = calloc(1, sizeof(*decl))) == NULL) { 586cd6a6acSopenharmony_ci return NULL; 596cd6a6acSopenharmony_ci } 606cd6a6acSopenharmony_ci decl->decl_id = decl_id; 616cd6a6acSopenharmony_ci for (i = 0; i < SYM_NUM; i++) { 626cd6a6acSopenharmony_ci if (symtab_init(&decl->symtab[i], symtab_sizes[i])) { 636cd6a6acSopenharmony_ci avrule_decl_destroy(decl); 646cd6a6acSopenharmony_ci return NULL; 656cd6a6acSopenharmony_ci } 666cd6a6acSopenharmony_ci } 676cd6a6acSopenharmony_ci 686cd6a6acSopenharmony_ci for (i = 0; i < SYM_NUM; i++) { 696cd6a6acSopenharmony_ci ebitmap_init(&decl->required.scope[i]); 706cd6a6acSopenharmony_ci ebitmap_init(&decl->declared.scope[i]); 716cd6a6acSopenharmony_ci } 726cd6a6acSopenharmony_ci return decl; 736cd6a6acSopenharmony_ci} 746cd6a6acSopenharmony_ci 756cd6a6acSopenharmony_ci/* note that unlike the other destroy functions, this one does /NOT/ 766cd6a6acSopenharmony_ci * destroy the pointer itself */ 776cd6a6acSopenharmony_cistatic void scope_index_destroy(scope_index_t * scope) 786cd6a6acSopenharmony_ci{ 796cd6a6acSopenharmony_ci unsigned int i; 806cd6a6acSopenharmony_ci if (scope == NULL) { 816cd6a6acSopenharmony_ci return; 826cd6a6acSopenharmony_ci } 836cd6a6acSopenharmony_ci for (i = 0; i < SYM_NUM; i++) { 846cd6a6acSopenharmony_ci ebitmap_destroy(scope->scope + i); 856cd6a6acSopenharmony_ci } 866cd6a6acSopenharmony_ci if (scope->class_perms_map) { 876cd6a6acSopenharmony_ci for (i = 0; i < scope->class_perms_len; i++) { 886cd6a6acSopenharmony_ci ebitmap_destroy(scope->class_perms_map + i); 896cd6a6acSopenharmony_ci } 906cd6a6acSopenharmony_ci } 916cd6a6acSopenharmony_ci free(scope->class_perms_map); 926cd6a6acSopenharmony_ci} 936cd6a6acSopenharmony_ci 946cd6a6acSopenharmony_civoid avrule_decl_destroy(avrule_decl_t * x) 956cd6a6acSopenharmony_ci{ 966cd6a6acSopenharmony_ci if (x == NULL) { 976cd6a6acSopenharmony_ci return; 986cd6a6acSopenharmony_ci } 996cd6a6acSopenharmony_ci cond_list_destroy(x->cond_list); 1006cd6a6acSopenharmony_ci avrule_list_destroy(x->avrules); 1016cd6a6acSopenharmony_ci role_trans_rule_list_destroy(x->role_tr_rules); 1026cd6a6acSopenharmony_ci filename_trans_rule_list_destroy(x->filename_trans_rules); 1036cd6a6acSopenharmony_ci role_allow_rule_list_destroy(x->role_allow_rules); 1046cd6a6acSopenharmony_ci range_trans_rule_list_destroy(x->range_tr_rules); 1056cd6a6acSopenharmony_ci scope_index_destroy(&x->required); 1066cd6a6acSopenharmony_ci scope_index_destroy(&x->declared); 1076cd6a6acSopenharmony_ci symtabs_destroy(x->symtab); 1086cd6a6acSopenharmony_ci free(x->module_name); 1096cd6a6acSopenharmony_ci free(x); 1106cd6a6acSopenharmony_ci} 1116cd6a6acSopenharmony_ci 1126cd6a6acSopenharmony_civoid avrule_block_destroy(avrule_block_t * x) 1136cd6a6acSopenharmony_ci{ 1146cd6a6acSopenharmony_ci avrule_decl_t *decl; 1156cd6a6acSopenharmony_ci if (x == NULL) { 1166cd6a6acSopenharmony_ci return; 1176cd6a6acSopenharmony_ci } 1186cd6a6acSopenharmony_ci decl = x->branch_list; 1196cd6a6acSopenharmony_ci while (decl != NULL) { 1206cd6a6acSopenharmony_ci avrule_decl_t *next_decl = decl->next; 1216cd6a6acSopenharmony_ci avrule_decl_destroy(decl); 1226cd6a6acSopenharmony_ci decl = next_decl; 1236cd6a6acSopenharmony_ci } 1246cd6a6acSopenharmony_ci free(x); 1256cd6a6acSopenharmony_ci} 1266cd6a6acSopenharmony_ci 1276cd6a6acSopenharmony_civoid avrule_block_list_destroy(avrule_block_t * x) 1286cd6a6acSopenharmony_ci{ 1296cd6a6acSopenharmony_ci while (x != NULL) { 1306cd6a6acSopenharmony_ci avrule_block_t *next = x->next; 1316cd6a6acSopenharmony_ci avrule_block_destroy(x); 1326cd6a6acSopenharmony_ci x = next; 1336cd6a6acSopenharmony_ci } 1346cd6a6acSopenharmony_ci} 1356cd6a6acSopenharmony_ci 1366cd6a6acSopenharmony_ci/* Get a conditional node from a avrule_decl with the same expression. 1376cd6a6acSopenharmony_ci * If that expression does not exist then create one. */ 1386cd6a6acSopenharmony_cicond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, 1396cd6a6acSopenharmony_ci cond_list_t * cond) 1406cd6a6acSopenharmony_ci{ 1416cd6a6acSopenharmony_ci cond_list_t *result; 1426cd6a6acSopenharmony_ci int was_created; 1436cd6a6acSopenharmony_ci result = cond_node_find(p, cond, decl->cond_list, &was_created); 1446cd6a6acSopenharmony_ci if (result != NULL && was_created) { 1456cd6a6acSopenharmony_ci result->next = decl->cond_list; 1466cd6a6acSopenharmony_ci decl->cond_list = result; 1476cd6a6acSopenharmony_ci } 1486cd6a6acSopenharmony_ci return result; 1496cd6a6acSopenharmony_ci} 1506cd6a6acSopenharmony_ci 1516cd6a6acSopenharmony_ci/* Look up an identifier in a policy's scoping table. If it is there, 1526cd6a6acSopenharmony_ci * marked as SCOPE_DECL, and any of its declaring block has been enabled, 1536cd6a6acSopenharmony_ci * then return 1. Otherwise return 0. Can only be called after the 1546cd6a6acSopenharmony_ci * decl_val_to_struct index has been created */ 1556cd6a6acSopenharmony_ciint is_id_enabled(char *id, policydb_t * p, int symbol_table) 1566cd6a6acSopenharmony_ci{ 1576cd6a6acSopenharmony_ci scope_datum_t *scope = 1586cd6a6acSopenharmony_ci (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); 1596cd6a6acSopenharmony_ci avrule_decl_t *decl; 1606cd6a6acSopenharmony_ci uint32_t len; 1616cd6a6acSopenharmony_ci 1626cd6a6acSopenharmony_ci if (scope == NULL) { 1636cd6a6acSopenharmony_ci return 0; 1646cd6a6acSopenharmony_ci } 1656cd6a6acSopenharmony_ci if (scope->scope != SCOPE_DECL) { 1666cd6a6acSopenharmony_ci return 0; 1676cd6a6acSopenharmony_ci } 1686cd6a6acSopenharmony_ci 1696cd6a6acSopenharmony_ci len = scope->decl_ids_len; 1706cd6a6acSopenharmony_ci if (len < 1) { 1716cd6a6acSopenharmony_ci return 0; 1726cd6a6acSopenharmony_ci } 1736cd6a6acSopenharmony_ci 1746cd6a6acSopenharmony_ci if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) { 1756cd6a6acSopenharmony_ci uint32_t i; 1766cd6a6acSopenharmony_ci for (i = 0; i < len; i++) { 1776cd6a6acSopenharmony_ci decl = p->decl_val_to_struct[scope->decl_ids[i] - 1]; 1786cd6a6acSopenharmony_ci if (decl != NULL && decl->enabled) { 1796cd6a6acSopenharmony_ci return 1; 1806cd6a6acSopenharmony_ci } 1816cd6a6acSopenharmony_ci } 1826cd6a6acSopenharmony_ci } else { 1836cd6a6acSopenharmony_ci decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1]; 1846cd6a6acSopenharmony_ci if (decl != NULL && decl->enabled) { 1856cd6a6acSopenharmony_ci return 1; 1866cd6a6acSopenharmony_ci } 1876cd6a6acSopenharmony_ci } 1886cd6a6acSopenharmony_ci 1896cd6a6acSopenharmony_ci return 0; 1906cd6a6acSopenharmony_ci} 1916cd6a6acSopenharmony_ci 1926cd6a6acSopenharmony_ci/* Check if a particular permission is present within the given class, 1936cd6a6acSopenharmony_ci * and that the class is enabled. Returns 1 if both conditions are 1946cd6a6acSopenharmony_ci * true, 0 if neither could be found or if the class id disabled. */ 1956cd6a6acSopenharmony_ciint is_perm_enabled(char *class_id, char *perm_id, policydb_t * p) 1966cd6a6acSopenharmony_ci{ 1976cd6a6acSopenharmony_ci class_datum_t *cladatum; 1986cd6a6acSopenharmony_ci perm_datum_t *perm; 1996cd6a6acSopenharmony_ci if (!is_id_enabled(class_id, p, SYM_CLASSES)) { 2006cd6a6acSopenharmony_ci return 0; 2016cd6a6acSopenharmony_ci } 2026cd6a6acSopenharmony_ci cladatum = 2036cd6a6acSopenharmony_ci (class_datum_t *) hashtab_search(p->p_classes.table, class_id); 2046cd6a6acSopenharmony_ci if (cladatum == NULL) { 2056cd6a6acSopenharmony_ci return 0; 2066cd6a6acSopenharmony_ci } 2076cd6a6acSopenharmony_ci perm = hashtab_search(cladatum->permissions.table, perm_id); 2086cd6a6acSopenharmony_ci if (perm == NULL && cladatum->comdatum != 0) { 2096cd6a6acSopenharmony_ci /* permission was not in this class. before giving 2106cd6a6acSopenharmony_ci * up, check the class's parent */ 2116cd6a6acSopenharmony_ci perm = 2126cd6a6acSopenharmony_ci hashtab_search(cladatum->comdatum->permissions.table, 2136cd6a6acSopenharmony_ci perm_id); 2146cd6a6acSopenharmony_ci } 2156cd6a6acSopenharmony_ci if (perm == NULL) { 2166cd6a6acSopenharmony_ci return 0; 2176cd6a6acSopenharmony_ci } 2186cd6a6acSopenharmony_ci return 1; 2196cd6a6acSopenharmony_ci} 220