Home | History | Annotate | Download | only in src
      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