xref: /aosp_15_r20/external/selinux/libsepol/src/avrule_block.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Authors: Jason Tang <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker  *
3*2d543d20SAndroid Build Coastguard Worker  * Functions that manipulate a logical block (conditional, optional,
4*2d543d20SAndroid Build Coastguard Worker  * or global scope) for a policy module.
5*2d543d20SAndroid Build Coastguard Worker  *
6*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2005 Tresys Technology, LLC
7*2d543d20SAndroid Build Coastguard Worker  *
8*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
9*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
10*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
11*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
12*2d543d20SAndroid Build Coastguard Worker  *
13*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
14*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
17*2d543d20SAndroid Build Coastguard Worker  *
18*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
19*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
20*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21*2d543d20SAndroid Build Coastguard Worker  */
22*2d543d20SAndroid Build Coastguard Worker 
23*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
24*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
25*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/avrule_block.h>
26*2d543d20SAndroid Build Coastguard Worker 
27*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
28*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
29*2d543d20SAndroid Build Coastguard Worker 
30*2d543d20SAndroid Build Coastguard Worker /* It is anticipated that there be less declarations within an avrule
31*2d543d20SAndroid Build Coastguard Worker  * block than the global policy.  Thus the symbol table sizes are
32*2d543d20SAndroid Build Coastguard Worker  * smaller than those listed in policydb.c */
33*2d543d20SAndroid Build Coastguard Worker static const unsigned int symtab_sizes[SYM_NUM] = {
34*2d543d20SAndroid Build Coastguard Worker 	2,
35*2d543d20SAndroid Build Coastguard Worker 	4,
36*2d543d20SAndroid Build Coastguard Worker 	8,
37*2d543d20SAndroid Build Coastguard Worker 	32,
38*2d543d20SAndroid Build Coastguard Worker 	16,
39*2d543d20SAndroid Build Coastguard Worker 	4,
40*2d543d20SAndroid Build Coastguard Worker 	2,
41*2d543d20SAndroid Build Coastguard Worker 	2,
42*2d543d20SAndroid Build Coastguard Worker };
43*2d543d20SAndroid Build Coastguard Worker 
avrule_block_create(void)44*2d543d20SAndroid Build Coastguard Worker avrule_block_t *avrule_block_create(void)
45*2d543d20SAndroid Build Coastguard Worker {
46*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *block;
47*2d543d20SAndroid Build Coastguard Worker 	if ((block = calloc(1, sizeof(*block))) == NULL) {
48*2d543d20SAndroid Build Coastguard Worker 		return NULL;
49*2d543d20SAndroid Build Coastguard Worker 	}
50*2d543d20SAndroid Build Coastguard Worker 	return block;
51*2d543d20SAndroid Build Coastguard Worker }
52*2d543d20SAndroid Build Coastguard Worker 
avrule_decl_create(uint32_t decl_id)53*2d543d20SAndroid Build Coastguard Worker avrule_decl_t *avrule_decl_create(uint32_t decl_id)
54*2d543d20SAndroid Build Coastguard Worker {
55*2d543d20SAndroid Build Coastguard Worker 	avrule_decl_t *decl;
56*2d543d20SAndroid Build Coastguard Worker 	int i;
57*2d543d20SAndroid Build Coastguard Worker 	if ((decl = calloc(1, sizeof(*decl))) == NULL) {
58*2d543d20SAndroid Build Coastguard Worker 		return NULL;
59*2d543d20SAndroid Build Coastguard Worker 	}
60*2d543d20SAndroid Build Coastguard Worker 	decl->decl_id = decl_id;
61*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
62*2d543d20SAndroid Build Coastguard Worker 		if (symtab_init(&decl->symtab[i], symtab_sizes[i])) {
63*2d543d20SAndroid Build Coastguard Worker 			avrule_decl_destroy(decl);
64*2d543d20SAndroid Build Coastguard Worker 			return NULL;
65*2d543d20SAndroid Build Coastguard Worker 		}
66*2d543d20SAndroid Build Coastguard Worker 	}
67*2d543d20SAndroid Build Coastguard Worker 
68*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
69*2d543d20SAndroid Build Coastguard Worker 		ebitmap_init(&decl->required.scope[i]);
70*2d543d20SAndroid Build Coastguard Worker 		ebitmap_init(&decl->declared.scope[i]);
71*2d543d20SAndroid Build Coastguard Worker 	}
72*2d543d20SAndroid Build Coastguard Worker 	return decl;
73*2d543d20SAndroid Build Coastguard Worker }
74*2d543d20SAndroid Build Coastguard Worker 
75*2d543d20SAndroid Build Coastguard Worker /* note that unlike the other destroy functions, this one does /NOT/
76*2d543d20SAndroid Build Coastguard Worker  * destroy the pointer itself */
scope_index_destroy(scope_index_t * scope)77*2d543d20SAndroid Build Coastguard Worker static void scope_index_destroy(scope_index_t * scope)
78*2d543d20SAndroid Build Coastguard Worker {
79*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
80*2d543d20SAndroid Build Coastguard Worker 	if (scope == NULL) {
81*2d543d20SAndroid Build Coastguard Worker 		return;
82*2d543d20SAndroid Build Coastguard Worker 	}
83*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SYM_NUM; i++) {
84*2d543d20SAndroid Build Coastguard Worker 		ebitmap_destroy(scope->scope + i);
85*2d543d20SAndroid Build Coastguard Worker 	}
86*2d543d20SAndroid Build Coastguard Worker 	if (scope->class_perms_map) {
87*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < scope->class_perms_len; i++) {
88*2d543d20SAndroid Build Coastguard Worker 			ebitmap_destroy(scope->class_perms_map + i);
89*2d543d20SAndroid Build Coastguard Worker 		}
90*2d543d20SAndroid Build Coastguard Worker 	}
91*2d543d20SAndroid Build Coastguard Worker 	free(scope->class_perms_map);
92*2d543d20SAndroid Build Coastguard Worker }
93*2d543d20SAndroid Build Coastguard Worker 
avrule_decl_destroy(avrule_decl_t * x)94*2d543d20SAndroid Build Coastguard Worker void avrule_decl_destroy(avrule_decl_t * x)
95*2d543d20SAndroid Build Coastguard Worker {
96*2d543d20SAndroid Build Coastguard Worker 	if (x == NULL) {
97*2d543d20SAndroid Build Coastguard Worker 		return;
98*2d543d20SAndroid Build Coastguard Worker 	}
99*2d543d20SAndroid Build Coastguard Worker 	cond_list_destroy(x->cond_list);
100*2d543d20SAndroid Build Coastguard Worker 	avrule_list_destroy(x->avrules);
101*2d543d20SAndroid Build Coastguard Worker 	role_trans_rule_list_destroy(x->role_tr_rules);
102*2d543d20SAndroid Build Coastguard Worker 	filename_trans_rule_list_destroy(x->filename_trans_rules);
103*2d543d20SAndroid Build Coastguard Worker 	role_allow_rule_list_destroy(x->role_allow_rules);
104*2d543d20SAndroid Build Coastguard Worker 	range_trans_rule_list_destroy(x->range_tr_rules);
105*2d543d20SAndroid Build Coastguard Worker 	scope_index_destroy(&x->required);
106*2d543d20SAndroid Build Coastguard Worker 	scope_index_destroy(&x->declared);
107*2d543d20SAndroid Build Coastguard Worker 	symtabs_destroy(x->symtab);
108*2d543d20SAndroid Build Coastguard Worker 	free(x->module_name);
109*2d543d20SAndroid Build Coastguard Worker 	free(x);
110*2d543d20SAndroid Build Coastguard Worker }
111*2d543d20SAndroid Build Coastguard Worker 
avrule_block_destroy(avrule_block_t * x)112*2d543d20SAndroid Build Coastguard Worker void avrule_block_destroy(avrule_block_t * x)
113*2d543d20SAndroid Build Coastguard Worker {
114*2d543d20SAndroid Build Coastguard Worker 	avrule_decl_t *decl;
115*2d543d20SAndroid Build Coastguard Worker 	if (x == NULL) {
116*2d543d20SAndroid Build Coastguard Worker 		return;
117*2d543d20SAndroid Build Coastguard Worker 	}
118*2d543d20SAndroid Build Coastguard Worker 	decl = x->branch_list;
119*2d543d20SAndroid Build Coastguard Worker 	while (decl != NULL) {
120*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_t *next_decl = decl->next;
121*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_destroy(decl);
122*2d543d20SAndroid Build Coastguard Worker 		decl = next_decl;
123*2d543d20SAndroid Build Coastguard Worker 	}
124*2d543d20SAndroid Build Coastguard Worker 	free(x);
125*2d543d20SAndroid Build Coastguard Worker }
126*2d543d20SAndroid Build Coastguard Worker 
avrule_block_list_destroy(avrule_block_t * x)127*2d543d20SAndroid Build Coastguard Worker void avrule_block_list_destroy(avrule_block_t * x)
128*2d543d20SAndroid Build Coastguard Worker {
129*2d543d20SAndroid Build Coastguard Worker 	while (x != NULL) {
130*2d543d20SAndroid Build Coastguard Worker 		avrule_block_t *next = x->next;
131*2d543d20SAndroid Build Coastguard Worker 		avrule_block_destroy(x);
132*2d543d20SAndroid Build Coastguard Worker 		x = next;
133*2d543d20SAndroid Build Coastguard Worker 	}
134*2d543d20SAndroid Build Coastguard Worker }
135*2d543d20SAndroid Build Coastguard Worker 
136*2d543d20SAndroid Build Coastguard Worker /* Get a conditional node from a avrule_decl with the same expression.
137*2d543d20SAndroid Build Coastguard Worker  * 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*2d543d20SAndroid Build Coastguard Worker cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl,
139*2d543d20SAndroid Build Coastguard Worker 				cond_list_t * cond)
140*2d543d20SAndroid Build Coastguard Worker {
141*2d543d20SAndroid Build Coastguard Worker 	cond_list_t *result;
142*2d543d20SAndroid Build Coastguard Worker 	int was_created;
143*2d543d20SAndroid Build Coastguard Worker 	result = cond_node_find(p, cond, decl->cond_list, &was_created);
144*2d543d20SAndroid Build Coastguard Worker 	if (result != NULL && was_created) {
145*2d543d20SAndroid Build Coastguard Worker 		result->next = decl->cond_list;
146*2d543d20SAndroid Build Coastguard Worker 		decl->cond_list = result;
147*2d543d20SAndroid Build Coastguard Worker 	}
148*2d543d20SAndroid Build Coastguard Worker 	return result;
149*2d543d20SAndroid Build Coastguard Worker }
150*2d543d20SAndroid Build Coastguard Worker 
151*2d543d20SAndroid Build Coastguard Worker /* Look up an identifier in a policy's scoping table.  If it is there,
152*2d543d20SAndroid Build Coastguard Worker  * marked as SCOPE_DECL, and any of its declaring block has been enabled,
153*2d543d20SAndroid Build Coastguard Worker  * then return 1.  Otherwise return 0. Can only be called after the
154*2d543d20SAndroid Build Coastguard Worker  * decl_val_to_struct index has been created */
is_id_enabled(const char * id,const policydb_t * p,int symbol_table)155*2d543d20SAndroid Build Coastguard Worker int is_id_enabled(const char *id, const policydb_t * p, int symbol_table)
156*2d543d20SAndroid Build Coastguard Worker {
157*2d543d20SAndroid Build Coastguard Worker 	const scope_datum_t *scope =
158*2d543d20SAndroid Build Coastguard Worker 	    (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id);
159*2d543d20SAndroid Build Coastguard Worker 	const avrule_decl_t *decl;
160*2d543d20SAndroid Build Coastguard Worker 	uint32_t len;
161*2d543d20SAndroid Build Coastguard Worker 
162*2d543d20SAndroid Build Coastguard Worker 	if (scope == NULL) {
163*2d543d20SAndroid Build Coastguard Worker 		return 0;
164*2d543d20SAndroid Build Coastguard Worker 	}
165*2d543d20SAndroid Build Coastguard Worker 	if (scope->scope != SCOPE_DECL) {
166*2d543d20SAndroid Build Coastguard Worker 		return 0;
167*2d543d20SAndroid Build Coastguard Worker 	}
168*2d543d20SAndroid Build Coastguard Worker 
169*2d543d20SAndroid Build Coastguard Worker 	len = scope->decl_ids_len;
170*2d543d20SAndroid Build Coastguard Worker 	if (len < 1) {
171*2d543d20SAndroid Build Coastguard Worker 		return 0;
172*2d543d20SAndroid Build Coastguard Worker 	}
173*2d543d20SAndroid Build Coastguard Worker 
174*2d543d20SAndroid Build Coastguard Worker 	if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) {
175*2d543d20SAndroid Build Coastguard Worker 		uint32_t i;
176*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < len; i++) {
177*2d543d20SAndroid Build Coastguard Worker 			decl = p->decl_val_to_struct[scope->decl_ids[i] - 1];
178*2d543d20SAndroid Build Coastguard Worker 			if (decl != NULL && decl->enabled) {
179*2d543d20SAndroid Build Coastguard Worker 				return 1;
180*2d543d20SAndroid Build Coastguard Worker 			}
181*2d543d20SAndroid Build Coastguard Worker 		}
182*2d543d20SAndroid Build Coastguard Worker 	} else {
183*2d543d20SAndroid Build Coastguard Worker 		decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1];
184*2d543d20SAndroid Build Coastguard Worker 		if (decl != NULL && decl->enabled) {
185*2d543d20SAndroid Build Coastguard Worker 			return 1;
186*2d543d20SAndroid Build Coastguard Worker 		}
187*2d543d20SAndroid Build Coastguard Worker 	}
188*2d543d20SAndroid Build Coastguard Worker 
189*2d543d20SAndroid Build Coastguard Worker 	return 0;
190*2d543d20SAndroid Build Coastguard Worker }
191*2d543d20SAndroid Build Coastguard Worker 
192*2d543d20SAndroid Build Coastguard Worker /* Check if a particular permission is present within the given class.
193*2d543d20SAndroid Build Coastguard Worker  * Whether the class is enabled is NOT checked.
194*2d543d20SAndroid Build Coastguard Worker  * Returns 1 if permission is present, 0 otherwise */
is_perm_existent(const class_datum_t * cladatum,const char * perm_id)195*2d543d20SAndroid Build Coastguard Worker int is_perm_existent(const class_datum_t *cladatum, const char *perm_id)
196*2d543d20SAndroid Build Coastguard Worker {
197*2d543d20SAndroid Build Coastguard Worker 	const perm_datum_t *perm;
198*2d543d20SAndroid Build Coastguard Worker 
199*2d543d20SAndroid Build Coastguard Worker 	perm = hashtab_search(cladatum->permissions.table, perm_id);
200*2d543d20SAndroid Build Coastguard Worker 	if (perm == NULL && cladatum->comdatum != 0) {
201*2d543d20SAndroid Build Coastguard Worker 		/* permission was not in this class.  before giving
202*2d543d20SAndroid Build Coastguard Worker 		 * up, check the class's parent */
203*2d543d20SAndroid Build Coastguard Worker 		perm =
204*2d543d20SAndroid Build Coastguard Worker 		    hashtab_search(cladatum->comdatum->permissions.table,
205*2d543d20SAndroid Build Coastguard Worker 				   perm_id);
206*2d543d20SAndroid Build Coastguard Worker 	}
207*2d543d20SAndroid Build Coastguard Worker 	if (perm == NULL) {
208*2d543d20SAndroid Build Coastguard Worker 		return 0;
209*2d543d20SAndroid Build Coastguard Worker 	}
210*2d543d20SAndroid Build Coastguard Worker 	return 1;
211*2d543d20SAndroid Build Coastguard Worker }
212