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 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 uint32_t i;
160 if (scope == NULL) {
161 return 0;
162 }
163 if (scope->scope != SCOPE_DECL) {
164 return 0;
165 }
166 for (i = 0; i < scope->decl_ids_len; i++) {
167 avrule_decl_t *decl =
168 p->decl_val_to_struct[scope->decl_ids[i] - 1];
169 if (decl != NULL && decl->enabled) {
170 return 1;
171 }
172 }
173 return 0;
174 }
175
176 /* Check if a particular permission is present within the given class,
177 * and that the class is enabled. Returns 1 if both conditions are
178 * 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)179 int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p)
180 {
181 class_datum_t *cladatum;
182 perm_datum_t *perm;
183 if (!is_id_enabled(class_id, p, SYM_CLASSES)) {
184 return 0;
185 }
186 cladatum =
187 (class_datum_t *) hashtab_search(p->p_classes.table, class_id);
188 if (cladatum == NULL) {
189 return 0;
190 }
191 perm = hashtab_search(cladatum->permissions.table, perm_id);
192 if (perm == NULL && cladatum->comdatum != 0) {
193 /* permission was not in this class. before giving
194 * up, check the class's parent */
195 perm =
196 hashtab_search(cladatum->comdatum->permissions.table,
197 perm_id);
198 }
199 if (perm == NULL) {
200 return 0;
201 }
202 return 1;
203 }
204