• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
33 static const unsigned int symtab_sizes[SYM_NUM] = {
34 	2,
35 	4,
36 	8,
37 	32,
38 	16,
39 	4,
40 	2,
41 	2,
42 };
43 
avrule_block_create(void)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 
avrule_decl_create(uint32_t decl_id)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 */
scope_index_destroy(scope_index_t * scope)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 
avrule_decl_destroy(avrule_decl_t * x)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 
avrule_block_destroy(avrule_block_t * x)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 
avrule_block_list_destroy(avrule_block_t * x)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. */
get_decl_cond_list(policydb_t * p,avrule_decl_t * decl,cond_list_t * cond)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 */
is_id_enabled(char * id,policydb_t * p,int symbol_table)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;
161 
162 	if (scope == NULL) {
163 		return 0;
164 	}
165 	if (scope->scope != SCOPE_DECL) {
166 		return 0;
167 	}
168 
169 	len = scope->decl_ids_len;
170 	if (len < 1) {
171 		return 0;
172 	}
173 
174 	if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) {
175 		uint32_t i;
176 		for (i = 0; i < len; i++) {
177 			decl = p->decl_val_to_struct[scope->decl_ids[i] - 1];
178 			if (decl != NULL && decl->enabled) {
179 				return 1;
180 			}
181 		}
182 	} else {
183 		decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1];
184 		if (decl != NULL && decl->enabled) {
185 			return 1;
186 		}
187 	}
188 
189 	return 0;
190 }
191 
192 /* Check if a particular permission is present within the given class,
193  * and that the class is enabled.  Returns 1 if both conditions are
194  * true, 0 if neither could be found or if the class id disabled. */
is_perm_enabled(char * class_id,char * perm_id,policydb_t * p)195 int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p)
196 {
197 	class_datum_t *cladatum;
198 	perm_datum_t *perm;
199 	if (!is_id_enabled(class_id, p, SYM_CLASSES)) {
200 		return 0;
201 	}
202 	cladatum =
203 	    (class_datum_t *) hashtab_search(p->p_classes.table, class_id);
204 	if (cladatum == NULL) {
205 		return 0;
206 	}
207 	perm = hashtab_search(cladatum->permissions.table, perm_id);
208 	if (perm == NULL && cladatum->comdatum != 0) {
209 		/* permission was not in this class.  before giving
210 		 * up, check the class's parent */
211 		perm =
212 		    hashtab_search(cladatum->comdatum->permissions.table,
213 				   perm_id);
214 	}
215 	if (perm == NULL) {
216 		return 0;
217 	}
218 	return 1;
219 }
220