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