1 /*
2 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * The views and conclusions contained in the software and documentation are those
26 * of the authors and should not be interpreted as representing official policies,
27 * either expressed or implied, of Tresys Technology, LLC.
28 */
29
30 #include <sepol/policydb/ebitmap.h>
31
32 #include "cil_internal.h"
33 #include "cil_flavor.h"
34 #include "cil_list.h"
35 #include "cil_log.h"
36 #include "cil_symtab.h"
37
38 struct cil_args_find {
39 enum cil_flavor flavor;
40 void *target;
41 struct cil_list *matching;
42 int match_self;
43 };
44
cil_type_match_any(struct cil_symtab_datum * d1,struct cil_symtab_datum * d2)45 static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_datum *d2)
46 {
47 enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor;
48 enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor;
49
50 if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
51 struct cil_type *t1 = (struct cil_type *)d1;
52 struct cil_type *t2 = (struct cil_type *)d2;
53 if (t1->value == t2->value) {
54 return CIL_TRUE;
55 }
56 } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
57 struct cil_typeattribute *a = (struct cil_typeattribute *)d1;
58 struct cil_type *t = (struct cil_type *)d2;
59 if (ebitmap_get_bit(a->types, t->value)) {
60 return CIL_TRUE;
61 }
62 } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
63 struct cil_type *t = (struct cil_type *)d1;
64 struct cil_typeattribute *a = (struct cil_typeattribute *)d2;
65 if (ebitmap_get_bit(a->types, t->value)) {
66 return CIL_TRUE;
67 }
68 } else {
69 /* Both are attributes */
70 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
71 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
72 return ebitmap_match_any(a1->types, a2->types);
73 }
74 return CIL_FALSE;
75 }
76
cil_type_matches(ebitmap_t * matches,struct cil_symtab_datum * d1,struct cil_symtab_datum * d2)77 static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2)
78 {
79 int rc = SEPOL_OK;
80 enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor;
81 enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor;
82
83 if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
84 struct cil_type *t1 = (struct cil_type *)d1;
85 struct cil_type *t2 = (struct cil_type *)d2;
86 if (t1->value == t2->value) {
87 ebitmap_set_bit(matches, t1->value, 1);
88 }
89 } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
90 struct cil_typeattribute *a = (struct cil_typeattribute *)d1;
91 struct cil_type *t = (struct cil_type *)d2;
92 if (ebitmap_get_bit(a->types, t->value)) {
93 ebitmap_set_bit(matches, t->value, 1);
94 }
95 } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
96 struct cil_type *t = (struct cil_type *)d1;
97 struct cil_typeattribute *a = (struct cil_typeattribute *)d2;
98 if (ebitmap_get_bit(a->types, t->value)) {
99 ebitmap_set_bit(matches, t->value, 1);
100 }
101 } else {
102 /* Both are attributes */
103 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
104 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
105 rc = ebitmap_and(matches, a1->types, a2->types);
106 }
107
108 return rc;
109 }
110
111 /* s1 is the src type that is matched with a self
112 * s2, and t2 are the source and type of the other rule
113 */
cil_self_match_any(struct cil_symtab_datum * s1,struct cil_symtab_datum * s2,struct cil_symtab_datum * t2)114 static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
115 {
116 int rc;
117 struct cil_tree_node *n1 = s1->nodes->head->data;
118 if (n1->flavor != CIL_TYPEATTRIBUTE) {
119 rc = cil_type_match_any(s1, t2);
120 } else {
121 struct cil_typeattribute *a = (struct cil_typeattribute *)s1;
122 ebitmap_t map;
123 ebitmap_init(&map);
124 rc = cil_type_matches(&map, s2, t2);
125 if (rc < 0) {
126 ebitmap_destroy(&map);
127 goto exit;
128 }
129 if (map.node == NULL) {
130 rc = CIL_FALSE;
131 goto exit;
132 }
133 rc = ebitmap_match_any(&map, a->types);
134 ebitmap_destroy(&map);
135 }
136
137 exit:
138 return rc;
139 }
140
cil_classperms_match_any(struct cil_classperms * cp1,struct cil_classperms * cp2)141 static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2)
142 {
143 struct cil_class *c1 = cp1->class;
144 struct cil_class *c2 = cp2->class;
145 struct cil_list_item *i1, *i2;
146
147 if (&c1->datum != &c2->datum) return CIL_FALSE;
148
149 cil_list_for_each(i1, cp1->perms) {
150 struct cil_perm *p1 = i1->data;
151 cil_list_for_each(i2, cp2->perms) {
152 struct cil_perm *p2 = i2->data;
153 if (&p1->datum == &p2->datum) return CIL_TRUE;
154 }
155 }
156 return CIL_FALSE;
157 }
158
__cil_classperms_list_match_any(struct cil_classperms * cp1,struct cil_list * cpl2)159 static int __cil_classperms_list_match_any(struct cil_classperms *cp1, struct cil_list *cpl2)
160 {
161 int rc;
162 struct cil_list_item *curr;
163
164 cil_list_for_each(curr, cpl2) {
165 if (curr->flavor == CIL_CLASSPERMS) {
166 struct cil_classperms *cp = curr->data;
167 if (FLAVOR(cp->class) == CIL_CLASS) {
168 rc = cil_classperms_match_any(cp1, cp);
169 if (rc == CIL_TRUE) return CIL_TRUE;
170 } else { /* MAP */
171 struct cil_list_item *i = NULL;
172 cil_list_for_each(i, cp->perms) {
173 struct cil_perm *cmp = i->data;
174 rc = __cil_classperms_list_match_any(cp1, cmp->classperms);
175 if (rc == CIL_TRUE) return CIL_TRUE;
176 }
177 }
178 } else { /* SET */
179 struct cil_classperms_set *cp_set = curr->data;
180 struct cil_classpermission *cp = cp_set->set;
181 rc = __cil_classperms_list_match_any(cp1, cp->classperms);
182 if (rc == CIL_TRUE) return CIL_TRUE;
183 }
184 }
185 return CIL_FALSE;
186 }
187
cil_classperms_list_match_any(struct cil_list * cpl1,struct cil_list * cpl2)188 static int cil_classperms_list_match_any(struct cil_list *cpl1, struct cil_list *cpl2)
189 {
190 int rc;
191 struct cil_list_item *curr;
192
193 cil_list_for_each(curr, cpl1) {
194 if (curr->flavor == CIL_CLASSPERMS) {
195 struct cil_classperms *cp = curr->data;
196 if (FLAVOR(cp->class) == CIL_CLASS) {
197 rc = __cil_classperms_list_match_any(cp, cpl2);
198 if (rc == CIL_TRUE) return CIL_TRUE;
199 } else { /* MAP */
200 struct cil_list_item *i = NULL;
201 cil_list_for_each(i, cp->perms) {
202 struct cil_perm *cmp = i->data;
203 rc = cil_classperms_list_match_any(cmp->classperms, cpl2);
204 if (rc == CIL_TRUE) return CIL_TRUE;
205 }
206 }
207 } else { /* SET */
208 struct cil_classperms_set *cp_set = curr->data;
209 struct cil_classpermission *cp = cp_set->set;
210 rc = cil_classperms_list_match_any(cp->classperms, cpl2);
211 if (rc == CIL_TRUE) return CIL_TRUE;
212 }
213 }
214 return CIL_FALSE;
215 }
216
__add_classes_from_classperms_list(struct cil_list * classperms,struct cil_list * class_list)217 static void __add_classes_from_classperms_list(struct cil_list *classperms, struct cil_list *class_list)
218 {
219 struct cil_list_item *curr;
220
221 cil_list_for_each(curr, classperms) {
222 if (curr->flavor == CIL_CLASSPERMS) {
223 struct cil_classperms *cp = curr->data;
224 if (FLAVOR(cp->class) == CIL_CLASS) {
225 cil_list_append(class_list, CIL_CLASS, cp->class);
226 } else { /* MAP */
227 struct cil_list_item *i = NULL;
228 cil_list_for_each(i, cp->perms) {
229 struct cil_perm *cmp = i->data;
230 __add_classes_from_classperms_list(cmp->classperms, class_list);
231 }
232 }
233 } else { /* SET */
234 struct cil_classperms_set *cp_set = curr->data;
235 struct cil_classpermission *cp = cp_set->set;
236 __add_classes_from_classperms_list(cp->classperms, class_list);
237 }
238 }
239 }
240
__add_classes_from_map_perms(hashtab_key_t k,hashtab_datum_t d,void * args)241 static int __add_classes_from_map_perms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
242 {
243 struct cil_list *class_list = args;
244 struct cil_perm *cmp = (struct cil_perm *)d;
245
246 __add_classes_from_classperms_list(cmp->classperms, class_list);
247
248 return SEPOL_OK;
249 }
250
cil_expand_class(struct cil_class * class)251 struct cil_list *cil_expand_class(struct cil_class *class)
252 {
253 struct cil_list *class_list;
254
255 cil_list_init(&class_list, CIL_CLASS);
256
257 if (FLAVOR(class) == CIL_CLASS) {
258 cil_list_append(class_list, CIL_CLASS, class);
259 } else { /* MAP */
260 cil_symtab_map(&class->perms, __add_classes_from_map_perms, class_list);
261 }
262
263 return class_list;
264 }
265
cil_permissionx_match_any(struct cil_permissionx * px1,struct cil_permissionx * px2)266 static int cil_permissionx_match_any(struct cil_permissionx *px1, struct cil_permissionx *px2)
267 {
268 int rc = CIL_FALSE;
269 struct cil_list *cl1 = NULL;
270 struct cil_list *cl2 = NULL;
271
272 if (px1->kind != px2->kind) goto exit;
273
274 if (!ebitmap_match_any(px1->perms, px2->perms)) goto exit;
275
276 cl1 = cil_expand_class(px1->obj);
277 cl2 = cil_expand_class(px2->obj);
278
279 if (!cil_list_match_any(cl1, cl2)) goto exit;
280
281 rc = CIL_TRUE;
282
283 exit:
284 cil_list_destroy(&cl1, CIL_FALSE);
285 cil_list_destroy(&cl2, CIL_FALSE);
286
287 return rc;
288 }
289
cil_find_matching_avrule(struct cil_tree_node * node,struct cil_avrule * avrule,struct cil_avrule * target,struct cil_list * matching,int match_self)290 int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrule *avrule, struct cil_avrule *target, struct cil_list *matching, int match_self)
291 {
292 int rc = SEPOL_OK;
293 struct cil_symtab_datum *s1 = avrule->src;
294 struct cil_symtab_datum *t1 = avrule->tgt;
295 struct cil_symtab_datum *s2 = target->src;
296 struct cil_symtab_datum *t2 = target->tgt;
297
298 if (match_self != CIL_TRUE && avrule == target) goto exit;
299
300 if (avrule->rule_kind != target->rule_kind) goto exit;
301
302 if (avrule->is_extended != target->is_extended) goto exit;
303
304 if (!cil_type_match_any(s1, s2)) goto exit;
305
306 if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) {
307 if (!cil_type_match_any(t1, t2)) goto exit;
308 } else {
309 if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) {
310 /* The earlier check whether s1 and s2 matches is all that is needed */
311 } else if (t1->fqn == CIL_KEY_SELF) {
312 rc = cil_self_match_any(s1, s2, t2);
313 if (rc < 0) {
314 goto exit;
315 } else if (rc == CIL_FALSE) {
316 rc = SEPOL_OK;
317 goto exit;
318 }
319 } else if (t2->fqn == CIL_KEY_SELF) {
320 rc = cil_self_match_any(s2, s1, t1);
321 if (rc < 0) {
322 goto exit;
323 } else if (rc == CIL_FALSE) {
324 rc = SEPOL_OK;
325 goto exit;
326 }
327 }
328 }
329
330 if (!target->is_extended) {
331 if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) {
332 cil_list_append(matching, CIL_NODE, node);
333 }
334 } else {
335 if (cil_permissionx_match_any(avrule->perms.x.permx, target->perms.x.permx)) {
336 cil_list_append(matching, CIL_NODE, node);
337 }
338 }
339
340 rc = SEPOL_OK;
341
342 exit:
343 return rc;
344 }
345
__cil_find_matching_avrule_in_ast(struct cil_tree_node * node,uint32_t * finished,void * extra_args)346 static int __cil_find_matching_avrule_in_ast(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
347 {
348 int rc = SEPOL_OK;
349 struct cil_args_find *args = extra_args;
350
351 if (node->flavor == CIL_BLOCK) {
352 struct cil_block *blk = node->data;
353 if (blk->is_abstract == CIL_TRUE) {
354 *finished = CIL_TREE_SKIP_HEAD;
355 goto exit;
356 }
357 } else if (node->flavor == CIL_MACRO) {
358 *finished = CIL_TREE_SKIP_HEAD;
359 goto exit;
360 } else if (node->flavor == CIL_AVRULE || node->flavor == CIL_AVRULEX) {
361 if (node->flavor == args->flavor) {
362 rc = cil_find_matching_avrule(node, node->data, args->target, args->matching, args->match_self);
363 }
364 }
365
366 exit:
367 return rc;
368 }
369
cil_find_matching_avrule_in_ast(struct cil_tree_node * current,enum cil_flavor flavor,void * target,struct cil_list * matching,int match_self)370 int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self)
371 {
372 int rc;
373 struct cil_args_find args;
374
375 args.flavor = flavor;
376 args.target = target;
377 args.matching = matching;
378 args.match_self = match_self;
379
380 rc = cil_tree_walk(current, __cil_find_matching_avrule_in_ast, NULL, NULL, &args);
381 if (rc) {
382 cil_log(CIL_ERR, "An error occured while searching for avrule in AST\n");
383 }
384
385 return rc;
386 }
387