• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		if (d1 == d2) {
73 			return CIL_TRUE;
74 		} else if (ebitmap_match_any(a1->types, a2->types)) {
75 			return CIL_TRUE;
76 		}
77 	}
78 	return CIL_FALSE;
79 }
80 
cil_type_matches(ebitmap_t * matches,struct cil_symtab_datum * d1,struct cil_symtab_datum * d2)81 static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2)
82 {
83 	int rc = SEPOL_OK;
84 	enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor;
85 	enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor;
86 
87 	if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
88 		struct cil_type *t1 = (struct cil_type *)d1;
89 		struct cil_type *t2 = (struct cil_type *)d2;
90 		if (t1->value == t2->value) {
91 			ebitmap_set_bit(matches, t1->value, 1);
92 		}
93 	} else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
94 		struct cil_typeattribute *a = (struct cil_typeattribute *)d1;
95 		struct cil_type *t = (struct cil_type *)d2;
96 		if (ebitmap_get_bit(a->types, t->value)) {
97 			ebitmap_set_bit(matches, t->value, 1);
98 		}
99 	} else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
100 		struct cil_type *t = (struct cil_type *)d1;
101 		struct cil_typeattribute *a = (struct cil_typeattribute *)d2;
102 		if (ebitmap_get_bit(a->types, t->value)) {
103 			ebitmap_set_bit(matches, t->value, 1);
104 		}
105 	} else {
106 		/* Both are attributes */
107 		struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
108 		struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
109 		rc = ebitmap_and(matches, a1->types, a2->types);
110 	}
111 
112 	return rc;
113 }
114 
115 /* s1 is the src type that is matched with a self
116  * s2, and t2 are the source and type of the other rule
117  */
cil_self_match_any(struct cil_symtab_datum * s1,struct cil_symtab_datum * s2,struct cil_symtab_datum * t2)118 static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
119 {
120 	int rc;
121 	struct cil_tree_node *n1 = s1->nodes->head->data;
122 	if (n1->flavor != CIL_TYPEATTRIBUTE) {
123 		rc = cil_type_match_any(s1, t2);
124 	} else {
125 		struct cil_typeattribute *a = (struct cil_typeattribute *)s1;
126 		ebitmap_t map;
127 		ebitmap_init(&map);
128 		rc = cil_type_matches(&map, s2, t2);
129 		if (rc < 0) {
130 			ebitmap_destroy(&map);
131 			goto exit;
132 		}
133 		if (map.node == NULL) {
134 			rc = CIL_FALSE;
135 			goto exit;
136 		}
137 		rc = ebitmap_match_any(&map, a->types);
138 		ebitmap_destroy(&map);
139 	}
140 
141 exit:
142 	return rc;
143 }
144 
cil_classperms_match_any(struct cil_classperms * cp1,struct cil_classperms * cp2)145 static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2)
146 {
147 	struct cil_class *c1 = cp1->class;
148 	struct cil_class *c2 = cp2->class;
149 	struct cil_list_item *i1, *i2;
150 
151 	if (&c1->datum != &c2->datum) return CIL_FALSE;
152 
153 	cil_list_for_each(i1, cp1->perms) {
154 		struct cil_perm *p1 = i1->data;
155 		cil_list_for_each(i2, cp2->perms) {
156 			struct cil_perm *p2 = i2->data;
157 			if (&p1->datum == &p2->datum) return CIL_TRUE;
158 		}
159 	}
160 	return CIL_FALSE;
161 }
162 
__cil_classperms_list_match_any(struct cil_classperms * cp1,struct cil_list * cpl2)163 static int __cil_classperms_list_match_any(struct cil_classperms *cp1, struct cil_list *cpl2)
164 {
165 	int rc;
166 	struct cil_list_item *curr;
167 
168 	cil_list_for_each(curr, cpl2) {
169 		if (curr->flavor == CIL_CLASSPERMS) {
170 			struct cil_classperms *cp = curr->data;
171 			if (FLAVOR(cp->class) == CIL_CLASS) {
172 				rc = cil_classperms_match_any(cp1, cp);
173 				if (rc == CIL_TRUE) return CIL_TRUE;
174 			} else { /* MAP */
175 				struct cil_list_item *i = NULL;
176 				cil_list_for_each(i, cp->perms) {
177 					struct cil_perm *cmp = i->data;
178 					rc = __cil_classperms_list_match_any(cp1, cmp->classperms);
179 					if (rc == CIL_TRUE) return CIL_TRUE;
180 				}
181 			}
182 		} else { /* SET */
183 			struct cil_classperms_set *cp_set = curr->data;
184 			struct cil_classpermission *cp = cp_set->set;
185 			rc = __cil_classperms_list_match_any(cp1, cp->classperms);
186 			if (rc == CIL_TRUE) return CIL_TRUE;
187 		}
188 	}
189 	return CIL_FALSE;
190 }
191 
cil_classperms_list_match_any(struct cil_list * cpl1,struct cil_list * cpl2)192 static int cil_classperms_list_match_any(struct cil_list *cpl1, struct cil_list *cpl2)
193 {
194 	int rc;
195 	struct cil_list_item *curr;
196 
197 	cil_list_for_each(curr, cpl1) {
198 		if (curr->flavor == CIL_CLASSPERMS) {
199 			struct cil_classperms *cp = curr->data;
200 			if (FLAVOR(cp->class) == CIL_CLASS) {
201 				rc = __cil_classperms_list_match_any(cp, cpl2);
202 				if (rc == CIL_TRUE) return CIL_TRUE;
203 			} else { /* MAP */
204 				struct cil_list_item *i = NULL;
205 				cil_list_for_each(i, cp->perms) {
206 					struct cil_perm *cmp = i->data;
207 					rc = cil_classperms_list_match_any(cmp->classperms, cpl2);
208 					if (rc == CIL_TRUE) return CIL_TRUE;
209 				}
210 			}
211 		} else { /* SET */
212 			struct cil_classperms_set *cp_set = curr->data;
213 			struct cil_classpermission *cp = cp_set->set;
214 			rc = cil_classperms_list_match_any(cp->classperms, cpl2);
215 			if (rc == CIL_TRUE) return CIL_TRUE;
216 		}
217 	}
218 	return CIL_FALSE;
219 }
220 
__add_classes_from_classperms_list(struct cil_list * classperms,struct cil_list * class_list)221 static void __add_classes_from_classperms_list(struct cil_list *classperms, struct cil_list *class_list)
222 {
223 	struct cil_list_item *curr;
224 
225 	cil_list_for_each(curr, classperms) {
226 		if (curr->flavor == CIL_CLASSPERMS) {
227 			struct cil_classperms *cp = curr->data;
228 			if (FLAVOR(cp->class) == CIL_CLASS) {
229 				cil_list_append(class_list, CIL_CLASS, cp->class);
230 			} else { /* MAP */
231 				struct cil_list_item *i = NULL;
232 				cil_list_for_each(i, cp->perms) {
233 					struct cil_perm *cmp = i->data;
234 					__add_classes_from_classperms_list(cmp->classperms, class_list);
235 				}
236 			}
237 		} else { /* SET */
238 			struct cil_classperms_set *cp_set = curr->data;
239 			struct cil_classpermission *cp = cp_set->set;
240 			__add_classes_from_classperms_list(cp->classperms, class_list);
241 		}
242 	}
243 }
244 
__add_classes_from_map_perms(hashtab_key_t k,hashtab_datum_t d,void * args)245 static int __add_classes_from_map_perms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
246 {
247 	struct cil_list *class_list = args;
248 	struct cil_perm *cmp = (struct cil_perm *)d;
249 
250 	__add_classes_from_classperms_list(cmp->classperms, class_list);
251 
252 	return SEPOL_OK;
253 }
254 
cil_expand_class(struct cil_class * class)255 struct cil_list *cil_expand_class(struct cil_class *class)
256 {
257 	struct cil_list *class_list;
258 
259 	cil_list_init(&class_list, CIL_CLASS);
260 
261 	if (FLAVOR(class) == CIL_CLASS) {
262 		cil_list_append(class_list, CIL_CLASS, class);
263 	} else { /* MAP */
264 		cil_symtab_map(&class->perms, __add_classes_from_map_perms, class_list);
265 	}
266 
267 	return class_list;
268 }
269 
cil_permissionx_match_any(struct cil_permissionx * px1,struct cil_permissionx * px2)270 static int cil_permissionx_match_any(struct cil_permissionx *px1, struct cil_permissionx *px2)
271 {
272 	int rc = CIL_FALSE;
273 	struct cil_list *cl1 = NULL;
274 	struct cil_list *cl2 = NULL;
275 
276 	if (px1->kind != px2->kind) goto exit;
277 
278 	if (!ebitmap_match_any(px1->perms, px2->perms)) goto exit;
279 
280 	cl1 = cil_expand_class(px1->obj);
281 	cl2 = cil_expand_class(px2->obj);
282 
283 	if (!cil_list_match_any(cl1, cl2)) goto exit;
284 
285 	rc = CIL_TRUE;
286 
287 exit:
288 	cil_list_destroy(&cl1, CIL_FALSE);
289 	cil_list_destroy(&cl2, CIL_FALSE);
290 
291 	return rc;
292 }
293 
cil_find_matching_avrule(struct cil_tree_node * node,struct cil_avrule * avrule,struct cil_avrule * target,struct cil_list * matching,int match_self)294 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)
295 {
296 	int rc = SEPOL_OK;
297 	struct cil_symtab_datum *s1 = avrule->src;
298 	struct cil_symtab_datum *t1 = avrule->tgt;
299 	struct cil_symtab_datum *s2 = target->src;
300 	struct cil_symtab_datum *t2 = target->tgt;
301 
302 	if (match_self != CIL_TRUE && avrule == target) goto exit;
303 
304 	if (avrule->rule_kind != target->rule_kind) goto exit;
305 
306 	if (avrule->is_extended != target->is_extended) goto exit;
307 
308 	if (!cil_type_match_any(s1, s2)) goto exit;
309 
310 	if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) {
311 		if (!cil_type_match_any(t1, t2)) goto exit;
312 	} else {
313 		if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) {
314 			/* The earlier check whether s1 and s2 matches is all that is needed */
315 		} else if (t1->fqn == CIL_KEY_SELF) {
316 			rc = cil_self_match_any(s1, s2, t2);
317 			if (rc < 0) {
318 				goto exit;
319 			} else if (rc == CIL_FALSE) {
320 				rc = SEPOL_OK;
321 				goto exit;
322 			}
323 		} else if (t2->fqn == CIL_KEY_SELF) {
324 			rc = cil_self_match_any(s2, s1, t1);
325 			if (rc < 0) {
326 				goto exit;
327 			} else if (rc == CIL_FALSE) {
328 				rc = SEPOL_OK;
329 				goto exit;
330 			}
331 		}
332 	}
333 
334 	if (!target->is_extended) {
335 		if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) {
336 			cil_list_append(matching, CIL_NODE, node);
337 		}
338 	} else {
339 		if (cil_permissionx_match_any(avrule->perms.x.permx, target->perms.x.permx)) {
340 			cil_list_append(matching, CIL_NODE, node);
341 		}
342 	}
343 
344 	rc = SEPOL_OK;
345 
346 exit:
347 	return rc;
348 }
349 
__cil_find_matching_avrule_in_ast(struct cil_tree_node * node,uint32_t * finished,void * extra_args)350 static int __cil_find_matching_avrule_in_ast(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
351 {
352 	int rc = SEPOL_OK;
353 	struct cil_args_find *args = extra_args;
354 
355 	if (node->flavor == CIL_BLOCK) {
356 		struct cil_block *blk = node->data;
357 		if (blk->is_abstract == CIL_TRUE) {
358 			*finished = CIL_TREE_SKIP_HEAD;
359 			goto exit;
360 		}
361 	} else if (node->flavor == CIL_MACRO) {
362 		*finished = CIL_TREE_SKIP_HEAD;
363 		goto exit;
364 	} else if (node->flavor == CIL_AVRULE || node->flavor == CIL_AVRULEX) {
365 		if (node->flavor == args->flavor) {
366 			rc = cil_find_matching_avrule(node, node->data, args->target, args->matching, args->match_self);
367 		}
368 	}
369 
370 exit:
371 	return rc;
372 }
373 
cil_find_matching_avrule_in_ast(struct cil_tree_node * current,enum cil_flavor flavor,void * target,struct cil_list * matching,int match_self)374 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)
375 {
376 	int rc;
377 	struct cil_args_find args;
378 
379 	args.flavor = flavor;
380 	args.target = target;
381 	args.matching = matching;
382 	args.match_self = match_self;
383 
384 	rc = cil_tree_walk(current, __cil_find_matching_avrule_in_ast, NULL, NULL, &args);
385 	if (rc) {
386 		cil_log(CIL_ERR, "An error occurred while searching for avrule in AST\n");
387 	}
388 
389 	return rc;
390 }
391